/* * Hencoop with automatic lamp and door timer, TM1637 display, two buttons and magnetically operated sealed switch */ #include #include #include #include #include #include // Extended TM1637 library https://github.com/bremme/arduino-tm1637 long maxOpenDoorVar = 8667; // Interval for maximum door opening time long closeDoorVar = 3667; // Interval for door closing const byte redButton = 4; // RedButton: light on, open door const byte blackButton = 5; // BlackButton: light off, close door const byte pinLight = 6; // Light power relay const byte pinDC = 7; // DC motor power relay const byte pinRelay3 = 8; // Motor relay control const byte pinRelay4 = 9; // Motor relay control const byte PIN_CLK = 10; // Define CLK pin (for 4-Digit Display) const byte PIN_DIO = 11; // Define DIO pin (for 4-Digit Display) const byte doorSwitch = 12; // Door's magnetically operated sealed switch long buttonCheck = 200; // Interval for checking button state byte buttonCommand = 0; // Variable for buttons value: 0 - nothing, 1 - light on, 2 - light off byte displayWork = 0; // Variable for display status: 0 - nothing, 1 - work long previousButtonMillis = 0; // Button previous press counter long buttonPressed = 0; // Button ms pressed counter long buttonLongPress = 1500; // Interval for long press button action long buttonShortPress = 400; // Interval for short press button action unsigned long lastButtonPressed; SevenSegmentExtended display(PIN_CLK, PIN_DIO); // Time bias correction variables: int correctionBias = 1; // Daily clock correction in seconds long correctionCheck = 300000; byte correctionHour = 3; bool correctionReady = true; // Threads: Thread pressButtonThread = Thread(); // Create thread for button state checking Thread correctionThread = Thread(); // Time bias correction thread void setup() { Serial.begin(9600); // Initializes the Serial connection @ 9600 baud for debug serStr("starting setup..."); display.begin(); // Initializes the display display.setBacklight(100); // Set the brightness to 100 % display.print("INIT"); // Display INIT on the display pinMode(pinRelay3, OUTPUT); pinMode(pinRelay4, OUTPUT); pinMode(pinDC, OUTPUT); pinMode(pinLight, OUTPUT); pinMode(redButton, INPUT); pinMode(blackButton, INPUT); pinMode(doorSwitch, INPUT); digitalWrite(pinRelay3, HIGH); digitalWrite(pinRelay4, HIGH); digitalWrite(pinDC, HIGH); digitalWrite(pinLight, HIGH); while (!Serial); // Wait until Arduino Serial Monitor opens setSyncProvider(RTC.get); // The function to get the time from the RTC if(timeStatus()!= timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time"); Serial.println(now()); while (!Serial) ; // wait for serial delay(200); Serial.println("DS1307RTC"); // Button state cheking thread: pressButtonThread.onRun(pressButton); pressButtonThread.setInterval(buttonCheck); // Interval for checking button pressing // Time bias correction thread: correctionThread.onRun(correctionLoop); correctionThread.setInterval(correctionCheck); delay (100); display.off(); serStr("...setup finished"); } void loop() { // Threads init: if (pressButtonThread.shouldRun()) pressButtonThread.run(); if (correctionThread.shouldRun()) correctionThread.run(); tmElements_t tm; if (RTC.read(tm)) { // If RTC works - call the checkTime function checkTime(); } else { display.on(); display.print("SET TIME"); } } // Check button pressing thread void pressButton() { unsigned long currentMillis = millis(); if (((currentMillis - previousButtonMillis) > 20000) && (displayWork == 1)) { display.off(); displayWork = 0; } if (digitalRead(redButton) == HIGH || digitalRead(blackButton) == HIGH) { tmElements_t tm; RTC.read(tm); display.on(); displayWork = 1; display.printTime(tm.Hour, tm.Minute, true); buttonPressed = buttonPressed + 200; if (buttonPressed > buttonShortPress) { if (digitalRead(redButton) == HIGH) buttonCommand = 1; if (digitalRead(blackButton) == HIGH) buttonCommand = 2; } if (buttonPressed > buttonLongPress) { buttonPressed = 0; buttonCommand = 0; if (digitalRead(redButton) == HIGH) serStr("Red button long press"); if (digitalRead(redButton) == HIGH) openDoor(); if (digitalRead(blackButton) == HIGH) serStr("Black button long press"); if (digitalRead(blackButton) == HIGH) closeDoor(); } previousButtonMillis = currentMillis; } else { buttonPressed = 0; } if (digitalRead(redButton) == LOW && digitalRead(blackButton) == LOW) { if (buttonCommand == 1) serStr("Red button short press"); if (buttonCommand == 1) lightOn(); if (buttonCommand == 2) serStr("Black button short press"); if (buttonCommand == 2) lightOff(); } } void lightOn() { buttonCommand = 0; digitalWrite(pinLight, LOW); serStr("Light on"); } void lightOff() { buttonCommand = 0; digitalWrite(pinLight, HIGH); serStr("Light off"); } void openDoor() { unsigned long openStart = millis(); if (digitalRead(doorSwitch) == LOW) { serStr("Door opening started..."); digitalWrite(pinRelay3, HIGH); digitalWrite(pinRelay4, HIGH); delay(1000); digitalWrite(pinDC, LOW); // DC on delay(3000); digitalWrite(pinRelay4, LOW); while (digitalRead(doorSwitch) == LOW) { if ((millis() - openStart) > maxOpenDoorVar) { break; } delay(55); } digitalWrite(pinRelay4, HIGH); delay(2000); digitalWrite(pinDC, HIGH); // DC off delay(1000); digitalWrite(pinRelay3, HIGH); digitalWrite(pinRelay4, HIGH); serStr("...door opening finished"); } else { serStr("Can't open door, magnet shows that door is open"); display.on(); display.print("can't - door is open"); display.off(); } } void closeDoor() { if (digitalRead(doorSwitch) == HIGH) { serStr("Door closing started..."); digitalWrite(pinRelay3, HIGH); digitalWrite(pinRelay4, HIGH); delay(1000); digitalWrite(pinDC, LOW); // DC on delay(3000); digitalWrite(pinRelay3, LOW); delay(closeDoorVar); digitalWrite(pinRelay3, HIGH); delay(2000); digitalWrite(pinDC, HIGH); // DC off delay(1000); digitalWrite(pinRelay3, HIGH); digitalWrite(pinRelay4, HIGH); serStr("...door closing finished"); } else { serStr("Can't close door, magnet shows that door is closed"); display.on(); display.print("can't - door is closed"); display.off(); } } // Send string to serial monitor with millis() counter and date/time void serStr(const char* serString) { tmElements_t tm; RTC.read(tm); long currentTime = millis(); String space = " "; String stringToPrint = currentTime + space + serString; Serial.println(stringToPrint); // RTC mark Serial.print("RTC time = "); Serial.print(tm.Hour); Serial.write(':'); Serial.print(tm.Minute); Serial.write(':'); Serial.print(tm.Second); Serial.print(", date (D/M/Y) = "); Serial.print(tm.Day); Serial.write('/'); Serial.print(tm.Month); Serial.write('/'); Serial.print(tmYearToCalendar(tm.Year)); Serial.println(); } void checkTime() { tmElements_t tm; RTC.read(tm); // January if (tm.Month == 1) { if (tm.Hour == 8 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 55) { lightOn(); delay(60000); } if (tm.Hour == 17 && tm.Minute == 55) { lightOff(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 55) { closeDoor(); delay(60000); } } // February if (tm.Month == 2) { if (tm.Hour == 7 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 30) { lightOn(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 15) { lightOff(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 30) { closeDoor(); delay(60000); } } // March if (tm.Month == 3) { if (tm.Hour == 6 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 30) { lightOn(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 30) { lightOff(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 45) { closeDoor(); delay(60000); } } // April if (tm.Month == 4) { if (tm.Hour == 5 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 18 && tm.Minute == 55) { lightOn(); delay(60000); } if (tm.Hour == 20 && tm.Minute == 45) { lightOff(); delay(60000); } if (tm.Hour == 20 && tm.Minute == 50) { closeDoor(); delay(60000); } } // May if (tm.Month == 5) { if (tm.Hour == 4 && tm.Minute == 30) { openDoor(); delay(60000); } if (tm.Hour == 21 && tm.Minute == 55) { closeDoor(); delay(60000); } } // June if (tm.Month == 6) { if (tm.Hour == 4 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 22 && tm.Minute == 30) { closeDoor(); delay(60000); } } // July if (tm.Month == 7) { if (tm.Hour == 4 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 22 && tm.Minute == 15) { closeDoor(); delay(60000); } } // August if (tm.Month == 8) { if (tm.Hour == 4 && tm.Minute == 45) { openDoor(); delay(60000); } if (tm.Hour == 21 && tm.Minute == 45) { closeDoor(); delay(60000); } } // September if (tm.Month == 9) { if (tm.Hour == 5 && tm.Minute == 55) { openDoor(); delay(60000); } if (tm.Hour == 17 && tm.Minute == 15) { lightOn(); delay(60000); } if (tm.Hour == 20 && tm.Minute == 15) { lightOff(); delay(60000); } if (tm.Hour == 20 && tm.Minute == 55) { closeDoor(); delay(60000); } } // October if (tm.Month == 10) { if (tm.Hour == 6 && tm.Minute == 25) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 15) { lightOn(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 15) { lightOff(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 45) { closeDoor(); delay(60000); } } // November if (tm.Month == 11) { if (tm.Hour == 6 && tm.Minute == 45) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 15) { lightOn(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 15) { lightOff(); delay(60000); } if (tm.Hour == 17 && tm.Minute == 15) { closeDoor(); delay(60000); } } // December if (tm.Month == 12) { if (tm.Hour == 8 && tm.Minute == 15) { openDoor(); delay(60000); } if (tm.Hour == 7 && tm.Minute == 45) { lightOn(); delay(60000); } if (tm.Hour == 19 && tm.Minute == 45) { lightOff(); delay(60000); } if (tm.Hour == 16 && tm.Minute == 45) { closeDoor(); delay(60000); } } } void correctionLoop() { tmElements_t RTCtime; RTC.read(RTCtime); if (RTCtime.Hour == correctionHour) { if (correctionReady) { // CORRECTION time_t RTCtimestamp; RTCtimestamp = makeTime(RTCtime); tmElements_t timeNew; time_t newTimestamp = RTCtimestamp - correctionBias; // -1sec everyday if ((RTCtime.Day % 5) == 0) newTimestamp = newTimestamp - 2; // -2sec every 5 days (-0.4sec everyday) breakTime(newTimestamp, timeNew); RTC.write(timeNew); setSyncProvider(RTC.get); // CORRECTION correctionReady = false; } } else correctionReady = true; }