From 9b27df7172735b793b02bbf7733e447023666a19 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 16:43:26 +0200 Subject: [PATCH 1/9] OTA flashing is disabling deepsleep at start --- esp32/src/main.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 0c8d54d..5125980 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -17,6 +17,7 @@ #include "esp_sleep.h" #include "RunningMedian.h" #include +#include const unsigned long TEMPREADCYCLE = 30000; /**< Check temperature all half minutes */ @@ -305,9 +306,6 @@ void readSensors() { digitalWrite(OUTPUT_SENSOR, LOW); } - - - //Homie.getMqttClient().disconnect(); void onHomieEvent(const HomieEvent& event) { @@ -333,6 +331,17 @@ void onHomieEvent(const HomieEvent& event) { Homie.getLogger() << "rtsleep" << endl; esp_deep_sleep_start(); break; + case HomieEventType::OTA_STARTED: + Serial.println("OTA DS Disabled"); + mode3Active=true; + break; + case HomieEventType::OTA_SUCCESSFUL: + Serial.println("OTA DS reenabled"); + mode3Active=false; + break; + default: + printf("Event %d\r\n", (uint8_t) event.type); + break; } } @@ -415,13 +424,13 @@ bool switchGeneralPumpHandler(const int pump, const HomieRange& range, const Str */ bool aliveHandler(const HomieRange& range, const String& value) { if (range.isRange) return false; // only one controller is present + Serial << value << endl; if (value.equals("ON") || value.equals("On") || value.equals("1")) { mode3Active=true; } else { mode3Active=false; - esp_deep_sleep_start(); } - Serial << (mode3Active ? "stayalive" : "") << endl; + return true; } @@ -690,9 +699,12 @@ void setup() { void loop() { Homie.loop(); + if(mode3Active){ + digitalWrite(OUTPUT_SENSOR, HIGH); + } if(millis() > 30000 && !mode3Active){ - Serial << (millis()/ 1000) << " ds watchdog" << endl; + Serial << (millis()/ 1000) << "s gone" << endl; Serial.flush(); esp_deep_sleep_start(); } From 04cb8bbaf0802c953cf8aeacb16769cd617a2674 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 16:57:57 +0200 Subject: [PATCH 2/9] Status LED for flashing --- esp32/src/main.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 5125980..9ee043e 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -147,10 +147,11 @@ void mode2MQTT(){ float temp[2] = { TEMP_INIT_VALUE, TEMP_INIT_VALUE }; float* pFloat = temp; int devices = dallas.readAllTemperatures(pFloat, 2); + if (devices < 2) { if ((pFloat[0] > TEMP_INIT_VALUE) && (pFloat[0] < TEMP_MAX_VALUE) ) { sensorTemp.setProperty("control").send( String(pFloat[0])); - } + } } else if (devices >= 2) { if ((pFloat[0] > TEMP_INIT_VALUE) && (pFloat[0] < TEMP_MAX_VALUE) ) { sensorTemp.setProperty("temp").send( String(pFloat[0])); @@ -270,7 +271,6 @@ void readSensors() { } } - Serial << "DS18B20" << endl; /* Read the temperature sensors once, as first time 85 degree is returned */ Serial << "DS18B20" << String(dallas.readDevices()) << endl; delay(200); @@ -322,9 +322,7 @@ void onHomieEvent(const HomieEvent& event) { //wait for rtc sync? rtcDeepSleepTime = deepSleepTime.get(); - if(!mode3Active){ - mode2MQTT(); - } + mode2MQTT(); Homie.getLogger() << "MQTT 1" << endl; break; case HomieEventType::READY_TO_SLEEP: @@ -332,11 +330,11 @@ void onHomieEvent(const HomieEvent& event) { esp_deep_sleep_start(); break; case HomieEventType::OTA_STARTED: - Serial.println("OTA DS Disabled"); + digitalWrite(OUTPUT_SENSOR, HIGH); mode3Active=true; break; case HomieEventType::OTA_SUCCESSFUL: - Serial.println("OTA DS reenabled"); + digitalWrite(OUTPUT_SENSOR, LOW); mode3Active=false; break; default: @@ -699,9 +697,6 @@ void setup() { void loop() { Homie.loop(); - if(mode3Active){ - digitalWrite(OUTPUT_SENSOR, HIGH); - } if(millis() > 30000 && !mode3Active){ Serial << (millis()/ 1000) << "s gone" << endl; From 579e7daa93768e7020df523cc5fc2b75185c4f62 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 18:14:51 +0200 Subject: [PATCH 3/9] onHomieEvent set --- esp32/platformio.ini | 1 + esp32/src/main.cpp | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/esp32/platformio.ini b/esp32/platformio.ini index e0e7544..ec166b1 100644 --- a/esp32/platformio.ini +++ b/esp32/platformio.ini @@ -19,3 +19,4 @@ board_build.partitions = defaultWithSmallerSpiffs.csv lib_deps = ArduinoJson@6.16.1 https://github.com/homieiot/homie-esp8266.git#v3.0 OneWire + DallasTemperature diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 9ee043e..e8fe5ff 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -147,11 +147,10 @@ void mode2MQTT(){ float temp[2] = { TEMP_INIT_VALUE, TEMP_INIT_VALUE }; float* pFloat = temp; int devices = dallas.readAllTemperatures(pFloat, 2); - if (devices < 2) { if ((pFloat[0] > TEMP_INIT_VALUE) && (pFloat[0] < TEMP_MAX_VALUE) ) { sensorTemp.setProperty("control").send( String(pFloat[0])); - } + } } else if (devices >= 2) { if ((pFloat[0] > TEMP_INIT_VALUE) && (pFloat[0] < TEMP_MAX_VALUE) ) { sensorTemp.setProperty("temp").send( String(pFloat[0])); @@ -271,6 +270,7 @@ void readSensors() { } } + Serial << "DS18B20" << endl; /* Read the temperature sensors once, as first time 85 degree is returned */ Serial << "DS18B20" << String(dallas.readDevices()) << endl; delay(200); @@ -311,7 +311,16 @@ void readSensors() { void onHomieEvent(const HomieEvent& event) { const String OFF = String("OFF"); switch(event.type) { + case HomieEventType::SENDING_STATISTICS: + mode2MQTT(); + Homie.getLogger() << "My statistics" << endl; + break; case HomieEventType::MQTT_READY: + //wait for rtc sync? + rtcDeepSleepTime = deepSleepTime.get(); + mode2MQTT(); + Homie.getLogger() << "MQTT 1" << endl; + plant0.setProperty("switch").send(OFF); plant1.setProperty("switch").send(OFF); plant2.setProperty("switch").send(OFF); @@ -320,10 +329,6 @@ void onHomieEvent(const HomieEvent& event) { plant5.setProperty("switch").send(OFF); plant6.setProperty("switch").send(OFF); - //wait for rtc sync? - rtcDeepSleepTime = deepSleepTime.get(); - mode2MQTT(); - Homie.getLogger() << "MQTT 1" << endl; break; case HomieEventType::READY_TO_SLEEP: Homie.getLogger() << "rtsleep" << endl; @@ -335,7 +340,6 @@ void onHomieEvent(const HomieEvent& event) { break; case HomieEventType::OTA_SUCCESSFUL: digitalWrite(OUTPUT_SENSOR, LOW); - mode3Active=false; break; default: printf("Event %d\r\n", (uint8_t) event.type); @@ -479,7 +483,7 @@ void systemInit(){ Homie_setFirmware("PlantControl", FIRMWARE_VERSION); // Set default values - deepSleepTime.setDefaultValue(300000); /* 5 minutes in milliseconds */ + deepSleepTime.setDefaultValue(30000); /* 30 seconds in milliseconds */ deepSleepNightTime.setDefaultValue(0); wateringDeepSleep.setDefaultValue(60000); /* 1 minute in milliseconds */ waterLevelMax.setDefaultValue(1000); /* 100cm in mm */ @@ -488,6 +492,7 @@ void systemInit(){ waterLevelVol.setDefaultValue(5000); /* 5l in ml */ Homie.setLoopFunction(homieLoop); + Homie.onEvent(onHomieEvent); Homie.setup(); mConfigured = Homie.isConfigured(); @@ -558,6 +563,11 @@ void systemInit(){ bool mode1(){ Serial.println("m1"); + + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + Serial << tv_now.tv_sec << " curtime" << endl; + readSensors(); //queue sensor values for @@ -699,7 +709,7 @@ void loop() { Homie.loop(); if(millis() > 30000 && !mode3Active){ - Serial << (millis()/ 1000) << "s gone" << endl; + Serial << (millis()/ 1000) << "s alive" << endl; Serial.flush(); esp_deep_sleep_start(); } From 73759eec68851483a8dec14c3e87ddcdda2d4f30 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 18:21:44 +0200 Subject: [PATCH 4/9] Sensor values are written and read in the same variable --- esp32/src/main.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index e8fe5ff..9c9ab39 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -57,11 +57,6 @@ bool mDeepSleep = false; int plantSensor1 = 0; -int lipoSenor = -1; -int lipoSensorValues = 0; -int solarSensor = -1; -int solarSensorValues = 0; - int mWaterGone = -1; /**< Amount of centimeter, where no water is seen */ int readCounter = 0; int mButtonClicks = 0; @@ -94,9 +89,7 @@ Plant mPlants[MAX_PLANTS] = { void readSystemSensors() { lipoRawSensor.add(analogRead(SENSOR_LIPO)); - solarRawSensor.add(analogRead(SENSOR_SOLAR)); - - + solarRawSensor.add(analogRead(SENSOR_SOLAR)); } int determineNextPump(); @@ -116,6 +109,8 @@ bool prepareSleep(void *) { } void mode2MQTT(){ + readSystemSensors(); + if (deepSleepTime.get()) { Serial << "sleeping for " << deepSleepTime.get() << endl; } @@ -139,10 +134,10 @@ void mode2MQTT(){ } } - sensorLipo.setProperty("percent").send( String(100 * lipoSenor / 4095) ); - sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoSenor)) ); - sensorSolar.setProperty("percent").send(String((100 * solarSensor ) / 4095)); - sensorSolar.setProperty("volt").send( String(SOLAR_VOLT(solarSensor)) ); + sensorLipo.setProperty("percent").send( String(100 * lipoRawSensor.getAverage() / 4095) ); + sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoRawSensor.getAverage())) ); + sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage() ) / 4095)); + sensorSolar.setProperty("volt").send( String(SOLAR_VOLT(solarRawSensor.getAverage())) ); float temp[2] = { TEMP_INIT_VALUE, TEMP_INIT_VALUE }; float* pFloat = temp; @@ -256,7 +251,9 @@ long getLastActivationForPump(int plantId){ * These sensors (ADC2) can only be read when no Wifi is used. */ void readSensors() { - Serial << "rs" << endl; + Serial << "Read Sensors" << endl; + + readSystemSensors(); /* activate all sensors */ pinMode(OUTPUT_SENSOR, OUTPUT); @@ -341,9 +338,6 @@ void onHomieEvent(const HomieEvent& event) { case HomieEventType::OTA_SUCCESSFUL: digitalWrite(OUTPUT_SENSOR, LOW); break; - default: - printf("Event %d\r\n", (uint8_t) event.type); - break; } } @@ -671,8 +665,8 @@ void setup() { // Configure Deep Sleep: if (mConfigured && (deepSleepNightTime.get() > 0) && - ( SOLAR_VOLT(solarSensor) < MINIMUM_SOLAR_VOLT)) { - Serial << deepSleepNightTime.get() << "ms ds " << SOLAR_VOLT(solarSensor) << "V" << endl; + ( SOLAR_VOLT(solarRawSensor.getAverage()) < MINIMUM_SOLAR_VOLT)) { + Serial << deepSleepNightTime.get() << "ms ds " << SOLAR_VOLT(solarRawSensor.getAverage()) << "V" << endl; uint64_t usSleepTime = deepSleepNightTime.get() * 1000U; esp_sleep_enable_timer_wakeup(usSleepTime); }else if (mConfigured && deepSleepTime.get()) { @@ -682,11 +676,11 @@ void setup() { } if (mConfigured && - (ADC_5V_TO_3V3(lipoSenor) < MINIMUM_LIPO_VOLT) && - (ADC_5V_TO_3V3(lipoSenor) > NO_LIPO_VOLT) && + (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) < MINIMUM_LIPO_VOLT) && + (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) > NO_LIPO_VOLT) && (deepSleepTime.get()) ) { long sleepEmptyLipo = (deepSleepTime.get() * EMPTY_LIPO_MULTIPL); - Serial << sleepEmptyLipo << " ms lipo " << ADC_5V_TO_3V3(lipoSenor) << "V" << endl; + Serial << sleepEmptyLipo << " ms lipo " << ADC_5V_TO_3V3(lipoRawSensor.getAverage()) << "V" << endl; esp_sleep_enable_timer_wakeup(sleepEmptyLipo * 1000U); mDeepSleep = true; } From 03be8a1bda5a6f14033596789112ea78b1d5005d Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 18:33:38 +0200 Subject: [PATCH 5/9] Deep sleep is now working --- esp32/include/ControllerConfiguration.h | 2 ++ esp32/src/main.cpp | 15 ++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/esp32/include/ControllerConfiguration.h b/esp32/include/ControllerConfiguration.h index 45d7c0e..3b036df 100644 --- a/esp32/include/ControllerConfiguration.h +++ b/esp32/include/ControllerConfiguration.h @@ -59,4 +59,6 @@ #define MAX_CONFIG_SETTING_ITEMS 50 /**< Parameter, that can be configured in Homie */ +#define PANIK_MODE_DEEPSLEEP 18000000000U /**< 5 hours in usecond */ + #endif diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 9c9ab39..fcc60ad 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -315,6 +315,9 @@ void onHomieEvent(const HomieEvent& event) { case HomieEventType::MQTT_READY: //wait for rtc sync? rtcDeepSleepTime = deepSleepTime.get(); + Serial << rtcDeepSleepTime << " ms ds" << endl; + esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) ); + mode2MQTT(); Homie.getLogger() << "MQTT 1" << endl; @@ -663,16 +666,10 @@ void setup() { // Big TODO use here the settings in RTC_Memory - // Configure Deep Sleep: - if (mConfigured && (deepSleepNightTime.get() > 0) && - ( SOLAR_VOLT(solarRawSensor.getAverage()) < MINIMUM_SOLAR_VOLT)) { + //Panik mode, the Lipo is empty, sleep a long long time: + if ( SOLAR_VOLT(solarRawSensor.getAverage()) < MINIMUM_SOLAR_VOLT) { Serial << deepSleepNightTime.get() << "ms ds " << SOLAR_VOLT(solarRawSensor.getAverage()) << "V" << endl; - uint64_t usSleepTime = deepSleepNightTime.get() * 1000U; - esp_sleep_enable_timer_wakeup(usSleepTime); - }else if (mConfigured && deepSleepTime.get()) { - Serial << deepSleepTime.get() << " ms ds" << endl; - uint64_t usSleepTime = deepSleepTime.get() * 1000U; - esp_sleep_enable_timer_wakeup(usSleepTime); + esp_sleep_enable_timer_wakeup(PANIK_MODE_DEEPSLEEP); } if (mConfigured && From 5591c6dba2a5954b459dd328e0bffd73f4414e68 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 19:50:05 +0200 Subject: [PATCH 6/9] Deep sleep is set according daylight --- esp32/include/ControllerConfiguration.h | 4 +- esp32/include/HomieConfiguration.h | 1 - esp32/src/main.cpp | 119 +++++++++++++++--------- 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/esp32/include/ControllerConfiguration.h b/esp32/include/ControllerConfiguration.h index 3b036df..0085256 100644 --- a/esp32/include/ControllerConfiguration.h +++ b/esp32/include/ControllerConfiguration.h @@ -46,7 +46,6 @@ #define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */ #define MAX_PLANTS 7 -#define EMPTY_LIPO_MULTIPL 3 /**< Multiplier to increase time for sleeping when lipo is empty */ #define MINIMUM_LIPO_VOLT 3.6f /**< Minimum voltage of the Lipo, that must be present */ #define NO_LIPO_VOLT 2.0f /**< No Lipo connected */ #define MINIMUM_SOLAR_VOLT 4.0f /**< Minimum voltage of the sun, to detect daylight */ @@ -59,6 +58,7 @@ #define MAX_CONFIG_SETTING_ITEMS 50 /**< Parameter, that can be configured in Homie */ -#define PANIK_MODE_DEEPSLEEP 18000000000U /**< 5 hours in usecond */ +#define PANIK_MODE_DEEPSLEEP (60*60*5U) /**< 5 hours in usecond */ +#define PANIK_MODE_DEEPSLEEP_US (PANIK_MODE_DEEPSLEEP*1000*1000) #endif diff --git a/esp32/include/HomieConfiguration.h b/esp32/include/HomieConfiguration.h index 510dd47..9146754 100644 --- a/esp32/include/HomieConfiguration.h +++ b/esp32/include/HomieConfiguration.h @@ -37,7 +37,6 @@ HomieNode stayAlive("stay", "alive", "alive"); /** *********************************** Settings ******************************* */ - HomieSetting deepSleepTime("deepsleep", "time in milliseconds to sleep (0 deactivats it)"); HomieSetting deepSleepNightTime("nightsleep", "time in milliseconds to sleep (0 uses same setting: deepsleep at night, too)"); HomieSetting wateringDeepSleep("pumpdeepsleep", "time seconds to sleep, while a pump is running"); diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index fcc60ad..1162215 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -29,6 +29,7 @@ const unsigned long TEMPREADCYCLE = 30000; /**< Check temperature all half minut /********************* non volatile enable after deepsleep *******************************/ +RTC_DATA_ATTR long gotoMode2AfterThisTimestamp = 0; RTC_DATA_ATTR long rtcDeepSleepTime = 0; /**< Time, when the microcontroller shall be up again */ RTC_DATA_ATTR long rtcLastActive0 = 0; RTC_DATA_ATTR long rtcMoistureTrigger0 = 0; /**= (MIN_TIME_RUNNING * MS_TO_S)) && (deepSleepTime.get() > 0)) { - Serial << "No W" << endl; - /* in 500 microseconds */ - wait4sleep.in(500, prepareSleep); - return; - } - } sensorLipo.setProperty("percent").send( String(100 * lipoRawSensor.getAverage() / 4095) ); sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoRawSensor.getAverage())) ); @@ -157,20 +166,37 @@ void mode2MQTT(){ bool lipoTempWarning = abs(temp[0] - temp[1]) > 5; if(lipoTempWarning){ - wait4sleep.in(500, prepareSleep); + Serial.println("Lipo temp incorrect, panic mode deepsleep"); + espDeepSleepFor(PANIK_MODE_DEEPSLEEP); return; } - digitalWrite(OUTPUT_PUMP, LOW); - for(int i=0; i < MAX_PLANTS; i++) { - digitalWrite(mPlants[i].mPinPump, LOW); - } + bool hasWater = mWaterGone > waterLevelMin.get(); + //FIXME no water warning message lastPumpRunning = determineNextPump(); - if(lastPumpRunning != -1){ + if(lastPumpRunning != -1 && hasWater){ setLastActivationForPump(lastPumpRunning, getCurrentTime()); digitalWrite(mPlants[lastPumpRunning].mPinPump, HIGH); } + float solarValue = solarRawSensor.getMedian(); + if(lastPumpRunning == -1 || !hasWater){ + if((ADC_5V_TO_3V3(solarValue) < SOLAR_CHARGE_MIN_VOLTAGE)){ + gotoMode2AfterThisTimestamp = getCurrentTime()+deepSleepNightTime.get(); + Serial.println("No pumps to activate and low light, deepSleepNight"); + espDeepSleepFor(deepSleepNightTime.get()); + }else { + gotoMode2AfterThisTimestamp = getCurrentTime()+deepSleepTime.get(); + Serial.println("No pumps to activate, deepSleep"); + espDeepSleepFor(deepSleepTime.get()); + } + + }else { + gotoMode2AfterThisTimestamp = 0; + Serial.println("Running pump, watering deepsleep"); + espDeepSleepFor(wateringDeepSleep.get()); + } + } void setMoistureTrigger(int plantId, long value){ @@ -316,6 +342,8 @@ void onHomieEvent(const HomieEvent& event) { //wait for rtc sync? rtcDeepSleepTime = deepSleepTime.get(); Serial << rtcDeepSleepTime << " ms ds" << endl; + + //saveguard, should be overriden in mode2MQTT normally esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) ); mode2MQTT(); @@ -341,6 +369,8 @@ void onHomieEvent(const HomieEvent& event) { case HomieEventType::OTA_SUCCESSFUL: digitalWrite(OUTPUT_SENSOR, LOW); break; + default: + break; } } @@ -358,7 +388,7 @@ int determineNextPump(){ long lastActivation = getLastActivationForPump(i); long sinceLastActivation = getCurrentTime()-lastActivation; //this pump is in cooldown skip it and disable low power mode trigger for it - if(mPlants[i].mSetting->pPumpCooldownInHours->get() > sinceLastActivation / 3600 / 1000){ + if(mPlants[i].mSetting->pPumpCooldownInHours->get() > sinceLastActivation / 3600){ setMoistureTrigger(i, DEACTIVATED_PLANT); continue; } @@ -480,9 +510,12 @@ void systemInit(){ Homie_setFirmware("PlantControl", FIRMWARE_VERSION); // Set default values - deepSleepTime.setDefaultValue(30000); /* 30 seconds in milliseconds */ - deepSleepNightTime.setDefaultValue(0); - wateringDeepSleep.setDefaultValue(60000); /* 1 minute in milliseconds */ + + //in seconds + deepSleepTime.setDefaultValue(10); + deepSleepNightTime.setDefaultValue(30); + wateringDeepSleep.setDefaultValue(5); + waterLevelMax.setDefaultValue(1000); /* 100cm in mm */ waterLevelMin.setDefaultValue(50); /* 5cm in mm */ waterLevelWarn.setDefaultValue(500); /* 50cm in mm */ @@ -560,10 +593,11 @@ void systemInit(){ bool mode1(){ Serial.println("m1"); + Serial << getCurrentTime() << " curtime" << endl; - struct timeval tv_now; - gettimeofday(&tv_now, NULL); - Serial << tv_now.tv_sec << " curtime" << endl; + if(rtcDeepSleepTime > 0){ + esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) ); + } readSensors(); //queue sensor values for @@ -612,7 +646,16 @@ bool mode1(){ } //check how long it was already in mode1 if to long goto mode2 - //TODO evaluate if something is to do + long cTime = getCurrentTime(); + if(cTime < 100000){ + Serial.println("Starting mode 2 due to missing ntp"); + //missing ntp time boot to mode3 + return true; + } + if(gotoMode2AfterThisTimestamp < cTime){ + Serial.println("Starting mode 2 after specified mode1 time"); + return true; + } return false; } @@ -667,19 +710,11 @@ void setup() { // Big TODO use here the settings in RTC_Memory //Panik mode, the Lipo is empty, sleep a long long time: - if ( SOLAR_VOLT(solarRawSensor.getAverage()) < MINIMUM_SOLAR_VOLT) { - Serial << deepSleepNightTime.get() << "ms ds " << SOLAR_VOLT(solarRawSensor.getAverage()) << "V" << endl; - esp_sleep_enable_timer_wakeup(PANIK_MODE_DEEPSLEEP); - } - - if (mConfigured && - (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) < MINIMUM_LIPO_VOLT) && - (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) > NO_LIPO_VOLT) && - (deepSleepTime.get()) ) { - long sleepEmptyLipo = (deepSleepTime.get() * EMPTY_LIPO_MULTIPL); - Serial << sleepEmptyLipo << " ms lipo " << ADC_5V_TO_3V3(lipoRawSensor.getAverage()) << "V" << endl; - esp_sleep_enable_timer_wakeup(sleepEmptyLipo * 1000U); - mDeepSleep = true; + if ((ADC_5V_TO_3V3(lipoRawSensor.getAverage()) < MINIMUM_LIPO_VOLT) && + (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) > NO_LIPO_VOLT)) { + Serial << PANIK_MODE_DEEPSLEEP << " s lipo " << ADC_5V_TO_3V3(lipoRawSensor.getAverage()) << "V" << endl; + esp_sleep_enable_timer_wakeup(PANIK_MODE_DEEPSLEEP_US); + esp_deep_sleep_start(); } if(mode1()){ From 1485539a8bde0f37c580ae4eed257477c755c871 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 20:03:12 +0200 Subject: [PATCH 7/9] Deep sleep is set according daylight --- esp32/src/main.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 1162215..cfcbc78 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -86,6 +86,14 @@ Plant mPlants[MAX_PLANTS] = { Plant(SENSOR_PLANT6, OUTPUT_PUMP6, 6, &plant6, &mSetting6) }; +float getBatteryVoltage(){ + return ADC_5V_TO_3V3(lipoRawSensor.getAverage()); +} + +float getSolarVoltage(){ + return SOLAR_VOLT(solarRawSensor.getAverage()); +} + void readSystemSensors() { lipoRawSensor.add(analogRead(SENSOR_LIPO)); solarRawSensor.add(analogRead(SENSOR_SOLAR)); @@ -120,6 +128,8 @@ void espDeepSleepFor(long seconds){ wait4sleep.in(500, prepareSleep); } + + void mode2MQTT(){ readSystemSensors(); @@ -144,9 +154,9 @@ void mode2MQTT(){ lastWaterValue = mWaterGone; sensorLipo.setProperty("percent").send( String(100 * lipoRawSensor.getAverage() / 4095) ); - sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoRawSensor.getAverage())) ); + sensorLipo.setProperty("volt").send( String(getBatteryVoltage()) ); sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage() ) / 4095)); - sensorSolar.setProperty("volt").send( String(SOLAR_VOLT(solarRawSensor.getAverage())) ); + sensorSolar.setProperty("volt").send( String(getSolarVoltage()) ); float temp[2] = { TEMP_INIT_VALUE, TEMP_INIT_VALUE }; float* pFloat = temp; @@ -179,9 +189,8 @@ void mode2MQTT(){ setLastActivationForPump(lastPumpRunning, getCurrentTime()); digitalWrite(mPlants[lastPumpRunning].mPinPump, HIGH); } - float solarValue = solarRawSensor.getMedian(); if(lastPumpRunning == -1 || !hasWater){ - if((ADC_5V_TO_3V3(solarValue) < SOLAR_CHARGE_MIN_VOLTAGE)){ + if(getSolarVoltage() < SOLAR_CHARGE_MIN_VOLTAGE){ gotoMode2AfterThisTimestamp = getCurrentTime()+deepSleepNightTime.get(); Serial.println("No pumps to activate and low light, deepSleepNight"); espDeepSleepFor(deepSleepNightTime.get()); @@ -375,7 +384,7 @@ void onHomieEvent(const HomieEvent& event) { } int determineNextPump(){ - float solarValue = solarRawSensor.getMedian(); + float solarValue = getSolarVoltage(); bool isLowLight =(ADC_5V_TO_3V3(solarValue) > SOLAR_CHARGE_MIN_VOLTAGE || ADC_5V_TO_3V3(solarValue) < SOLAR_CHARGE_MAX_VOLTAGE); @@ -710,9 +719,9 @@ void setup() { // Big TODO use here the settings in RTC_Memory //Panik mode, the Lipo is empty, sleep a long long time: - if ((ADC_5V_TO_3V3(lipoRawSensor.getAverage()) < MINIMUM_LIPO_VOLT) && - (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) > NO_LIPO_VOLT)) { - Serial << PANIK_MODE_DEEPSLEEP << " s lipo " << ADC_5V_TO_3V3(lipoRawSensor.getAverage()) << "V" << endl; + if ((getBatteryVoltage() < MINIMUM_LIPO_VOLT) && + (getBatteryVoltage() > NO_LIPO_VOLT)) { + Serial << PANIK_MODE_DEEPSLEEP << " s lipo " << getBatteryVoltage() << "V" << endl; esp_sleep_enable_timer_wakeup(PANIK_MODE_DEEPSLEEP_US); esp_deep_sleep_start(); } From 9b5bf90da981e297bdca6f3ae7879a575b412dd4 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 20:46:09 +0200 Subject: [PATCH 8/9] settings gpio mode before deepsleep --- esp32/include/PlantCtrl.h | 21 ++++---------------- esp32/src/PlantCtrl.cpp | 11 +++-------- esp32/src/main.cpp | 40 +++++++++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/esp32/include/PlantCtrl.h b/esp32/include/PlantCtrl.h index 41f735a..a955797 100644 --- a/esp32/include/PlantCtrl.h +++ b/esp32/include/PlantCtrl.h @@ -13,13 +13,12 @@ #define PLANT_CTRL_H #include "HomieTypes.h" +#include "RunningMedian.h" class Plant { private: - int mValue = 0; /**< Value of the moist sensor */ - - int mAnalogValue=0; /**< moist sensor values, used for a calculation */ + RunningMedian moistureRaw = RunningMedian(5); HomieNode* mPlant = NULL; public: @@ -45,14 +44,6 @@ public: */ void addSenseValue(int analogValue); - /** - * @brief Calculate the value based on the information - * @see amountMeasurePoints - * Internal memory, used by addSenseValue will be resetted - * @return int analog value - */ - void calculateSensorValue(int amountMeasurePoints); - /** * @brief Get the Sensor Pin of the analog measuring * @@ -67,7 +58,7 @@ public: */ int getPumpPin() { return mPinPump; } - int getSensorValue() { return mValue; } + int getSensorValue() { return moistureRaw.getMedian(); } /** * @brief Check if a plant is too dry and needs some water. @@ -76,7 +67,7 @@ public: * @return false */ bool isPumpRequired() { - return (this->mSetting->pSensorDry != NULL) && (this->mValue < this->mSetting->pSensorDry->get()); + return (this->mSetting->pSensorDry != NULL) && (this->moistureRaw.getMedian() < this->mSetting->pSensorDry->get()); } HomieInternals::SendingPromise& setProperty(const String& property) const { @@ -84,10 +75,6 @@ public: } void init(void); - - long getSettingSensorDry() { - return this->mSetting->pSensorDry->get(); - } }; #endif diff --git a/esp32/src/PlantCtrl.cpp b/esp32/src/PlantCtrl.cpp index 7290ae8..e7cf64d 100644 --- a/esp32/src/PlantCtrl.cpp +++ b/esp32/src/PlantCtrl.cpp @@ -20,7 +20,7 @@ Plant::Plant(int pinSensor, int pinPump,int plantId, HomieNode* plant, PlantSett } void Plant::init(void) { - this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT); + this->mSetting->pSensorDry->setDefaultValue(4095); this->mSetting->pSensorDry->setValidator([] (long candidate) { return (((candidate >= 0) && (candidate <= 4095) ) || candidate == DEACTIVATED_PLANT); }); @@ -41,10 +41,5 @@ void Plant::init(void) { } void Plant::addSenseValue(int analog) { - this->mAnalogValue += analog; -} - -void Plant::calculateSensorValue(int amountMeasurePoints) { - this->mValue = this->mAnalogValue / amountMeasurePoints; - this->mAnalogValue = 0; -} + this->moistureRaw.add(analog); +} \ No newline at end of file diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index cfcbc78..c420665 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -121,6 +121,13 @@ bool prepareSleep(void *) { } void espDeepSleepFor(long seconds){ + delay(1500); + gpio_deep_sleep_hold_en(); + gpio_hold_en(GPIO_NUM_13); //pump pwr + //gpio_hold_en(GPIO_NUM_23); //p0 + //FIXME fix for outher outputs + + Serial.print("Going to sleep for "); Serial.print(seconds); Serial.println(" seconds"); @@ -140,15 +147,18 @@ void mode2MQTT(){ digitalWrite(mPlants[i].mPinPump, LOW); } - if (deepSleepTime.get()) { - Serial << "sleeping for " << deepSleepTime.get() << endl; - } - /* Publish default values */ + if (deepSleepTime.get()) { + Serial << "sleeping for " << deepSleepTime.get() << endl; + } + /* Publish default values */ if(lastPumpRunning != -1){ long waterDiff = mWaterGone-lastWaterValue; //TODO attribute used water in ml to plantid } + for(int i=0; i < MAX_PLANTS; i++) { + mPlants[i].setProperty("moist").send(String(100 * mPlants[i].getSensorValue() / 4095 )); + } sensorWater.setProperty("remaining").send(String(waterLevelMax.get() - mWaterGone )); Serial << "W : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone ) << "%)" << endl; lastWaterValue = mWaterGone; @@ -181,11 +191,14 @@ void mode2MQTT(){ return; } - - bool hasWater = mWaterGone > waterLevelMin.get(); + bool hasWater = true;//FIXMEmWaterGone > waterLevelMin.get(); //FIXME no water warning message lastPumpRunning = determineNextPump(); + if(lastPumpRunning != -1 && !hasWater){ + Serial.println("Want to pump but no water"); + } if(lastPumpRunning != -1 && hasWater){ + digitalWrite(OUTPUT_PUMP, HIGH); setLastActivationForPump(lastPumpRunning, getCurrentTime()); digitalWrite(mPlants[lastPumpRunning].mPinPump, HIGH); } @@ -385,30 +398,29 @@ void onHomieEvent(const HomieEvent& event) { int determineNextPump(){ float solarValue = getSolarVoltage(); - bool isLowLight =(ADC_5V_TO_3V3(solarValue) > SOLAR_CHARGE_MIN_VOLTAGE || ADC_5V_TO_3V3(solarValue) < SOLAR_CHARGE_MAX_VOLTAGE); - - - + bool isLowLight =(solarValue > SOLAR_CHARGE_MIN_VOLTAGE || solarValue < SOLAR_CHARGE_MAX_VOLTAGE); //FIXME instead of for, use sorted by last activation index to ensure equal runtime? for(int i=0; i < MAX_PLANTS; i++) { - mPlants[i].calculateSensorValue(AMOUNT_SENOR_QUERYS); - mPlants[i].setProperty("moist").send(String(100 * mPlants[i].getSensorValue() / 4095 )); long lastActivation = getLastActivationForPump(i); long sinceLastActivation = getCurrentTime()-lastActivation; //this pump is in cooldown skip it and disable low power mode trigger for it if(mPlants[i].mSetting->pPumpCooldownInHours->get() > sinceLastActivation / 3600){ - setMoistureTrigger(i, DEACTIVATED_PLANT); - continue; + Serial.println("Skipping due to cooldown"); + //setMoistureTrigger(i, DEACTIVATED_PLANT); + //continue; } //skip as it is not low light if(!isLowLight && mPlants[i].mSetting->pPumpOnlyWhenLowLight->get()){ + Serial.println("Skipping due to light"); continue; } if(mPlants->isPumpRequired()){ + Serial.println("Requested pumpin"); return i; } + Serial.println("No pump required"); } return -1; } From 6e9b7b29ffb618ced14aaa18728463bad3ba55c1 Mon Sep 17 00:00:00 2001 From: c3ma Date: Wed, 21 Oct 2020 20:51:25 +0200 Subject: [PATCH 9/9] set pump output --- esp32/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index c420665..1319b3f 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -714,6 +714,7 @@ void setup() { } /* read button */ pinMode(BUTTON, INPUT); + pinMode(OUTPUT_PUMP, OUTPUT); /* Disable Wifi and bluetooth */ WiFi.mode(WIFI_OFF);