Arduino opens a window when the air in a room is exhaled
Automatic window opening by Arduino
Components and supplies
1
ULN2003 driver
1
OLED display 128x32
1
Stepper motor 28BYJ-48 12V
1
Arduino Nano R3
Project description
Code
CO2CubeWindow
arduino
Main loop
1 2/* 3 * Receives the signal from MyCO2Cube and opens / closes a window 4 */ 5 6#define releaseButton 3 7 8bool openWindow = false; 9bool released = false; 10volatile bool releaseButtonPushed = false; 11bool set = false; 12bool locked = false; 13unsigned long lockTime, infoTime; 14int lockedInfo; 15 16void setup() { 17 InitializeOledDisplay(); 18 InitializeMyClock(); //contains InitializeShiftRegister(); 19 InitializeReceiver(); 20 InitializeStepMotor(); 21 InitializeFan(); 22 InitializeCO2CubeWindow(); 23 DisplayText("SETTING", false, true); 24} 25 26void InitializeCO2CubeWindow() { 27 pinMode(releaseButton, INPUT_PULLUP); 28 attachInterrupt(digitalPinToInterrupt(releaseButton), ReleaseButtonPushed, LOW); 29 lockTime = millis(); 30} 31 32void loop() { 33 if (set) { 34 GetSignal(); 35 36 if (releaseButtonPushed) { //switches between Normal, Release and Locked mode 37 detachInterrupt(digitalPinToInterrupt(releaseButton)); 38 releaseButtonPushed = false; 39 if (locked) { 40 locked = false; 41 TurnMyClockOFF(); 42 DisplayOpenClose(); 43 } 44 else { 45 released = !released; 46 if ((millis() - lockTime) < 800) locked = true; 47 lockTime = millis(); 48 if (locked) { 49 DisplayText("LOCKED", false, true); 50 released = false; 51 infoTime = millis(); 52 lockedInfo = 0; 53 } else { 54 if (released) DisplayText("RELEASE", false, true); 55 else { 56 DisplayOpenClose(); 57 } 58 TurnMyClockOFF(); 59 } 60 } 61 delay(700); 62 attachInterrupt(digitalPinToInterrupt(releaseButton), ReleaseButtonPushed, LOW); 63 } 64 65 if (locked) { 66 CloseWindow(); 67 if (millis() - infoTime > 7000) { 68 DisplayLockedInfo(); //shows some statistics 69 infoTime = millis(); 70 } 71 } 72 else { 73 if (released) ReleaseWindow(); 74 else { 75 if (openWindow) OpenWindow(); 76 else CloseWindow(); 77 } 78 } 79 80 DisplayMyClock(); //shows the clock 81 } 82 else CloseWindow(); //sets device after turning on 83} 84 85void ReleaseButtonPushed() { 86 releaseButtonPushed = true; 87}
Receiver
arduino
Serves nRFL01 receiver
1 2/* 3 * nRF24L01 Receiver 4 */ 5 6#include <SPI.h> 7#include <nRF24L01.h> 8#include <RF24.h> 9 10RF24 receiver(9, 8); // CE, CSN 11const byte address[6] = "openw"; //address through which two modules communicate 12 13void InitializeReceiver() { 14 if (!receiver.begin()) { 15 DisplayText("ComERR", false, true); 16 while(1); 17 } 18 19 receiver.setPALevel(RF24_PA_MIN); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, and RF24_PA_max 20 receiver.setDataRate(RF24_250KBPS); //RF24_250KBPS, RF24_1MBPS, RF24_2MBPS 21 22 receiver.openReadingPipe(0, address); 23 receiver.startListening(); //Set module as receiver 24} 25 26void GetSignal() { 27 receiver.powerUp(); 28 if (receiver.available()) { 29 TurnFanOFF(); 30 TurnStepMotorOFF(); 31 TurnMyClockOFF(); 32 char text[32] = {0}; 33 receiver.read(&text, sizeof(text)); 34 if (strcmp(text,"open") == 0) { openWindow = true; RecordOpen(); if (!released && !locked) DisplayOpenClose(); } 35 if (strcmp(text,"close") == 0) { openWindow = false; if (!released && !locked) DisplayOpenClose(); } 36 DisplayText(text, true, false); 37 } 38}
ShiftRegister
arduino
Serves shift registers for the clock
1 2#define dataPin A2 //PIN 14 of 1 shift register 3#define latchPin A3 //PIN 12 of both shift registers 4#define clockPin A1 //PIN 11 of both shift registers 5#define resetPin 10 //PIN 10 of both shift registers 6 7/* 8 * 2 Shift registers 74HC595 for displaying the clock on the 7segment4digit display 9 * 10 * Q0 - PIN 15 of shift register I 11 * Q1-Q7 - PINS 1-7 of shift register I 12 * +5V - PIN 16 of shift register 13 * GND - PIN 8 of shift register 14 * PIN 9 of shift register I to PIN 14 of shift register II 15 * Both shift registers share latchPin, clockPin, resetPin 16 * 17 * MOSFET IRF520N: 18 * Gates to pin 1-4 of shift register II 19 * Sources to ground 20 * Drains do Digit1-Digit4 of 7segmet4digit display 21 */ 22 23void InitializeShiftRegister() { 24 DDRC |= B00001110; //pinMode(dataPin, OUTPUT); 25 //pinMode(clockPin, OUTPUT); 26 //pinMode(latchPin, OUTPUT); 27 DDRB |= B00000100; //pinMode(resetPin, OUTPUT); 28 ClearShiftRegister(); //digitalWrite(resetPin, HIGH); 29 //digitalWrite(latchPin, HIGH); 30} 31 32void SetShiftRegister(byte digitID, byte digitValue) { 33 PORTC &= B11110101; //digitalWrite(latchPin, LOW); 34 //digitalWrite(clockPin, LOW); 35 shiftOut(dataPin, clockPin, MSBFIRST, digitID); //shift out high byte, alternative: LSBFIRST / MSBFIRST 36 PORTC &= B11111101; //digitalWrite(clockPin, LOW); 37 shiftOut(dataPin, clockPin, MSBFIRST, digitValue); //shift out low byte, alternative: LSBFIRST / MSBFIRST 38 PORTC |= B00001000; //digitalWrite(latchPin, HIGH); 39} 40 41void ClearShiftRegister() { 42 PORTB &= B11111011; //digitalWrite(resetPin, LOW); 43 PORTB |= B00000100; //digitalWrite(resetPin, HIGH); 44 PORTC &= B11110111; //digitalWrite(latchPin, LOW); 45 PORTC |= B00001000; //digitalWrite(latchPin, HIGH); 46}
StepMotor
arduino
Serves stepper motor
1 2/* 3 * 12V Stepper motor 28BYJ-48 with ULN2003 driver 4 */ 5 6#include <Stepper.h> 7 8#define fullOpenWindowSteps 100000 9#define releaseSteps 15000 10#define closeButton 2 11#define isClosed ((PIND & B100) == 0) 12 13const int stepsPerRevolution = 2048; 14const int rpm = 14; 15long steps = fullOpenWindowSteps; 16bool wasOpen = false; 17 18Stepper stepMotor = Stepper(stepsPerRevolution, 4, 6, 5, 7); 19 20void InitializeStepMotor() { 21 pinMode(closeButton, INPUT_PULLUP); 22 stepMotor.setSpeed(rpm); 23 TurnStepMotorOFF(); 24} 25 26void CloseWindow() { 27 if (isClosed) { 28 if (wasOpen) { 29 for (int k = 0; k < 50; k++) stepMotor.step(-1); //noise reduction of the closeButton 30 wasOpen = false; 31 } 32 TurnStepMotorOFF(); 33 if (!locked) TurnDisplayOFF(); 34 TurnMyClockON(); 35 steps = 0; 36 if (!set) { 37 set = true; 38 DisplayText("READY", false, false); 39 } 40 } 41 else { 42 TurnMyClockOFF(); 43 if (steps > 0) steps--; 44 stepMotor.step(-1); 45 wasOpen = true; 46 } 47} 48 49void OpenWindow() { 50 if (steps < fullOpenWindowSteps) { 51 stepMotor.step(1); 52 steps++; 53 } 54 else { 55 TurnStepMotorOFF(); 56 TurnDisplayOFF(); 57 TurnMyClockON(); 58 TurnFanON(); 59 } 60} 61 62void ReleaseWindow() { 63 if (steps < releaseSteps) { 64 stepMotor.step(1); 65 steps++; 66 } 67 else { 68 TurnStepMotorOFF(); 69 TurnMyClockON(); 70 } 71} 72 73void TurnStepMotorOFF() { 74 PORTD &= B00001111; 75}
PIN_scheme
arduino
1 2/* Movement unit 3 PIN 0 - (RX0) 4 PIN 1 - (TX1) DO NOT USE! 5 PIN 2 - closeButton 6 PIN 3 - releaseButton (interrupt) 7 8 PIN 4 - INT1 stepper motor module ULN2003 9 PIN 5 - INT2 stepper motor module ULN2003 10 PIN 6 - INT3 stepper motor module ULN2003 11 PIN 7 - INT4 stepper motor module ULN2003 12 13 PIN 8 - CSN nRF24L01 14 PIN 9 - CE nRF24L01 15 PIN 10 - RESET PIN shiftregister I & II 16 PIN 11 - MOSI nRF24L01 17 PIN 12 - MISO nRF24L01 18 PIN 13 - SCK nRF24L01 19 20 PIN A0 - Fan MOSFET ON/OFF pin 21 PIN A1 - CLOCK PIN shiftregister I & II 22 PIN A2 - DATA PIN shiftregister I 23 PIN A3 - LATCH PIN shiftregister I & II 24 25 PIN A4 - (SDA) OLED display, DS1307 26 PIN A5 - (SCL) OLED display, DS1307 27 28 PIN A6 - (INPUT only) 29 PIN A7 - (INPUT only) 30 31 VCC 12V - Fan, StepMotor 32 VCC 5V - OLED display, DS1307, shift register I & II, RESET PIN of shift register I & II 33 VCC 3.3V - nRF24L01 34 GND - nRF24L01, StepMotor, Fan, OLED display, DS1307, closeButton, releaseButton 35*/
OledDisplay
arduino
Serves OledDisplay
1 2/* 3 * OLED display 128x32 4 * SDA - pin A4 5 * SCK - pin A5 6 * VCC - 3V-5V 7 */ 8 9#include <SPI.h> 10#include <Wire.h> 11#include <Adafruit_SSD1306.h> 12 13#define SCREEN_WIDTH 128 // OLED display width, in pixels 14#define SCREEN_HEIGHT 32 // OLED display height, in pixels 15 16#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 17 18Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 19 20bool displayON; 21 22void InitializeOledDisplay() { 23 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 24 while(1); 25 } 26 //display.ssd1306_command(SSD1306_SETCONTRAST); 27 //display.ssd1306_command(255); 28 //display.dim(true); // set contrast to 31 (reduces consumption to half) 29 //display.display(); 30 display.setTextColor(WHITE); 31 DisplayText("WELCOME", false, false); 32} 33 34#define vertical 12 35bool holdDisplay = false; 36char holdString[32]; 37 38void DisplayText(char text[32], bool showReceived, bool setHoldDisplay) { 39 display.clearDisplay(); 40 TurnDisplayON(); 41 42 if (setHoldDisplay) { 43 strcpy(holdString,text); 44 holdDisplay = true; 45 } else { 46 if (showReceived) { 47 display.setCursor(0,0); 48 display.setTextSize(1); 49 display.print("Received:"); 50 } 51 display.setCursor(0,vertical); 52 display.setTextSize(3); 53 display.print(text); 54 display.display(); 55 delay(2000); 56 } 57 58 if (holdDisplay) { 59 display.clearDisplay(); 60 display.setCursor(0,vertical); 61 display.setTextSize(3); 62 display.print(holdString); 63 display.display(); 64 } 65 else TurnDisplayOFF(); 66} 67 68void DisplayLockedInfo() { 69 if (lockedInfo == 0) { 70 display.clearDisplay(); 71 display.setCursor(0,0); 72 display.setTextSize(1); 73 display.print("Open at 22:00-6:00"); 74 display.setCursor(0,vertical); 75 display.setTextSize(3); 76 display.print(openCount); 77 display.print("x"); 78 display.display(); 79 } 80 81 if (lockedInfo == 1) { 82 display.clearDisplay(); 83 display.setCursor(0,0); 84 display.setTextSize(1); 85 display.print("Last open:"); 86 if (!openTimeNotSet) { 87 display.setCursor(0,vertical); 88 display.setTextSize(2); 89 display.print(lastTime.day()); 90 display.print("."); 91 display.print(lastTime.month()); 92 display.print("."); 93 display.print(lastTime.hour()); 94 display.print(":"); 95 display.print(lastTime.minute()); 96 } 97 display.display(); 98 } 99 100 if (lockedInfo == 2) DisplayText("LOCKED", false, true); 101 102 lockedInfo++; if (lockedInfo > 2) lockedInfo = 0; 103} 104 105void DisplayOpenClose() { 106 if (openWindow) DisplayText("OPEN", false, true); 107 else DisplayText("CLOSE", false, true); 108} 109 110void TurnDisplayOFF() { 111 if (displayON) { 112 displayON = false; 113 display.ssd1306_command(SSD1306_DISPLAYOFF); 114 } 115} 116 117void TurnDisplayON() { 118 if (!displayON) { 119 displayON = true; 120 display.ssd1306_command(SSD1306_DISPLAYON); 121 } 122}
MyClock
arduino
Displays the clock on 7segment4digit display
1 2/* 3 * MyClock for 7segment4digit display: 4 * 1st up row: D4, A, F, D3, D2, B 5 * 2nd bottom row: E, D, DP, C, G, D1 6 * 7 * DS1307 rtc module 8 * 9 * !!! VBAT PIN must be connected to +3V of the lithium battery 10 */ 11 12#include <Wire.h> 13#include "RTClib.h" 14 15RTC_DS1307 rtc; 16DateTime myTime, openTime, lastTime; 17bool openTimeNotSet = true; 18int openCount = 0; 19 20byte digitID[4] = {B00000010, B00000100, B00001000, B00010000}; //pins 1-4 of shift register II to Mosfet IRF520N gates, Byte = {0, 0, 0, D4, D3, D2, D1, 0} 21byte digitValue[4]; 22byte number[11] = {B11010111, B00010001, B11001101, B01011101, B00011011, B01011110, B11011110, B00010101, B11011111, B01011111, B00001000}; //pins 15 & 1-8 of shift register I, Byte = {E, D, DP, C, G, A, F, B} 23byte dotValue = B00100000; 24int k = 0; 25int minuteHigh, minuteLow, hourHigh, hourLow, lastMinute = 1; 26bool myClockON = true; 27unsigned long startTime, actualTime; 28 29void InitializeMyClock() { 30 InitializeShiftRegister(); 31 32 if (!rtc.begin()) { 33 DisplayText("ClkERR", false, true); 34 while(1); 35 } 36 //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //sets the RTC to the date & time from the PC 37 38 digitValue[0] = number[10]; 39 digitValue[1] = number[10]; 40 digitValue[2] = number[10] | dotValue; 41 digitValue[3] = number[10]; 42 TurnMyClockOFF(); 43 startTime = millis(); 44} 45 46void DisplayMyClock() { 47 if (myClockON) { 48 actualTime = millis(); 49 if (((actualTime - startTime) > 10000) || (actualTime < startTime)) { 50 GetTime(); 51 startTime = millis(); 52 } 53 SetShiftRegister(digitID[k], digitValue[k]); 54 k++; if (k > 3) k = 0; 55 } 56} 57 58void GetTime() { 59 myTime = rtc.now(); 60 if (myTime.minute() != lastMinute) { 61 lastMinute = myTime.minute(); 62 minuteHigh = lastMinute / 10; 63 minuteLow = lastMinute - (minuteHigh * 10); 64 hourHigh = myTime.hour() / 10; 65 hourLow = myTime.hour() - (hourHigh * 10); 66 digitValue[0] = number[minuteLow]; 67 digitValue[1] = number[minuteHigh]; 68 digitValue[2] = number[hourLow] | dotValue; 69 digitValue[3] = number[hourHigh]; 70 } 71} 72 73void RecordOpen() { 74 if (openTimeNotSet) { 75 openTime = rtc.now(); 76 openCount = 0; 77 openTimeNotSet = false; 78 } 79 80 lastTime = rtc.now(); 81 int actualHour = lastTime.hour(); 82 int actualDay = lastTime.day(); 83 int lastHour = openTime.hour(); 84 int lastDay = openTime.day(); 85 86 if ((actualHour >= 22) && (actualHour <= 6)) { 87 if ( ((actualHour >= 22) && (actualHour < 24) && ((lastHour < 22) || (lastDay < actualDay))) 88 || ((actualHour >= 0) && (actualHour <= 6) && ( ((lastHour < 22) && (lastDay < actualDay)) || ((lastHour >= 22) && (lastDay < (actualDay -1))) ) ) ) { 89 openTime = rtc.now(); 90 openCount = 0; 91 } 92 openCount++; 93 } 94} 95 96void TurnMyClockOFF() { 97 if (myClockON) { 98 ClearShiftRegister(); 99 myClockON = false; 100 } 101} 102 103void TurnMyClockON() { 104 if (!myClockON) myClockON = true; 105}
Fan
arduino
Serves the fan
1 2 3#define fanONOFFPin A0 4 5bool fanON = true; 6 7void InitializeFan() { 8 pinMode(fanONOFFPin, OUTPUT); 9 TurnFanOFF(); 10} 11 12void TurnFanON() { 13 if (!fanON) { 14 digitalWrite(fanONOFFPin, HIGH); 15 fanON = true; 16 } 17} 18 19void TurnFanOFF() { 20 if (fanON) { 21 digitalWrite(fanONOFFPin, LOW); 22 fanON = false; 23 } 24}
Comments
Only logged in users can leave comments