firmware wip - add sun fading , some reorganizing

This commit is contained in:
Marcus 2024-04-30 00:54:08 +02:00
parent 7842fadb15
commit eb0f91e313
1 changed files with 169 additions and 115 deletions

View File

@ -95,7 +95,7 @@ char WebUiPassword[32] = "cangrow";
// configured - if false, let the user configure system settings first
bool configured = false;
// NTP Offset
short ntpOffset;
short NtpOffset;
// MoistureSensor_Type - contains which moisture sensor to use
// 1: analog capacitive sensor
// 2: I2C chirp sensor from catnip electronics
@ -138,10 +138,14 @@ byte LighthoursBloom = 12;
byte SunriseHour = 7;
// SunriseHour - contains to which minute of SunriseHour the growlight turns on
byte SunriseMinute = 0;
// PINled_PWM - contains the PWM value for dimming the grow light
// PINledPWM - contains the PWM value for dimming the grow light
// default is 255 to ensure it is just on for the case UseLEDrelais is true
byte PINled_PWM = 255;
byte PINfan_PWM = 255;
byte PINledPWM = 255;
byte PINfanPWM = 255;
// fade in and out sunrise and sunset?
bool SunFade;
byte SunFadeDuration = 30;
/*
*
@ -354,11 +358,11 @@ function convertDateToEpoch(src, dst) {
*
* Pin assignments
*
* D0 - MOSFET Fan
* D0 - MOSFET Pump
* D1, D2 - I2C
* D3 - DHT11
* D4 - PIN_WIPE
* D5 - MOSFET Pump
* D5 - MOSFET Fan
* D6 - MOSFET Grow LED, PWM
* D7 - waterlevel (set HIGH to read value)
* D8 - analog soil moisture (set HIGH to read value)
@ -692,7 +696,7 @@ bool loadEEPROM() {
* 164 PumpOnTime
* 165 MoistureSensor_Type
* 166 SoilmoistureLow
* 167 ntpOffset
* 167 NtpOffset
* 169 UseLEDrelais
*
* 170 GrowName
@ -707,10 +711,12 @@ bool loadEEPROM() {
*
* -- afterwards added, need to sort --
*
* 213 PINled_PWM
* 213 PINledPWM
* 214 TemperatureSensor_Type
* 215 UseFANrelais
* 216 PINfan_PWM
* 216 PINfanPWM
* 217 SunFade
* 218 SunFadeDuration
*
*/
@ -763,20 +769,13 @@ bool loadEEPROM() {
// size is 1 byte
EEPROM.get(166, SoilmoistureLow);
// size is 2 byte
EEPROM.get(167, ntpOffset);
EEPROM.get(167, NtpOffset);
// size is 1 byte
EEPROM.get(169, UseLEDrelais);
// size is 1 byte
// I forgot to add TemperatureSensor_Type to EEPROM and noticed it
// quite late in the process of programming. So this value residents
// in 214 and not directly after UseLEDrelais
EEPROM.get(213, PINled_PWM);
// size is 1 byte
EEPROM.get(214, TemperatureSensor_Type);
// size is 1 byte
EEPROM.get(215, UseFANrelais);
// size is 1 byte
EEPROM.get(216, PINfan_PWM);
}
// TODO auth does not work atm
// EEPROM.get(160, WebUiUsername);
@ -805,6 +804,12 @@ bool loadEEPROM() {
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);
}
@ -833,8 +838,8 @@ bool loadEEPROM() {
Serial.println(MoistureSensor_Type);
Serial.print("SoilmoistureLow: ");
Serial.println(SoilmoistureLow);
Serial.print("ntpOffset: ");
Serial.println(ntpOffset);
Serial.print("NtpOffset: ");
Serial.println(NtpOffset);
Serial.print("UseLEDrelais: ");
Serial.println(UseLEDrelais);
Serial.print("UseFANrelais: ");
@ -859,10 +864,14 @@ bool loadEEPROM() {
Serial.println(SunriseMinute);
Serial.print("DayOfGrow: ");
Serial.println(DayOfGrow);
Serial.print("PINled_PWM: ");
Serial.println(PINled_PWM);
Serial.print("PINfan_PWM: ");
Serial.println(PINfan_PWM);
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 {
@ -911,7 +920,7 @@ void wifiConnect() {
display.display();
timeClient.begin();
timeClient.setTimeOffset(ntpOffset * 60 * 60);
timeClient.setTimeOffset(NtpOffset * 60 * 60);
timeClient.update();
while ( ! timeClient.isTimeSet()) {
timeClient.update();
@ -951,6 +960,51 @@ void wifiAp() {
//Serial.println("The login credentials for the WebUI are 'cangrow' for username and password");
}
void setOutput(byte pin, byte pinState) {
/*
* Pin assignments
*
* 1 - LED
* 2 - FAN
* 3 - PUMP
*
*/
switch(pin) {
case 1:
if(pinState > 0) {
if(UseLEDrelais == true) {
digitalWrite(PINled, HIGH);
} else {
analogWrite(PINled, PINledPWM);
}
} else {
digitalWrite(PINled, LOW);
}
break;
case 2:
if(pinState > 0) {
if(UseFANrelais == true) {
digitalWrite(PINfan, HIGH);
} else {
analogWrite(PINfan, PINledPWM);
}
} else {
digitalWrite(PINfan, LOW);
}
break;
// PUMP Pin (D0) does not support PWM, so we do not need to care about
case 3:
if(pinState > 0) {
digitalWrite(PINpump, HIGH);
} else {
digitalWrite(PINpump, LOW);
}
break;
}
}
/*
* Setup
*
@ -1068,8 +1122,9 @@ void setup() {
// set web handler
WebHandler();
// start webserver
webserver.begin();
webserver.begin();
Serial.println(".:: CanGrow Ready ::.");
}
@ -1086,18 +1141,16 @@ void loop() {
unsigned int secondsToday = (timeClient.getHours() * 60 * 60) + (timeClient.getMinutes() * 60) + timeClient.getSeconds();
unsigned long currentRuntime = millis();
byte lightHours;
byte PINledPWM_tmp;
// first we call webserver handle client
webserver.handleClient();
// do every second when everything is configured
// do every second when everything is configured and grow is started
if( (configured == true) && (strlen(GrowName) > 0) && (currentRuntime - outputPrevTime >= 1000) ){
// debug output
Serial.print("secondsSunrise: ");
Serial.println(secondsSunrise);
Serial.print("secondsToday: ");
Serial.println(secondsToday);
//Serial.println("yolo");
/*
* LED controlling
*/
// calculate acutal DayOfGrow
DayOfGrow = int(ceil(float((timeClient.getEpochTime() - GrowStart) / 60 / 60 / 24)));
@ -1109,17 +1162,31 @@ void loop() {
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) ) )){
// turn on light
// check if secondsToday is larger then secondsSunrise time AND if
// secondsToday is smaller then the sum of secondsSunrise + seconds of lightHours
if( (SunFade == true) && ((secondsToday >= secondsSunrise) && (secondsToday <= ( secondsSunrise + (lightHours * 60 * 60))) ) ){
// in the first n minutes of lighting (SunFadeDuration), we want
//to raise the light slowly to prevent stress from the plant
if(secondsSunrise + SunFadeDuration * 60 >= secondsToday) {
// convert progress sunrise to PWM value
PINledPWM_tmp = (SunFadeDuration * 60 - ((secondsSunrise + SunFadeDuration * 60) - secondsToday)) * 255 / (SunFadeDuration * 60);
} else if( (SunFade == true) && (secondsToday >= ((secondsSunrise + lightHours * 60 * 60) - SunFadeDuration * 60) ) ) {
// calculate progress sunset to PWM value
PINledPWM_tmp = (secondsSunrise + (lightHours * 60 * 60) - secondsToday) * 255 / (SunFadeDuration * 60);
} else {
// no sunrise or sunset, just keep the LED turned on
setOutput(1, PINledPWM);
}
// TODO write a LED control function which takes also takes care of UseLEDrelais
analogWrite(PINled, PINled_PWM);
} else {
// turn off
digitalWrite(PINled, LOW);
setOutput(1, 0);
}
// current time gets previous time for new interval
outputPrevTime = currentRuntime;
}
@ -1176,7 +1243,7 @@ void WebHandler() {
webserver.onNotFound(WEB404);
// switching MOSFETs
webserver.on("/switch", HTTP_POST, POSTswitchMOSFET);
webserver.on("/switch", HTTP_POST, POSTsetOutput);
// api stuff
webserver.on("/api/sensors", HTTP_GET, APIgetSensors);
@ -1433,7 +1500,7 @@ void WEBroot() {
}
body += "<br>";
body += "Growlight brightnes: ";
body += ((PINled_PWM * 100) / 255);
body += ((PINledPWM * 100) / 255);
body += " %<br>";
body += "<form method='post' action='/switch'>";
body += "MOSFET<select id='output' name='output' required>\n";
@ -1450,8 +1517,8 @@ void WEBroot() {
body += "</select><br>\n";
if(UseFANrelais == false) {
body += "Speed FAN: <input type='range' id='PINfan_PWM' name='PINfan_PWM' min='1' max='255' value='";
body += PINfan_PWM;
body += "Speed FAN: <input type='range' id='PINfanPWM' name='PINfanPWM' min='1' max='255' value='";
body += PINfanPWM;
body += "'/><br>\n";
}
@ -1620,9 +1687,9 @@ void WEBsystemSettings() {
body += "<option value='2'" + returnStrSelected(TemperatureSensor_Type, 2) + ">I2C chirp</option>\n";
body += "</select><br>\n";
// ntpOffset int
body += "NTP offset: <input type='number' name='ntpOffset' min='-12' max='14' value='";
body += ntpOffset;
// NtpOffset int
body += "NTP offset: <input type='number' name='NtpOffset' min='-12' max='14' value='";
body += NtpOffset;
body+= "' required><br>\n";
body += "<input type='submit' value='Save'>\n";
@ -1703,15 +1770,25 @@ void WEBgrowSettings() {
body += SunriseMinute;
body+= "' required><br>\n";
// SunFade bool
body += "Fade in and out LED?: <select id='SunFade' name='SunFade' required>\n";
body += "<option value='1'" + returnStrSelected(SunFade, 1) + ">Yes</option>\n";
body += "<option value='0'" + returnStrSelected(SunFade, 0) + ">No</option>\n";
body += "</select><br>\n";
body += "Fading duration (minutes): <input type='number' name='SunFadeDuration' min='0' max='255' value='";
body += SunFadeDuration;
body+= "' required><br>\n";
if(UseLEDrelais == false) {
body += "Brightness LED: <input type='range' id='PINled_PWM' name='PINled_PWM' min='1' max='255' value='";
body += PINled_PWM;
body += "Brightness LED: <input type='range' id='PINledPWM' name='PINledPWM' min='1' max='255' value='";
body += PINledPWM;
body += "'/><br>\n";
}
if(UseFANrelais == false) {
body += "Speed FAN: <input type='range' id='PINfan_PWM' name='PINfan_PWM' min='1' max='255' value='";
body += PINfan_PWM;
body += "Speed FAN: <input type='range' id='PINfanPWM' name='PINfanPWM' min='1' max='255' value='";
body += PINfanPWM;
body += "'/><br>\n";
}
@ -1735,18 +1812,18 @@ void POSTgrowSettings() {
if(UseLEDrelais == true) {
// if a relais is used to turn on grow light, we force PWM to max val
PINled_PWM = 255;
PINledPWM = 255;
} else {
// otherwise just do PWM
PINled_PWM = webserver.arg("PINled_PWM").toInt();
PINledPWM = webserver.arg("PINledPWM").toInt();
}
if(UseFANrelais == true) {
// if a relais is used to turn on grow light, we force PWM to max val
PINfan_PWM = 255;
PINfanPWM = 255;
} else {
// otherwise just do PWM
PINfan_PWM = webserver.arg("PINfan_PWM").toInt();
PINfanPWM = webserver.arg("PINfanPWM").toInt();
}
String GrowName_tmp = webserver.arg("GrowName");
@ -1760,6 +1837,8 @@ void POSTgrowSettings() {
LighthoursBloom = webserver.arg("LighthoursBloom").toInt();
SunriseHour = webserver.arg("SunriseHour").toInt();
SunriseMinute = webserver.arg("SunriseMinute").toInt();
SunFade = webserver.arg("SunFade").toInt();
SunFadeDuration = webserver.arg("SunFadeDuration").toInt();
// size is 32 byte
EEPROM.put(170, GrowName);
@ -1778,17 +1857,18 @@ void POSTgrowSettings() {
// size is 1 byte
EEPROM.put(211, SunriseMinute);
// size is 1 byte
EEPROM.put(213, PINled_PWM);
EEPROM.put(213, PINledPWM);
// size is 1 byte
EEPROM.put(216, PINfan_PWM);
EEPROM.put(216, PINfanPWM);
EEPROM.put(217, SunFade);
EEPROM.put(218, SunFadeDuration);
EEPROM.commit();
//analogWrite(PINled, PINled_PWM);
//analogWrite(PINled, PINledPWM);
Serial.println(":: POSTgrowSettings ::");
@ -1808,10 +1888,10 @@ void POSTgrowSettings() {
Serial.println(SunriseHour);
Serial.print("SunriseMinute: ");
Serial.println(SunriseMinute);
Serial.print("PINled_PWM: ");
Serial.println(PINled_PWM);
Serial.print("PINfan_PWM: ");
Serial.println(PINfan_PWM);
Serial.print("PINledPWM: ");
Serial.println(PINledPWM);
Serial.print("PINfanPWM: ");
Serial.println(PINfanPWM);
webserver.sendHeader("Location", String("/growSettings?success"), true);
webserver.send(302, "text/plain", "growSettings/save: success!\n");
@ -1819,7 +1899,7 @@ void POSTgrowSettings() {
void POSTsystemSettings() {
ntpOffset = webserver.arg("ntpOffset").toInt();
NtpOffset = webserver.arg("NtpOffset").toInt();
MoistureSensor_Type = webserver.arg("MoistureSensor_Type").toInt();
SoilmoistureLow = webserver.arg("SoilmoistureLow").toInt();
UsePump = webserver.arg("UsePump").toInt();
@ -1844,7 +1924,7 @@ void POSTsystemSettings() {
// size is 1 byte
EEPROM.put(166, SoilmoistureLow);
// size is 2 byte
EEPROM.put(167, ntpOffset);
EEPROM.put(167, NtpOffset);
// size is 1 byte
EEPROM.put(169, UseLEDrelais);
// size is 1 byte
@ -1858,25 +1938,25 @@ void POSTsystemSettings() {
// update time with new offset
timeClient.setTimeOffset(ntpOffset * 60 * 60);
timeClient.setTimeOffset(NtpOffset * 60 * 60);
timeClient.update();
Serial.println(":: POSTsystemSettings ::");
// when user uses an relais for LED control, we force here PINled_PWM to 255
// when user uses an relais for LED control, we force here PINledPWM to 255
// to ensure nothing bad happens
if(UseLEDrelais == true) {
PINled_PWM = 255;
EEPROM.put(213, PINled_PWM);
PINledPWM = 255;
EEPROM.put(213, PINledPWM);
EEPROM.commit();
Serial.println("UseLEDrelais is 1, forcing PINled_PWM to max to prevent relais damage");
Serial.println("UseLEDrelais is 1, forcing PINledPWM to max to prevent relais damage");
}
if(UseFANrelais == true) {
PINfan_PWM = 255;
EEPROM.put(215, PINfan_PWM);
PINfanPWM = 255;
EEPROM.put(215, PINfanPWM);
EEPROM.commit();
Serial.println("UseFANrelais is 1, forcing PINfan_PWM to max to prevent relais damage");
Serial.println("UseFANrelais is 1, forcing PINfanPWM to max to prevent relais damage");
}
Serial.print("configured: ");
@ -1891,8 +1971,8 @@ void POSTsystemSettings() {
Serial.println(MoistureSensor_Type);
Serial.print("SoilmoistureLow: ");
Serial.println(SoilmoistureLow);
Serial.print("ntpOffset: ");
Serial.println(ntpOffset);
Serial.print("NtpOffset: ");
Serial.println(NtpOffset);
Serial.print("UseLEDrelais: ");
Serial.println(UseLEDrelais);
Serial.print("UseFANrelais: ");
@ -1972,53 +2052,26 @@ void POSTwifiSettings() {
}
void POSTswitchMOSFET() {
byte MosfetState = webserver.arg("state").toInt();
byte MosfetNr = webserver.arg("output").toInt();
byte PINfan_PWM = webserver.arg("PINfan_PWM").toInt();
void POSTsetOutput() {
byte OutputState = webserver.arg("state").toInt();
byte OutputNr = webserver.arg("output").toInt();
PINledPWM = webserver.arg("PINledPWM").toInt();
PINfanPWM = webserver.arg("PINfanPWM").toInt();
Serial.println(":: GETswitchMOSFET ::");
Serial.print("MosfetState: ");
Serial.println(MosfetState);
Serial.print("MosfetNr: ");
Serial.println(MosfetNr);
Serial.print("OutputState: ");
Serial.println(OutputState);
Serial.print("OutputNr: ");
Serial.println(OutputNr);
if((MosfetState > 1) || (MosfetState < 0)) {
if((OutputNr > 3) || (OutputNr < 1) || (OutputState > 255) || (OutputState < 255)) {
webserver.send(400, "text/plain", "not valid\n");
} else {
switch(MosfetNr) {
case 1:
if(MosfetState == 1) {
if(UseLEDrelais == true) {
digitalWrite(PINled, MosfetState);
} else {
analogWrite(PINled, PINled_PWM);
}
} else {
digitalWrite(PINled, MosfetState);
}
break;
case 2:
digitalWrite(PINpump, MosfetState);
break;
case 3:
if(MosfetState == 1) {
if(UseFANrelais == true) {
digitalWrite(PINfan, MosfetState);
} else {
analogWrite(PINfan, PINfan_PWM);
}
} else {
digitalWrite(PINfan, MosfetState);
}
break;
default:
webserver.send(400, "text/plain", "not valid\n");
break;
setOutput(OutputNr, OutputState);
webserver.sendHeader("Location", String("/?success"), true);
webserver.send(302, "text/plain", "switch: success!\n");
}
webserver.sendHeader("Location", String("/?success"), true);
webserver.send(302, "text/plain", "switch: success!\n");
}
}
@ -2065,6 +2118,7 @@ void APIgetSensors() {
* - when PWM for fan is set, set fan speed to regulate humidity and
* temperature
* - re-organize EEPROM saved values.
* - prevent GrowStart to be in the future
*
*
*/