//estimated time of "45deg. to 0deg. "= 5.5 seconds "-45deg. to -45 11s"
#include <Adafruit_Sensor.h>
#include <MsTimer2.h> //for our timing to manage time properly or multitasking
#include <LiquidCrystal_I2C.h>
#include <Button2.h>
#include "DHT.h"
#include "RTClib.h"
#include <Wire.h>
#include <EEPROM.h>
RTC_DS3231 rtc;
DateTime startTime1;
DateTime startTime2;
DateTime startTime3;
TimeSpan deltaTime1;
TimeSpan deltaTime2;
TimeSpan deltaTime3;
#define DHT1_PIN 23
#define DHT2_PIN 25
#define DHT3_PIN 27
#define DHTTYPE DHT11 // DHT 22 (AM2302), AM2321
#define TOTAL_SECONDS1 0 //0,1,2,3 address store long data here
#define TOTAL_SECONDS2 4 //4,5,6,7 address store long data here
#define TOTAL_SECONDS3 8 //8,9,10,11 address store long data here
#define BROWNOUT_FLAG1 1023
#define BROWNOUT_FLAG2 1022
#define BROWNOUT_FLAG3 1021
DHT dht1(DHT1_PIN, DHTTYPE);
DHT dht2(DHT2_PIN, DHTTYPE);
DHT dht3(DHT3_PIN, DHTTYPE);
/////////////////////////////////////////////////////////////////
#define TYPE1_BUTTON_PIN A0
#define TYPE2_BUTTON_PIN A1
#define TYPE3_BUTTON_PIN A2
#define TYPE1_ANGLE_PIN A4
#define TYPE2_ANGLE_PIN A5
#define TYPE3_ANGLE_PIN A6
#define VCC_ADC A15
#define TEST_PIN A9
/////////////////////////////////////////////////////////////////
//hard-coded constants
#define TILT_DELAY_NEG45 12000
#define TILT_DELAY_0 6000
#define BROWNOUT_ADC 499
/////////////////////////////////////////////////////////////////
Button2 type1Button, type2Button, type3Button, type4Button;
/////////////////////////////////////////////////////////////////
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define RELAY1_PIN 2
#define RELAY2_PIN 3
#define RELAY3_PIN 4
#define REL_TILT1_PIN 5
#define RELAY5_PIN 6
#define RELAY6_PIN 7
#define RELAY7_PIN 8
#define REL_TILT2_PIN 9
#define RELAY9_PIN 10
#define RELAY10_PIN 11
#define RELAY11_PIN 12
#define REL_TILT3_PIN 13
#define BUZZER_PIN 29
#define LED1R_PIN 41
#define LED2R_PIN 39
#define LED3R_PIN 37
#define LED1G_PIN 35
#define LED2G_PIN 33
#define LED3G_PIN 31
byte startedFlag1, startedFlag2, startedFlag3, finishFlag1, finishFlag2, finishFlag3;
volatile unsigned long timer1, timer2, loopStepTimer;
volatile unsigned long eggTiltTimer1, eggTiltTimer2, eggTiltTimer3;
bool togglerA, togglerB, togglerC;
byte displayMode, loopStep, tiltStepEgg1, tiltStepEgg2, tiltStepEgg3;
int tiltAngle1, tiltAngle2, tiltAngle3;
int prevDesiredAngle, prevDesiredAngle2, prevDesiredAngle3;
long totalSeconds1, totalSeconds2, totalSeconds3;
unsigned long currentSecond, currentSecond2, currentSecond3;
unsigned long previousSecond, previousSecond2, previousSecond3;
ISR(TIMER4_COMPA_vect) {
timerIsr();
}
void timerIsr() { // this are interrupt service //countdown timers
//routine to turn provide a count down timer
//this will decrement every 1 millisecond approx
if (timer1)
timer1-- ; // Only decrement if non-zero !!!!!!!!!!!!
if (timer2)
timer2-- ;
if (eggTiltTimer1)
eggTiltTimer1-- ;
if (eggTiltTimer2)
eggTiltTimer2-- ;
if (eggTiltTimer3)
eggTiltTimer3-- ;
if (loopStepTimer)
loopStepTimer-- ;
}
void displayControl() {
switch (displayMode) {
case 0:
lcd.setCursor(0, 0);
lcd.print(F("Chicken Egg "));
lcd.setCursor(0, 1);
lcd.print(F("Temperature: ")); lcd.print(dht1.readTemperature());
lcd.print((char)223); lcd.print(F("C "));
lcd.setCursor(0, 2);
lcd.print(F("Humidity: ")); lcd.print(dht1.readHumidity()); lcd.print(F("% "));
lcd.setCursor(0, 3);
if (startedFlag1) {
lcd.print(F("Time:"));
byte days = deltaTime1.days();
byte hr = deltaTime1.hours();
byte min = deltaTime1.minutes();
byte sec = deltaTime1.seconds();
float hrDecimal = hr + min / 60.0;
if (days < 10) {
lcd.print(0);
}
lcd.print(days); lcd.print(F("d,"));
if (hr < 10) {
lcd.print(0);//print zero digit
}
lcd.print(hr);
lcd.print(F("h(21days)"));
Serial.print(days); Serial.print("d,");
Serial.print(hr); Serial.print(":");
Serial.print(min); Serial.print(":");
Serial.println(sec);
}
if (finishFlag1) {
lcd.print(F("Incubation Finished"));
}
break;
case 1:
lcd.setCursor(0, 0);
lcd.print(F("Duck Egg "));
lcd.setCursor(0, 1);
lcd.print(F("Temperature: ")); lcd.print(dht2.readTemperature());
lcd.print((char)223); lcd.print(F("C "));
lcd.setCursor(0, 2);
lcd.print(F("Humidity: ")); lcd.print(dht2.readHumidity()); lcd.print(F("% "));
lcd.setCursor(0, 3);
if (startedFlag2) {
lcd.print(F("Time:"));
byte days = deltaTime2.days();
byte hr = deltaTime2.hours();
byte min = deltaTime2.minutes();
byte sec = deltaTime2.seconds();
float hrDecimal = hr + min / 60.0;
if (days < 10) {
lcd.print(0);
}
lcd.print(days); lcd.print(F("d,"));
if (hr < 10) {
lcd.print(0);//print zero digit
}
lcd.print(hr);
lcd.print(F("h(28days)"));
Serial.print(days); Serial.print("d,");
Serial.print(hr); Serial.print(":");
Serial.print(min); Serial.print(":");
Serial.println(sec);
}
if (finishFlag2) {
lcd.print(F("Incubation Finished"));
}
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(F("Quail Egg "));
lcd.setCursor(0, 1);
lcd.print(F("Temperature: ")); lcd.print(dht3.readTemperature());
lcd.print((char)223); lcd.print(F("C "));
lcd.setCursor(0, 2);
lcd.print(F("Humidity: ")); lcd.print(dht3.readHumidity()); lcd.print(F("% "));
lcd.setCursor(0, 3);
if (startedFlag3) {
lcd.print(F("Time:"));
byte days = deltaTime3.days();
byte hr = deltaTime3.hours();
byte min = deltaTime3.minutes();
byte sec = deltaTime3.seconds();
float hrDecimal = hr + min / 60.0;
if (days < 10) {
lcd.print(0);
}
lcd.print(days); lcd.print(F("d,"));
if (hr < 10) {
lcd.print(0);//print zero digit
}
lcd.print(hr);
lcd.print(F("h(18days)"));
Serial.print(days); Serial.print("d,");
Serial.print(hr); Serial.print(":");
Serial.print(min); Serial.print(":");
Serial.println(sec);
}
if (finishFlag3) {
lcd.print(F("Incubation Finished"));
}
break;
}
}
void setup() {
//secondsPassed = 72;
cli();//stop interrupts
//set timer4 interrupt at 1khz
TCCR4A = 0;// set entire TCCR1A register to 0
TCCR4B = 0;// same for TCCR1B
TCNT4 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR4A = 250;
// turn on CTC mode
TCCR4B |= (1 << WGM12);
//64 prescaler//this is just because wokwi will not lag very much on high prescaler
TCCR4B |= (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK4 |= (1 << OCIE4A);
sei();//allow interrupts
analogReference(INTERNAL1V1); //for brownout detection porposes
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" EGG INCUBATOR"));
delay(1000);
lcd.clear();
dht1.begin();
dht2.begin();
dht3.begin();
Serial.begin(115200);
rtc.begin();
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);
pinMode(REL_TILT1_PIN, OUTPUT);
pinMode(RELAY5_PIN, OUTPUT);
pinMode(RELAY6_PIN, OUTPUT);
pinMode(RELAY7_PIN, OUTPUT);
pinMode(REL_TILT2_PIN, OUTPUT);
pinMode(RELAY9_PIN, OUTPUT);
pinMode(RELAY10_PIN, OUTPUT);
pinMode(RELAY11_PIN, OUTPUT);
pinMode(REL_TILT3_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(RELAY1_PIN, HIGH); //high will turn off all relay
digitalWrite(RELAY2_PIN, HIGH);
digitalWrite(RELAY3_PIN, HIGH);
digitalWrite(REL_TILT1_PIN, HIGH);
digitalWrite(RELAY5_PIN, HIGH);
digitalWrite(RELAY6_PIN, HIGH);
digitalWrite(RELAY7_PIN, HIGH);
digitalWrite(REL_TILT2_PIN, HIGH);
digitalWrite(RELAY9_PIN, HIGH);
digitalWrite(RELAY10_PIN, HIGH);
digitalWrite(RELAY11_PIN, HIGH);
digitalWrite(REL_TILT3_PIN, HIGH);
digitalWrite(BUZZER_PIN, HIGH);///active-low buzzer
//and buzzer is a passive type
pinMode(LED1R_PIN, OUTPUT);
pinMode(LED2R_PIN, OUTPUT);
pinMode(LED3R_PIN, OUTPUT);
pinMode(LED1G_PIN, OUTPUT);
pinMode(LED2G_PIN, OUTPUT);
pinMode(LED3G_PIN, OUTPUT);
pinMode(TYPE1_ANGLE_PIN, INPUT_PULLUP);
pinMode(TYPE2_ANGLE_PIN, INPUT_PULLUP);
pinMode(TYPE3_ANGLE_PIN, INPUT_PULLUP);
type1Button.begin(TYPE1_BUTTON_PIN);
type2Button.begin(TYPE2_BUTTON_PIN);
type3Button.begin(TYPE3_BUTTON_PIN);
type1Button.setClickHandler(buttonHandler1);
// button.setLongClickHandler(handler); // this will only be called upon release
//type1Button.setLongClickDetectedHandler(buttonHandler1); // this will only be called upon detection
type1Button.setDoubleClickHandler(buttonHandler1);
type1Button.setTripleClickHandler(buttonHandler1);
type2Button.setClickHandler(buttonHandler2);
// button.setLongClickHandler(handler); // this will only be called upon release
//type1Button.setLongClickDetectedHandler(buttonHandler1); // this will only be called upon detection
type2Button.setDoubleClickHandler(buttonHandler2);
type2Button.setTripleClickHandler(buttonHandler2);
type3Button.setClickHandler(buttonHandler3);
// button.setLongClickHandler(handler); // this will only be called upon release
//type1Button.setLongClickDetectedHandler(buttonHandler1); // this will only be called upon detection
type3Button.setDoubleClickHandler(buttonHandler3);
type3Button.setTripleClickHandler(buttonHandler3);
type4Button.begin(TEST_PIN); //for debugging testing porpuses
type4Button.setClickHandler(buttonHandler4);
type4Button.setDoubleClickHandler(buttonHandler4);
type4Button.setTripleClickHandler(buttonHandler4);
if (EEPROM.read(BROWNOUT_FLAG1) == 1) {
startTime1 = rtc.now() - TimeSpan(readLongFromEEPROM(TOTAL_SECONDS1));
//set start time seconds ago so that the time of brownout will not be included as part of incubation total time
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F("BROWNOUT DETECTED"));
lcd.setCursor(0, 2);
lcd.print(F("CONTINUING..."));
lcd.setCursor(0, 3);
lcd.print(F(" "));
startedFlag1 = 1;
EEPROM.write(BROWNOUT_FLAG1, 0); //reset
}
if (EEPROM.read(BROWNOUT_FLAG2) == 1) {
startTime2 = rtc.now() - TimeSpan(readLongFromEEPROM(TOTAL_SECONDS2));
//set start time seconds ago so that the time of brownout will not be included as part of incubation total time
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F("BROWNOUT DETECTED"));
lcd.setCursor(0, 2);
lcd.print(F("CONTINUING..."));
lcd.setCursor(0, 3);
lcd.print(F(" "));
startedFlag2 = 1;
EEPROM.write(BROWNOUT_FLAG2, 0); //reset
}
if (EEPROM.read(BROWNOUT_FLAG3) == 1) {
startTime3 = rtc.now() - TimeSpan(readLongFromEEPROM(TOTAL_SECONDS3));
//set start time seconds ago so that the time of brownout will not be included as part of incubation total time
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F("BROWNOUT DETECTED"));
lcd.setCursor(0, 2);
lcd.print(F("CONTINUING..."));
lcd.setCursor(0, 3);
lcd.print(F(" "));
startedFlag3 = 1;
EEPROM.write(BROWNOUT_FLAG3, 0); //reset
}
}
void loop() {
loopSetup();
type1Button.loop();
type2Button.loop();
type3Button.loop();
type4Button.loop();
tiltEggAlgorithm1(tiltAngle1);
tiltEggAlgorithm2(tiltAngle2);
tiltEggAlgorithm3(tiltAngle3);
brownOutDetect();
if (!timer1) {
timer1 = 1000; // execute this every 1000ms
displayControl();
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//buzzer logic
if (finishFlag1 || finishFlag2 || finishFlag3) {
//tone(BUZZER_PIN, 2000, 500); //2khzfor 500ms
digitalWrite(BUZZER_PIN,LOW);
}
else {
digitalWrite(BUZZER_PIN,HIGH);
//noTone(BUZZER_PIN);
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//temp humidity sensor ,led indicators logic
if ( startedFlag1 ) {
if (dht1.readTemperature() >= 37.9) {
digitalWrite(RELAY1_PIN, 1);
digitalWrite(RELAY2_PIN, 1);
if (dht1.readHumidity() >= 55 && dht1.readHumidity() <= 65) {
digitalWrite(RELAY3_PIN, 0); //fan on
}
else {
digitalWrite(RELAY3_PIN, 1); //fan off
}
}
else {
digitalWrite(RELAY1_PIN, 0);
digitalWrite(RELAY2_PIN, 0);
digitalWrite(RELAY3_PIN, 1); //fan off
}
digitalWrite(LED1G_PIN, 1);//status led
digitalWrite(LED1R_PIN, 0);
deltaTime1 = rtc.now() - startTime1;
totalSeconds1 = deltaTime1.totalseconds();
eggTiltControl1(totalSeconds1);//fucntion which decides when to tilt
if (deltaTime1.days() >= 21) {
deltaTime1 = 0;
finishFlag1 = 1;
startedFlag1 = 0;
timer1 = 1000;
lcd.clear();
displayMode = 0;
}
else {
finishFlag1 = 0;
}
}
else {
digitalWrite(RELAY1_PIN, 1); //off all
digitalWrite(RELAY2_PIN, 1);
digitalWrite(RELAY3_PIN, 1);
digitalWrite(LED1G_PIN, 0);//status led
if (finishFlag1) { //blink red led
digitalWrite(LED1R_PIN, !digitalRead(LED1R_PIN));
}
else {
digitalWrite(LED1R_PIN, 1);
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
if ( startedFlag2 ) {
if (dht2.readTemperature() >= 38.6) {
digitalWrite(RELAY5_PIN, 1);
digitalWrite(RELAY6_PIN, 1);
if (dht2.readHumidity() >= 55 && dht2.readHumidity() <= 60) {
digitalWrite(RELAY7_PIN, 0); //fan on
}
else {
digitalWrite(RELAY7_PIN, 1); //fan off
}
}
else {
digitalWrite(RELAY5_PIN, 0);
digitalWrite(RELAY6_PIN, 0);
digitalWrite(RELAY7_PIN, 1); //fan off
}
digitalWrite(LED2G_PIN, 1);//status led
digitalWrite(LED2R_PIN, 0);
deltaTime2 = rtc.now() - startTime2;
totalSeconds2 = deltaTime2.totalseconds();
eggTiltControl2(totalSeconds2);//fucntion which decides when to tilt
if (deltaTime2.days() >= 28) {
deltaTime2 = 0;
finishFlag2 = 1;
startedFlag2 = 0;
timer1 = 1000;
lcd.clear();
displayMode = 1;
}
else {
finishFlag2 = 0;
}
}
else {
digitalWrite(RELAY5_PIN, 1); //off all
digitalWrite(RELAY6_PIN, 1);
digitalWrite(RELAY7_PIN, 1);
digitalWrite(LED2G_PIN, 0);//status led
if (finishFlag2) { //blink red led
digitalWrite(LED2R_PIN, !digitalRead(LED2R_PIN));
}
else {
digitalWrite(LED2R_PIN, 1);
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
if ( startedFlag3 ) {
if (dht3.readTemperature() >= 37.3) {
digitalWrite(RELAY9_PIN, 1);
digitalWrite(RELAY10_PIN, 1);
if (dht3.readHumidity() >= 60 && dht2.readHumidity() <= 70) {
digitalWrite(RELAY11_PIN, 0); //fan on
}
else {
digitalWrite(RELAY11_PIN, 1); //fan off
}
}
else {
digitalWrite(RELAY9_PIN, 0);
digitalWrite(RELAY10_PIN, 0);
digitalWrite(RELAY11_PIN, 1); //fan off
}
digitalWrite(LED3G_PIN, 1);//status led
digitalWrite(LED3R_PIN, 0);
deltaTime3 = rtc.now() - startTime3;
totalSeconds3 = deltaTime3.totalseconds();
eggTiltControl3(totalSeconds3);//fucntion which decides when to tilt
if (deltaTime3.days() >= 18) {
deltaTime3 = 0;
finishFlag3 = 1;
startedFlag3 = 0;
timer1 = 1000;
lcd.clear();
displayMode = 2;
}
else {
finishFlag3 = 0;
}
}
else {
digitalWrite(RELAY9_PIN, 1); //off all
digitalWrite(RELAY10_PIN, 1);
digitalWrite(RELAY11_PIN, 1);
digitalWrite(LED3G_PIN, 0);//status led
if (finishFlag3) { //blink red led
digitalWrite(LED3R_PIN, !digitalRead(LED3R_PIN));
}
else {
digitalWrite(LED3R_PIN, 1);
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
}
}
void buttonHandler1(Button2 & btn) {
switch (btn.getType()) {
case single_click:
lcd.clear();
displayMode = 0;
if (finishFlag1) {
finishFlag1 = 0;
}
break;
case double_click://start incubating
if (!startedFlag1) {
startTime1 = rtc.now();
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STARTING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
startedFlag1 = 1;
displayMode = 0;
}
break;
case triple_click://stop incubating
if (startedFlag1) {
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STOPPING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
tiltAngle1 = 0;
startedFlag1 = 0;
displayMode = 0;
}
break;
}
}
void buttonHandler2(Button2 & btn) {
switch (btn.getType()) {
case single_click:
lcd.clear();
displayMode = 1;
if (finishFlag2) {
finishFlag2 = 0;
}
break;
case double_click://start incubating
if (!startedFlag2) {
startTime2 = rtc.now();
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STARTING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
startedFlag2 = 1;
displayMode = 1;
}
break;
case triple_click://stop incubating
if (startedFlag2) {
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STOPPING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
tiltAngle3 = 0;
displayMode = 1;
startedFlag2 = 0;
}
break;
}
}
void buttonHandler3(Button2 & btn) {
switch (btn.getType()) {
case single_click:
lcd.clear();
displayMode = 2;
if (finishFlag3) {
finishFlag3 = 0;
}
break;
case double_click://start incubating
if (!startedFlag3) {
startTime3 = rtc.now();
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STARTING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
tiltAngle3 = 0;
startedFlag3 = 1;
displayMode = 2;
}
break;
case triple_click://stop incubating
if (startedFlag3) {
timer1 = 2000;//long delay to give time disPLAYING notification
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F(" STOPPING EGG "));
lcd.setCursor(0, 2);
lcd.print(F(" INCUBATION "));
lcd.setCursor(0, 3);
lcd.print(F(" "));
displayMode = 2;
startedFlag3 = 0;
}
break;
}
}
void eggTiltControl2(const unsigned long totalSeconds) { //for tilting control based on time
float days = totalSeconds / 3600 / 24;
if (days >= 26 ) { //go back to flat position
tiltAngle2 = 0;
Serial.println("0 deg");
}
if (days >= 4 && days <= 25 ) {
currentSecond2 = totalSeconds;
if (currentSecond2 - previousSecond2 >= 17280) { //4.8 hours 1 day
previousSecond2 = currentSecond2;//17280seconds=4.8h
togglerB = !togglerB;
if (togglerB) {
Serial.println("45 deg");
tiltAngle2 = 45;
}
else {
tiltAngle2 = -45;
Serial.println("-45 deg");
}
}
}
}
void eggTiltControl1(const unsigned long totalSeconds) { //for tilting control based on time
float days = totalSeconds / 3600 / 24;
if (days >= 19 ) { //go back to flat position
tiltAngle1 = 0;
Serial.println("0 deg");
}
if (days >= 4 && days <= 18 ) {
currentSecond = totalSeconds;
if (currentSecond - previousSecond >= 17280) { //4.8 hours 1 day
previousSecond = currentSecond;//17280seconds=4.8h
togglerA = !togglerA;
if (togglerA) {
Serial.println("45 deg");
tiltAngle1 = 45;
}
else {
tiltAngle1 = -45;
Serial.println("-45 deg");
}
}
}
}
void eggTiltControl3(const unsigned long totalSeconds) { //for tilting control based on time
float days = totalSeconds / 3600 / 24;
if (days >= 16 ) { //go back to flat position
tiltAngle3 = 0;
Serial.println("0 deg");
}
if (days >= 4 && days <= 15 ) {
currentSecond3 = totalSeconds;
if (currentSecond3 - previousSecond3 >= 17280) { //4.8 hours 1 day
previousSecond3 = currentSecond3;//17280seconds=4.8h
togglerC = !togglerC;
if (togglerC) {
Serial.println("45 deg");
tiltAngle3 = 45;
}
else {
tiltAngle3 = -45;
Serial.println("-45 deg");
}
}
}
}
void buttonHandler4(Button2 & btn) {
switch (btn.getType()) {
case single_click:
//TimeSpan(days,hours,minutes,seconds)
if (displayMode == 0) {
startTime1 = startTime1 - TimeSpan(0, 4, 50, 0);//advance the time
}
else if (displayMode == 1) {
startTime2 = startTime2 - TimeSpan(0, 4, 50, 0);//advance the time
}
else if (displayMode == 2) {
startTime3 = startTime3 - TimeSpan(0, 4, 50, 0);//advance the time
}
break;
case double_click:
//TimeSpan(days,hours,minutes,seconds)
if (displayMode == 0) {
startTime1 = startTime1 - TimeSpan(4, 0, 0, 0); //advance the time
}
else if (displayMode == 1) {
startTime2 = startTime2 - TimeSpan(4, 0, 0, 0); //advance the time
}
else if (displayMode == 2) {
startTime3 = startTime3 - TimeSpan(4, 0, 0, 0); //advance the time
}
//tiltAngle1=45;
// if (EEPROM.read(BROWNOUT_FLAG1) == 1) {
// startTime1 = rtc.now() - TimeSpan(readLongFromEEPROM(TOTAL_SECONDS1));
// //set start time seconds ago so that the time of brownout will not be included as part of incubation total time
// timer1 = 2000;//long delay to give time disPLAYING notification
// lcd.clear();
// lcd.setCursor(0, 1);
// lcd.print(F("BROWNOUT DETECTED"));
// lcd.setCursor(0, 2);
// lcd.print(F("CONTINUING..."));
// lcd.setCursor(0, 3);
// lcd.print(F(" "));
// startedFlag1 = 1;
// EEPROM.write(BROWNOUT_FLAG1, 0); //reset
// }
break;
}
}
void tiltEggAlgorithm1(const int desiredAngle) {
tiltStepEgg1;
prevDesiredAngle ;
int delayValue;
if (desiredAngle != prevDesiredAngle ) {
tiltStepEgg1 = 0; //change detection
digitalWrite(REL_TILT1_PIN, LOW);
//eggTiltTimer=1000; //add delay or else it will turn off immideately becuase its in 45 degree position its already in
}
prevDesiredAngle = desiredAngle ;
switch (tiltStepEgg1) {
case 0:
if (digitalRead(TYPE1_ANGLE_PIN) == LOW) { //if 45 deg is reached
if (desiredAngle == 45) delayValue = 0;
if (desiredAngle == 0) delayValue = TILT_DELAY_0;
if (desiredAngle == -45) delayValue = TILT_DELAY_NEG45;
tiltStepEgg1 = 1;
eggTiltTimer1 = delayValue;
}
break;
case 1:
if (!eggTiltTimer1) {
digitalWrite(REL_TILT1_PIN, HIGH); //stop Motor
tiltStepEgg1 = 2;
}
break;
}
}
void tiltEggAlgorithm2(const int desiredAngle2) {
tiltStepEgg2;
prevDesiredAngle2 ;
int delayValue;
if (desiredAngle2 != prevDesiredAngle2 ) {
tiltStepEgg2 = 0; //change detection
digitalWrite(REL_TILT2_PIN, LOW);
}
prevDesiredAngle2 = desiredAngle2 ;
switch (tiltStepEgg2) {
case 0:
if (digitalRead(TYPE2_ANGLE_PIN) == LOW) { //if 45 deg is reached
if (desiredAngle2 == 45) delayValue = 0;
if (desiredAngle2 == 0) delayValue = TILT_DELAY_0;
if (desiredAngle2 == -45) delayValue = TILT_DELAY_NEG45;
tiltStepEgg2 = 1;
eggTiltTimer2 = delayValue;
}
break;
case 1:
if (!eggTiltTimer2) {
digitalWrite(REL_TILT2_PIN, HIGH); //stop Motor
tiltStepEgg2 = 2;
}
break;
}
}
void tiltEggAlgorithm3(const int desiredAngle3) {
tiltStepEgg3;
prevDesiredAngle3 ;
int delayValue;
if (desiredAngle3 != prevDesiredAngle3 ) {
tiltStepEgg3 = 0; //change detection
digitalWrite(REL_TILT3_PIN, LOW);
}
prevDesiredAngle3 = desiredAngle3 ;
switch (tiltStepEgg3) {
case 0:
if (digitalRead(TYPE3_ANGLE_PIN) == LOW) { //if 45 deg is reached
if (desiredAngle3 == 45) delayValue = 0;
if (desiredAngle3 == 0) delayValue = TILT_DELAY_0;
if (desiredAngle3 == -45) delayValue = TILT_DELAY_NEG45;
tiltStepEgg3 = 1;
eggTiltTimer3 = delayValue;
}
break;
case 1:
if (!eggTiltTimer3) {
digitalWrite(REL_TILT3_PIN, HIGH); //stop Motor
tiltStepEgg3 = 2;
}
break;
}
}
void loopSetup() {
//this will go to flat position on firs boot
switch (loopStep) {
case 0:
tiltAngle1 = 45;
tiltAngle2 = 45;
tiltAngle3 = 45;
loopStepTimer = 1000;
loopStep = 1;
break;
case 1:
if (!loopStepTimer) {
loopStep = 2;//exit
tiltAngle1 = 0; // flat position
tiltAngle2 = 0;
tiltAngle3 = 0;
}
break;
}
}
void brownOutDetect() {
if (analogRead(VCC_ADC) < BROWNOUT_ADC) { //if it detected lower than normal operating voltage(1024)
if (startedFlag1) {
EEPROM.update(BROWNOUT_FLAG1, 1); //set 1 if gastart ang chckcen egg
writeLongIntoEEPROM(TOTAL_SECONDS1, totalSeconds1);
}
if (startedFlag2) {
EEPROM.update(BROWNOUT_FLAG2, 1);
writeLongIntoEEPROM(TOTAL_SECONDS2, totalSeconds2);
}
if (startedFlag3) {
EEPROM.update(BROWNOUT_FLAG3, 1);
writeLongIntoEEPROM(TOTAL_SECONDS3, totalSeconds3);
}
}
else {
//in case of it detected very sudden voltage drop ,that dont cause total shutdown of system
//it will cancel brownout continuation;
if (startedFlag1) {
EEPROM.update(BROWNOUT_FLAG1, 0); //set 0
}
if (startedFlag2) {
EEPROM.update(BROWNOUT_FLAG2, 0);
}
if (startedFlag3) {
EEPROM.update(BROWNOUT_FLAG3, 0);
}
}
}
void writeLongIntoEEPROM(int address, long number)
{
EEPROM.update(address, (number >> 24) & 0xFF);
EEPROM.update(address + 1, (number >> 16) & 0xFF);
EEPROM.update(address + 2, (number >> 8) & 0xFF);
EEPROM.update(address + 3, number & 0xFF);
}
long readLongFromEEPROM(int address)
{
return ((long)EEPROM.read(address) << 24) +
((long)EEPROM.read(address + 1) << 16) +
((long)EEPROM.read(address + 2) << 8) +
(long)EEPROM.read(address + 3);
}