hencoop/hencoop.ino

297 lines
8.7 KiB
C++

/*
* Hencoop with automatic lamp and door timer, TM1637 display and two buttons
*/
#include <Arduino.h>
#include <Wire.h>
#include <TimeLib.h>
#include <Thread.h>
#include <DS1307RTC.h>
#include <SevenSegmentExtended.h> // Extended TM1637 library https://github.com/bremme/arduino-tm1637
long openDoorVar = 3780; // Interval for door opening
long closeDoorVar = 3600; // Interval for door closing
const byte PIN_CLK = 2; // Define CLK pin (for 4-Digit Display)
const byte PIN_DIO = 3; // Define DIO pin (for 4-Digit Display)
const byte redButton = 4; // RedButton: light on, open door
const byte blackButton = 5; // BlackButton: light off, close door
const byte pinLight = 6; // Light relay
const byte pinDC = 7; // DC motor relay
const byte pinRelay3 = 8; // Motor relay control
const byte pinRelay4 = 9; // Motor relay control
const byte led = 13;
SevenSegmentExtended display(PIN_CLK, PIN_DIO);
// long ledPulse = 1000; // Interval for LED blinking pulse
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 = 5000; // Interval for long press button action
long buttonShortPress = 600; // Interval for short press button action
unsigned long lastButtonPressed;
// Threads:
Thread pressButtonThread = Thread(); // Create thread for button state checking
// Thread ledThread = Thread(); // Create thread for LED pulse indication
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(led, OUTPUT);
pinMode(redButton, INPUT);
pinMode(blackButton, 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");
// LED blinking thread:
// ledThread.onRun(ledBlink);
// ledThread.setInterval(ledPulse); // Interval for LED blinking
// Button state cheking thread:
pressButtonThread.onRun(pressButton);
pressButtonThread.setInterval(buttonCheck); // Interval for checking button pressing
delay (1000);
display.off();
serStr("...setup finished");
}
void loop() {
// Threads init:
// if (ledThread.shouldRun())
// ledThread.run();
if (pressButtonThread.shouldRun())
pressButtonThread.run();
if (timeStatus() == timeSet) { // If RTC works - call the checkTime function
checkTime();
} else {
display.on();
display.print("SET TIME");
}
/*
} else { // Fast blinking indicates that time is
int i; // not set or DS1307RTC is not plugged
for (i = 1; i <= 500; i++) {
digitalWrite(led, LOW);
delay(50);
digitalWrite(led, HIGH);
delay(50);
}
}
*/
}
void checkTime() {
// Winter
// 6:56 open door, 7:01 light on, 10:01 light off,
// 16:01 light on, 19:01 light off, 19:05 close door
if (month()==11 || month()==12 || month()==1 ) {
if (hour() == 6 && minute() == 56) {
openDoor();
delay(60000);
}
if (hour() == 7 && minute() == 1) {
lightOn();
delay(60000);
}
if (hour() == 10 && minute() == 1) {
lightOff();
delay(60000);
}
if (hour() == 16 && minute() == 1) {
lightOn();
delay(60000);
}
if (hour() == 19 && minute() == 1) {
lightOff();
delay(60000);
}
if (hour() == 19 && minute() == 5) {
closeDoor();
delay(60000);
}
}
// Spring
// 6:30 door open, 17:01 light on, 20:01 light off, 20:05 door close
if (month()==2 || month()==3 || month()==4 ) {
if (hour() == 6 && minute() == 30) {
openDoor();
delay(60000);
}
if (hour() == 17 && minute() == 1) {
lightOn();
delay(60000);
}
if (hour() == 20 && minute() == 1) {
lightOff();
delay(60000);
}
if (hour() == 20 && minute() == 5) {
closeDoor();
delay(60000);
}
}
// Summer
// 5:30 open door, 22:05 close door
if (month()==5 || month()==6 || month()==7 ) {
if (hour() == 5 && minute() == 30) {
openDoor();
delay(60000);
}
if (hour() == 22 && minute() == 5) {
closeDoor();
delay(60000);
}
}
// Autumn
// 6:01 open door, 17:01 light on, 20:01 light off, 21:05 close door
if (month()==8 || month()==9 || month()==10 ) {
if (hour() == 6 && minute() == 1) {
openDoor();
delay(60000);
}
if (hour() == 17 && minute() == 1) {
lightOn();
delay(60000);
}
if (hour() == 20 && minute() == 1) {
lightOff();
delay(60000);
}
if (hour() == 21 && minute() == 5) {
closeDoor();
delay(60000);
}
}
}
/*
// LED pulse blinking thread
void ledBlink() {
static bool ledStatus = false; // LED status bool
ledStatus = !ledStatus; // Invert LED state
digitalWrite(led, ledStatus); // Activate LED state
}
*/
// 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) {
// if (digitalRead(redButton) == HIGH) serStr("Red button pressed, time showed");
// if (digitalRead(blackButton) == HIGH) serStr("Black button pressed, time showed");
display.on();
displayWork = 1;
display.printTime(hour(), 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() {
serStr("Door opening started...");
digitalWrite(pinDC, LOW); // DC on
delay(1000);
digitalWrite(pinRelay4, LOW);
delay(openDoorVar);
digitalWrite(pinRelay4, HIGH);
delay(1000);
digitalWrite(pinDC, HIGH); // DC off
serStr("...door opening finished");
}
void closeDoor() {
serStr("Door closing started...");
digitalWrite(pinDC, LOW); // DC on
delay(1000);
digitalWrite(pinRelay3, LOW);
delay(closeDoorVar);
digitalWrite(pinRelay3, HIGH);
delay(1000);
digitalWrite(pinDC, HIGH); // DC off
serStr("...door closing finished");
}
// Send string to serial monitor with millis() counter and date/time
void serStr(const char* serString) {
long currentTime = millis();
String space = " ";
String stringToPrint = currentTime + space + serString;
Serial.println(stringToPrint);
// RTC mark
Serial.print("RTC time = ");
Serial.print(hour());
Serial.write(':');
Serial.print(minute());
Serial.write(':');
Serial.print(second());
Serial.print(", date (D/M/Y) = ");
Serial.print(day());
Serial.write('/');
Serial.print(month());
Serial.write('/');
Serial.print(year());
Serial.println();
}