Files
hencoop/hencoop.ino

455 lines
12 KiB
Arduino
Raw Normal View History

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