Deep sleep is set according daylight

This commit is contained in:
c3ma 2020-10-21 19:50:05 +02:00
parent 03be8a1bda
commit 5591c6dba2
3 changed files with 79 additions and 45 deletions

View File

@ -46,7 +46,6 @@
#define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */ #define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */
#define MAX_PLANTS 7 #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 MINIMUM_LIPO_VOLT 3.6f /**< Minimum voltage of the Lipo, that must be present */
#define NO_LIPO_VOLT 2.0f /**< No Lipo connected */ #define NO_LIPO_VOLT 2.0f /**< No Lipo connected */
#define MINIMUM_SOLAR_VOLT 4.0f /**< Minimum voltage of the sun, to detect daylight */ #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 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 #endif

View File

@ -37,7 +37,6 @@ HomieNode stayAlive("stay", "alive", "alive");
/** /**
*********************************** Settings ******************************* *********************************** Settings *******************************
*/ */
HomieSetting<long> deepSleepTime("deepsleep", "time in milliseconds to sleep (0 deactivats it)"); HomieSetting<long> deepSleepTime("deepsleep", "time in milliseconds to sleep (0 deactivats it)");
HomieSetting<long> deepSleepNightTime("nightsleep", "time in milliseconds to sleep (0 uses same setting: deepsleep at night, too)"); HomieSetting<long> deepSleepNightTime("nightsleep", "time in milliseconds to sleep (0 uses same setting: deepsleep at night, too)");
HomieSetting<long> wateringDeepSleep("pumpdeepsleep", "time seconds to sleep, while a pump is running"); HomieSetting<long> wateringDeepSleep("pumpdeepsleep", "time seconds to sleep, while a pump is running");

View File

@ -29,6 +29,7 @@ const unsigned long TEMPREADCYCLE = 30000; /**< Check temperature all half minut
/********************* non volatile enable after deepsleep *******************************/ /********************* 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 rtcDeepSleepTime = 0; /**< Time, when the microcontroller shall be up again */
RTC_DATA_ATTR long rtcLastActive0 = 0; RTC_DATA_ATTR long rtcLastActive0 = 0;
RTC_DATA_ATTR long rtcMoistureTrigger0 = 0; /**<Level for the moisture sensor */ RTC_DATA_ATTR long rtcMoistureTrigger0 = 0; /**<Level for the moisture sensor */
@ -47,14 +48,12 @@ RTC_DATA_ATTR long rtcMoistureTrigger6 = 0; /**<Level for the moisture sensor
RTC_DATA_ATTR int lastPumpRunning = 0; RTC_DATA_ATTR int lastPumpRunning = 0;
RTC_DATA_ATTR long lastWaterValue = 0; RTC_DATA_ATTR long lastWaterValue = 0;
const char* ntpServer = "pool.ntp.org";
bool warmBoot = true; bool warmBoot = true;
bool mode3Active = false; /**< Controller must not sleep */ bool mode3Active = false; /**< Controller must not sleep */
bool mLoopInited = false;
bool mDeepSleep = false;
int plantSensor1 = 0; int plantSensor1 = 0;
int mWaterGone = -1; /**< Amount of centimeter, where no water is seen */ int mWaterGone = -1; /**< Amount of centimeter, where no water is seen */
@ -96,21 +95,41 @@ int determineNextPump();
void setLastActivationForPump(int pumpId, long time); void setLastActivationForPump(int pumpId, long time);
//FIXME real impl
long getCurrentTime(){ long getCurrentTime(){
return 1337; struct timeval tv_now;
gettimeofday(&tv_now, NULL);
return tv_now.tv_sec;
} }
//wait till homie flushed mqtt ect. //wait till homie flushed mqtt ect.
bool prepareSleep(void *) { bool prepareSleep(void *) {
//FIXME wait till pending mqtt is done, then start sleep via event or whatever //FIXME wait till pending mqtt is done, then start sleep via event or whatever
//Homie.prepareToSleep(); //Homie.prepareToSleep();
bool queueIsEmpty = true;
if(queueIsEmpty){
esp_deep_sleep_start();
}
return true; // repeat? true there is something in the queue to be done return true; // repeat? true there is something in the queue to be done
} }
void espDeepSleepFor(long seconds){
Serial.print("Going to sleep for ");
Serial.print(seconds);
Serial.println(" seconds");
esp_sleep_enable_timer_wakeup( (seconds * 1000U * 1000U) );
wait4sleep.in(500, prepareSleep);
}
void mode2MQTT(){ void mode2MQTT(){
readSystemSensors(); readSystemSensors();
configTime(0, 0, ntpServer);
digitalWrite(OUTPUT_PUMP, LOW);
for(int i=0; i < MAX_PLANTS; i++) {
digitalWrite(mPlants[i].mPinPump, LOW);
}
if (deepSleepTime.get()) { if (deepSleepTime.get()) {
Serial << "sleeping for " << deepSleepTime.get() << endl; Serial << "sleeping for " << deepSleepTime.get() << endl;
} }
@ -124,16 +143,6 @@ void mode2MQTT(){
Serial << "W : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone ) << "%)" << endl; Serial << "W : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone ) << "%)" << endl;
lastWaterValue = mWaterGone; lastWaterValue = mWaterGone;
if (mWaterGone <= waterLevelMin.get()) {
/* let the ESP sleep qickly, as nothing must be done */
if ((millis() >= (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("percent").send( String(100 * lipoRawSensor.getAverage() / 4095) );
sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoRawSensor.getAverage())) ); sensorLipo.setProperty("volt").send( String(ADC_5V_TO_3V3(lipoRawSensor.getAverage())) );
sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage() ) / 4095)); sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage() ) / 4095));
@ -157,20 +166,37 @@ void mode2MQTT(){
bool lipoTempWarning = abs(temp[0] - temp[1]) > 5; bool lipoTempWarning = abs(temp[0] - temp[1]) > 5;
if(lipoTempWarning){ if(lipoTempWarning){
wait4sleep.in(500, prepareSleep); Serial.println("Lipo temp incorrect, panic mode deepsleep");
espDeepSleepFor(PANIK_MODE_DEEPSLEEP);
return; 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(); lastPumpRunning = determineNextPump();
if(lastPumpRunning != -1){ if(lastPumpRunning != -1 && hasWater){
setLastActivationForPump(lastPumpRunning, getCurrentTime()); setLastActivationForPump(lastPumpRunning, getCurrentTime());
digitalWrite(mPlants[lastPumpRunning].mPinPump, HIGH); 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){ void setMoistureTrigger(int plantId, long value){
@ -316,6 +342,8 @@ void onHomieEvent(const HomieEvent& event) {
//wait for rtc sync? //wait for rtc sync?
rtcDeepSleepTime = deepSleepTime.get(); rtcDeepSleepTime = deepSleepTime.get();
Serial << rtcDeepSleepTime << " ms ds" << endl; Serial << rtcDeepSleepTime << " ms ds" << endl;
//saveguard, should be overriden in mode2MQTT normally
esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) ); esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) );
mode2MQTT(); mode2MQTT();
@ -341,6 +369,8 @@ void onHomieEvent(const HomieEvent& event) {
case HomieEventType::OTA_SUCCESSFUL: case HomieEventType::OTA_SUCCESSFUL:
digitalWrite(OUTPUT_SENSOR, LOW); digitalWrite(OUTPUT_SENSOR, LOW);
break; break;
default:
break;
} }
} }
@ -358,7 +388,7 @@ int determineNextPump(){
long lastActivation = getLastActivationForPump(i); long lastActivation = getLastActivationForPump(i);
long sinceLastActivation = getCurrentTime()-lastActivation; long sinceLastActivation = getCurrentTime()-lastActivation;
//this pump is in cooldown skip it and disable low power mode trigger for it //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); setMoistureTrigger(i, DEACTIVATED_PLANT);
continue; continue;
} }
@ -480,9 +510,12 @@ void systemInit(){
Homie_setFirmware("PlantControl", FIRMWARE_VERSION); Homie_setFirmware("PlantControl", FIRMWARE_VERSION);
// Set default values // Set default values
deepSleepTime.setDefaultValue(30000); /* 30 seconds in milliseconds */
deepSleepNightTime.setDefaultValue(0); //in seconds
wateringDeepSleep.setDefaultValue(60000); /* 1 minute in milliseconds */ deepSleepTime.setDefaultValue(10);
deepSleepNightTime.setDefaultValue(30);
wateringDeepSleep.setDefaultValue(5);
waterLevelMax.setDefaultValue(1000); /* 100cm in mm */ waterLevelMax.setDefaultValue(1000); /* 100cm in mm */
waterLevelMin.setDefaultValue(50); /* 5cm in mm */ waterLevelMin.setDefaultValue(50); /* 5cm in mm */
waterLevelWarn.setDefaultValue(500); /* 50cm in mm */ waterLevelWarn.setDefaultValue(500); /* 50cm in mm */
@ -560,10 +593,11 @@ void systemInit(){
bool mode1(){ bool mode1(){
Serial.println("m1"); Serial.println("m1");
Serial << getCurrentTime() << " curtime" << endl;
struct timeval tv_now; if(rtcDeepSleepTime > 0){
gettimeofday(&tv_now, NULL); esp_sleep_enable_timer_wakeup( (rtcDeepSleepTime * 1000U) );
Serial << tv_now.tv_sec << " curtime" << endl; }
readSensors(); readSensors();
//queue sensor values for //queue sensor values for
@ -612,7 +646,16 @@ bool mode1(){
} }
//check how long it was already in mode1 if to long goto mode2 //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; return false;
} }
@ -667,19 +710,11 @@ void setup() {
// Big TODO use here the settings in RTC_Memory // Big TODO use here the settings in RTC_Memory
//Panik mode, the Lipo is empty, sleep a long long time: //Panik mode, the Lipo is empty, sleep a long long time:
if ( SOLAR_VOLT(solarRawSensor.getAverage()) < MINIMUM_SOLAR_VOLT) { if ((ADC_5V_TO_3V3(lipoRawSensor.getAverage()) < MINIMUM_LIPO_VOLT) &&
Serial << deepSleepNightTime.get() << "ms ds " << SOLAR_VOLT(solarRawSensor.getAverage()) << "V" << endl; (ADC_5V_TO_3V3(lipoRawSensor.getAverage()) > NO_LIPO_VOLT)) {
esp_sleep_enable_timer_wakeup(PANIK_MODE_DEEPSLEEP); 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 (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(mode1()){ if(mode1()){