CanGrow/Arduino/CanGrow/CanGrow_SysFunctions.h

567 lines
16 KiB
C

/*
*
*
* System Functions
*
*
*/
void wipeEEPROM() {
Serial.println(":: wipe EEPROM ::");
// wipeMsg is helper variable to know if the Serial.print Message was
// already sent
byte wipeMsg = 0;
while(digitalRead(PinWIPE) == LOW ) {
// only show the Serial message once
if(wipeMsg == 0) {
Serial.println("Please release PinWIPE to erase all data saved in EEPROM");
Serial.println("LAST CHANCE TO KEEP THE DATA BY RESETTING NOW!!");
display.clearDisplay();
display.setCursor(0,0);
display.println("!!!!!!!!!!!!!!!!!!!!!");
display.println("");
display.println("RELEASE PinWIPE");
display.println("TO WIPE EEPROM");
display.display();
// increase i to show the serial message only once
wipeMsg = 1;
}
delay(500);
}
// write a 0 to all 512 bytes of the EEPROM
Serial.print("wiping EEPROM... ");
display.println("Wiping EEPROM...");
display.println("Will restart in 3s");
display.display();
for (int i = 0; i < 512; i++) { EEPROM.write(i, 0); }
// commit everything to EEPROM and end here
EEPROM.end();
Serial.println("DONE");
// set D4 PinWIPE internal LED to Output to give feedback WIPE
// was done
pinMode(PinWIPE, OUTPUT);
Serial.println("!! Device will restart in 3 seconds !!");
// let the internal led blink fast to signalize wipe is done
for(byte i = 0; i <= 24 ; i++) {
if(i % 2) {
digitalWrite(PinWIPE, LOW);
} else {
digitalWrite(PinWIPE, HIGH);
}
delay(125);
}
ESP.restart();
}
bool loadEEPROM() {
/*
* EEPROM Save table
*
* 0 WIFIssid
* 32 WIFIpassword
* 96 WIFIip
* 112 WIFInetmask
* 128 WIFIgateway
* 144 WIFIdns
* 160 WIFIuseDHCP
*
* 161 configured
* 162 UseFan
* 163 UsePump
* 164 PumpOnTime
* 165 MoistureSensor_Type
* 166 SoilmoistureLow
* 167 NtpOffset
* 169 UseLEDrelais
*
* 170 GrowName
* 202 GrowStart
* 206 DaysVeg
* 207 DaysBloom
* 208 LighthoursVet
* 209 LighthoursBloom
* 210 SunriseHour
* 211 SunriseMinute
* 212 DayOfGrow
*
* -- afterwards added, need to sort --
*
* 213 PinLEDPWM
* 214 TemperatureSensor_Type
* 215 UseFANrelais
* 216 PinFANPWM
* 217 SunFade
* 218 SunFadeDuration
* 219 MaintenanceDuration (2 byte)
* 221 Esp32CamIP (16 byte)
* 237 ...
*
*/
Serial.println(":: loading EEPROM ::");
display.setCursor(0,36);
display.fillRect(0,36,128,64-36, 0);
display.println("loading EEPROM");
display.display();
// read var WIFIssid from address 0, 32 byte long
// read this first, because we decide on the ssid length (>0?) if
// we run in unconfigured AP mode, nor not
EEPROM.get(0, WIFIssid);
// when length is > 0 then read furter EEPROM config data
if(strlen(WIFIssid)) {
/*
* WIFI settings
*/
// read var WIFIpassword from address 32, 64 byte long
EEPROM.get(32, WIFIpassword);
// read var WIFIip from address 96, 16 byte long
EEPROM.get(96, WIFIip);
// read var WIFInetmask from address 112, 16 byte long
EEPROM.get(112, WIFInetmask);
// read var WIFIgateway from address 128, 16 byte long
EEPROM.get(128, WIFIgateway);
// read var WIFIgateway from address 128, 16 byte long
EEPROM.get(144, WIFIdns);
// read var WIFIuseDHCP from Address 160, 1 byte long
EEPROM.get(160, WIFIuseDHCP);
/*
* System settings
*/
// size is 1 byte
EEPROM.get(161, configured);
if(configured == true) {
// size is 1 byte
EEPROM.get(162, UseFan);
// size is 1 byte
EEPROM.get(163, UsePump);
// size is 1 byte
EEPROM.get(164, PumpOnTime);
// size is 1 byte
EEPROM.get(165, MoistureSensor_Type);
// size is 1 byte
EEPROM.get(166, SoilmoistureLow);
// size is 2 byte
EEPROM.get(167, NtpOffset);
// size is 1 byte
EEPROM.get(169, UseLEDrelais);
// size is 1 byte
EEPROM.get(214, TemperatureSensor_Type);
// size is 1 byte
EEPROM.get(215, UseFANrelais);
// size is 2 byte
EEPROM.get(219, MaintenanceDuration);
// size is 16 byte
EEPROM.get(221, Esp32CamIP);
}
// TODO auth does not work atm
// EEPROM.get(160, WebUiUsername);
// EEPROM.get(176, WebUiPassword);
/*
* Grow settings
*/
// size is 32 byte
EEPROM.get(170, GrowName);
if(strlen(GrowName) > 0) {
// size is 4 byte
EEPROM.get(202, GrowStart);
// size is 1 byte
EEPROM.get(206, DaysVeg);
// size is 1 byte
EEPROM.get(207, DaysBloom);
// size is 1 byte
EEPROM.get(208, LighthoursVeg);
// size is 1 byte
EEPROM.get(209, LighthoursBloom);
// size is 1 byte
EEPROM.get(210, SunriseHour);
// size is 1 byte
EEPROM.get(211, SunriseMinute);
// size is 1 byte
EEPROM.get(212, DayOfGrow);
// size is 1 byte
EEPROM.get(213, PinLEDPWM);
// size is 1 byte
EEPROM.get(216, PinFANPWM);
EEPROM.get(217, SunFade);
EEPROM.get(218, SunFadeDuration);
}
// print values to Serial output
Serial.println("---- WiFi values ----");
Serial.print("WIFIssid: ");
Serial.println(WIFIssid);
Serial.print("WIFIpassword: ");
Serial.println(WIFIpassword);
Serial.print("Use DHCP: ");
Serial.println(WIFIuseDHCP);
Serial.println("---- System values ----");
Serial.print("configured: ");
Serial.println(configured);
Serial.print("UseFan: ");
Serial.println(UseFan);
Serial.print("UsePump: ");
Serial.println(UsePump);
Serial.print("PumpOnTime: ");
Serial.println(PumpOnTime);
Serial.print("MoistureSensor_Type: ");
Serial.println(MoistureSensor_Type);
Serial.print("TemperatureSensor_Type: ");
Serial.println(TemperatureSensor_Type);
Serial.print("SoilmoistureLow: ");
Serial.println(SoilmoistureLow);
Serial.print("NtpOffset: ");
Serial.println(NtpOffset);
Serial.print("UseLEDrelais: ");
Serial.println(UseLEDrelais);
Serial.print("UseFANrelais: ");
Serial.println(UseFANrelais);
Serial.print("MaintenanceDuration: ");
Serial.println(MaintenanceDuration);
Serial.println("---- Grow values ----");
Serial.print("GrowName: ");
Serial.println(GrowName);
Serial.print("GrowStart: ");
Serial.println(GrowStart);
Serial.print("DaysVeg: ");
Serial.println(DaysVeg);
Serial.print("DaysBloom: ");
Serial.println(DaysBloom);
Serial.print("LighthoursVeg: ");
Serial.println(LighthoursVeg);
Serial.print("LighthoursBloom: ");
Serial.println(LighthoursBloom);
Serial.print("SunriseHour: ");
Serial.println(SunriseHour);
Serial.print("SunriseMinute: ");
Serial.println(SunriseMinute);
Serial.print("DayOfGrow: ");
Serial.println(DayOfGrow);
Serial.print("PinLEDPWM: ");
Serial.println(PinLEDPWM);
Serial.print("PinFANPWM: ");
Serial.println(PinFANPWM);
Serial.print("SunFade: ");
Serial.println(SunFade);
Serial.print("SunFadeDuration: ");
Serial.println(SunFadeDuration);
} else {
Serial.println("EEPROM value WIFIssid is empty");
}
Serial.println(":: EEPROM loaded ::");
display.setCursor(0,42);
display.println("EEPROM loaded");
display.display();
return(strlen(WIFIssid));
}
void wifiConnect() {
Serial.println(":: Connecting to WiFi ::");
FirstRun = false;
Serial.print("SSID: ");
Serial.println(WIFIssid);
display.fillRect(0,36,128,64-36, 0);
display.setCursor(0,36);
display.println("Connecting to WiFi");
display.println(WIFIssid);
display.display();
// Start WiFi connection
WiFi.begin(WIFIssid, WIFIpassword);
if(WIFIuseDHCP == false) {
WiFi.config(WIFIip, WIFIdns, WIFIgateway, WIFInetmask);
}
// wait until WiFi connection is established
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.println(":: Getting time from NTP ::");
display.fillRect(0,36,128,64-36, 0);
display.setCursor(0,36);
display.println("Getting NTP time");
display.display();
timeClient.begin();
timeClient.setTimeOffset(NtpOffset * 60 * 60);
timeClient.update();
while ( ! timeClient.isTimeSet()) {
timeClient.update();
delay(500);
Serial.print(".");
}
Serial.println(timeClient.getFormattedTime());
Serial.println(timeClient.getEpochTime());
display.println(timeClient.getFormattedTime());
display.display();
display.print("IP: ");
display.print(WiFi.localIP());
display.display();
}
void wifiAp() {
Serial.println(":: Creating Accesspoint ::");
display.fillRect(0,36,128,64-36, 0);
display.setCursor(0,36);
display.println("Creating AccessPoint");
display.println(APssid);
display.display();
FirstRun = true;
// configure WiFi Access Point
WiFi.softAPConfig(WIFIip, WIFIgateway, WIFInetmask);
// start Access Point
// TODO make AP with password - does not work atm. idk why.
WiFi.softAP(APssid);
Serial.print("SSID: ");
Serial.println(APssid);
Serial.print("CanGrow IP address: ");
Serial.println(WiFi.softAPIP());
display.print("IP: ");
display.println(WiFi.softAPIP());
display.display();
// TODO does not work atm, idk why
//Serial.println("The login credentials for the WebUI are 'cangrow' for username and password");
}
void setOutput(byte Output, byte OutputState) {
/*
* Pin assignments
*
* 1 - LED
* 2 - FAN
* 3 - PUMP
*
*/
bool UseRelais = true;
byte OutputPin;
switch(Output) {
case 1:
OutputPin = PinLED;
if(UseLEDrelais == true) {
UseRelais = true;
} else {
UseRelais = false;
}
break;
case 2:
OutputPin = PinFAN;
if(UseFANrelais == true) {
UseRelais = true;
} else {
UseRelais = false;
}
break;
// PUMP Pin (D0) does not support PWM, so we do not need to care about
case 3:
OutputPin = PinPUMP;
break;
}
//~ Serial.print("Output: ");
//~ Serial.println(Output);
//~ Serial.print("OutputPin: ");
//~ Serial.println(OutputPin);
//~ Serial.print("OutputState: ");
//~ Serial.println(OutputState);
//~ Serial.print("UseRelais: ");
//~ Serial.println(UseRelais);
if( (UseRelais == true) || (OutputPin == PinPUMP) ) {
digitalWrite(OutputPin, OutputState);
} else {
analogWrite(OutputPin, OutputState);
}
}
void controlLED() {
byte lightHours;
byte PinLEDPWM_tmp;
unsigned int secondsSunrise = (SunriseHour * 60 * 60) + (SunriseMinute * 60);
unsigned int secondsToday = (timeClient.getHours() * 60 * 60) + (timeClient.getMinutes() * 60) + timeClient.getSeconds();
if(DayOfGrow > DaysVeg ) {
lightHours = LighthoursBloom;
} else {
lightHours = LighthoursVeg;
}
// check if secondsToday is larger then secondsSunrise time AND if
// secondsToday is smaller then the sum of secondsSunrise + seconds of lightHours
if( ((secondsToday >= secondsSunrise) && (secondsToday <= ( secondsSunrise + (lightHours * 60 * 60))) ) ){
//Serial.println("light on time");
// when SunFade is true, fade LED light. Otherwise just turn on or off
if( (SunFade == true) && (UseLEDrelais == false) && (secondsSunrise + SunFadeDuration * 60 >= secondsToday) ) {
// in the first n minutes of lighting (SunFadeDuration), we want
// to raise the light slowly to prevent stress from the plant
// convert progress sunrise to PWM value
PinLEDPWM_tmp = (SunFadeDuration * 60 - ((secondsSunrise + SunFadeDuration * 60) - secondsToday)) * PinLEDPWM / (SunFadeDuration * 60);
setOutput(1, PinLEDPWM_tmp);
//Serial.print("sunrise PWM; ");
//Serial.println(PinLEDPWM_tmp);
} else if( (SunFade == true) && (UseLEDrelais == false) && (secondsToday >= ((secondsSunrise + lightHours * 60 * 60) - SunFadeDuration * 60) ) ) {
// calculate progress sunset to PWM value
PinLEDPWM_tmp = (secondsSunrise + (lightHours * 60 * 60) - secondsToday) * PinLEDPWM / (SunFadeDuration * 60);
setOutput(1, PinLEDPWM_tmp);
//Serial.print("sunset PWM: ");
//Serial.println(PinLEDPWM_tmp);
} else {
//Serial.println("just turn on the light");
// no sunrise or sunset, just keep the LED turned on
setOutput(1, PinLEDPWM);
}
} else {
//Serial.println("good night time");
// turn off
setOutput(1, 0);
}
}
void refreshSensors() {
valSoilmoisture = getSoilmoisture(MoistureSensor_Type);
valHumidity = getHumidity();
valTemperature = getTemperature(TemperatureSensor_Type);
valWaterlevel = getWaterlevel();
}
void displayScreens() {
/*
* which screen to display
* interate through different screens
*
*/
if(ScreenIterationPassed > DisplayScreenDuration){
ScreenIterationPassed = 0;
// helper variable, maybe i find a better way in future
byte LastScreen = 2;
// when the next screen gets displayed, clear display
display.clearDisplay();
display.display();
// when ScreenToDisplay has reach last number of screens, reset to first (0)
if(ScreenToDisplay >= LastScreen) {
ScreenToDisplay = 0;
} else {
ScreenToDisplay++;
}
}
display.setCursor(0,0);
if(MaintenanceMode == true) {
display.drawBitmap(0, 0, bmpCanGrow_Logo, 128, 32, WHITE);
display.display();
display.setCursor(0,32);
display.println("Maintenance mode active");
display.print("Time left: ");
display.print(MaintenanceDuration - ((millis() - MaintenanceStarted) / 1000));
display.println("s");
} else {
// in this switch case the single screens gets defined
switch(ScreenToDisplay) {
case 0:
display.print("Humidity: ");
display.print(valHumidity);
display.println(" %");
display.println("");
display.print("Temperature: ");
display.print(valTemperature);
display.println(" C");
display.println("");
display.print("Moisture: ");
display.print(valSoilmoisture);
display.println(" %");
display.println("");
if(UsePump == true) {
display.print("Pump Waterlvl: ");
switch(valWaterlevel) {
case 0:
display.println("OK");
break;
case 1:
display.println("Warn");
break;
case 2:
display.println("Crit");
break;
}
}
break;
case 1:
display.print("LED: ");
display.print(PinLEDPWM * 100 / 255);
display.println(" %");
display.print("State: ");
display.println(digitalRead(PinLED));
display.println("");
display.print("FAN: ");
display.print(PinFANPWM * 100 / 255);
display.println(" %");
display.print("State: ");
display.println(digitalRead(PinFAN));
display.println("");
display.print("Pump state: ");
display.println(digitalRead(PinPUMP));
break;
case 2:
// display Logo
display.drawBitmap(0, 0, bmpCanGrow_Logo, 128, 32, WHITE);
display.display();
display.setCursor(0,32);
display.println(GrowName);
display.print("DoG: ");
display.print(DayOfGrow);
display.print(", ");
display.println(timeClient.getFormattedTime());
display.print("IP: ");
display.println(WiFi.localIP());
break;
}
}
ScreenIterationPassed++;
display.display();
}