added timed light function

This commit is contained in:
Your Name 2021-08-29 20:45:50 +02:00
parent e927fc8c70
commit f99f72b65a
4 changed files with 102 additions and 12 deletions

View File

@ -69,8 +69,12 @@
#define SENSOR_TANK_ECHO GPIO_NUM_16 /**< GPIO 16 - echo feedback of water sensor */
#define SENSOR_TANK_TRG GPIO_NUM_17 /**< GPIO 17 - trigger for water sensor */
#define BUTTON GPIO_NUM_0 /**< GPIO 0 - Fix button of NodeMCU */
#define CUSTOM1_PIN3 GPIO_NUM_2 /**< GPIO 2 - Custom GPIO controlling a MOSFET, connected to GND */
#define CUSTOM1_PIN2 GPIO_NUM_12 /**< GPIO 4 - custom GPIO directly connected to GPIO header */
#define CUSTOM1_PIN1 GPIO_NUM_34 /** direct gpio */
#define CUSTOM1_PIN3 GPIO_NUM_35 /** direct gpio */
#define CUSTOM1_PIN5 GPIO_NUM_2 /** mosfet controlled */
#define CUSTOM1_PIN7 GPIO_NUM_12 /** mosfet controlled */
#define I2C1_SDA GPIO_NUM_34 /**< GPIO 34 - I2C */
#define I2C1_SCL GPIO_NUM_35 /**< GPIO 35 - I2C */
/* @} */
@ -80,6 +84,8 @@
*/
#define FIRMWARE_VERSION "sw 1.3 hw 0.10"
#define TIMED_LIGHT_PIN CUSTOM1_PIN5
#define MOIST_SENSOR_MAX_FRQ 60000 // 60kHz (500Hz margin)
#define MOIST_SENSOR_MIN_FRQ 1000 // 1kHz (500Hz margin)

View File

@ -51,6 +51,11 @@ HomieNode plant4("plant4", "Plant 4", "Plant"); /**< dynamic Homie information f
HomieNode plant5("plant5", "Plant 5", "Plant"); /**< dynamic Homie information for sixth plant */
HomieNode plant6("plant6", "Plant 6", "Plant"); /**< dynamic Homie information for seventh plant */
#if defined(TIMED_LIGHT_PIN)
HomieNode timedLightNode("timedLight", "TimedLight", "Status");
#endif // TIMED_LIGHT_PIN
HomieNode sensorLipo("lipo", "Battery Status", "Lipo");
HomieNode sensorSolar("solar", "Solar Status", "Solarpanel");
HomieNode sensorWater("water", "WaterSensor", "Water");
@ -78,6 +83,14 @@ HomieSetting<const char *> lipoSensorAddr("lipoDSAddr", "1wire address for lipo
HomieSetting<const char *> waterSensorAddr("tankDSAddr", "1wire address for water temperature sensor");
HomieSetting<const char *> ntpServer("ntpServer", "NTP server (pool.ntp.org as default)");
#if defined(TIMED_LIGHT_PIN)
HomieSetting<double> timedLightVoltageCutoff("LightVoltageCutoff", "voltage at wich to disable light");
HomieSetting<long> timedLightStart("LightStart", "hour to start light");
HomieSetting<long> timedLightEnd("LightEnd", "hour to end light");
HomieSetting<bool> timedLightOnlyWhenDark("LightOnlyDark", "only enable light, if solar is low");
#endif // TIMED_LIGHT_PIN
/**
* @}
*/

View File

@ -18,7 +18,7 @@
#include "RunningMedian.h"
#include "MathUtils.h"
#define MOISTURE_MEASUREMENT_DURATION 500 /** ms */
#define MOISTURE_MEASUREMENT_DURATION 400 /** ms */
class Plant

View File

@ -57,9 +57,10 @@
******************************************************************************/
void log(int level, String message, int code);
int determineNextPump();
int determineNextPump(bool lowLight);
void plantcontrol();
void readPowerSwitchedSensors();
bool determineTimedLightState(bool lowLight);
/******************************************************************************
* NON VOLATILE VARIABLES in DEEP SLEEP
@ -67,6 +68,10 @@ void readPowerSwitchedSensors();
RTC_DATA_ATTR int lastPumpRunning = -1; /**< store last successfully waterd plant */
RTC_DATA_ATTR long lastWaterValue = 0; /**< to calculate the used water per plant */
#if defined(TIMED_LIGHT_PIN)
RTC_DATA_ATTR bool timedLightOn = false; /**< allow fast recovery after poweron */
#endif // TIMED_LIGHT_PIN
RTC_DATA_ATTR long rtcLastWateringPlant[MAX_PLANTS] = {0};
RTC_DATA_ATTR long consecutiveWateringPlant[MAX_PLANTS] = {0};
@ -133,19 +138,21 @@ void espDeepSleepFor(long seconds, bool activatePump)
}
}
//allo hold for all digital pins
gpio_deep_sleep_hold_en();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
if (activatePump)
{
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
gpio_deep_sleep_hold_en();
gpio_hold_en(OUTPUT_ENABLE_PUMP); //pump pwr
}
else
{
gpio_hold_dis(OUTPUT_ENABLE_PUMP); //pump pwr
gpio_deep_sleep_hold_dis();
digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
digitalWrite(OUTPUT_ENABLE_SENSOR, LOW);
for (int i = 0; i < MAX_PLANTS; i++)
@ -160,7 +167,10 @@ void espDeepSleepFor(long seconds, bool activatePump)
gpio_hold_en(OUTPUT_PUMP4);
gpio_hold_en(OUTPUT_PUMP5);
gpio_hold_en(OUTPUT_PUMP6);
//FIXME fix for outher outputs
#if defined(TIMED_LIGHT_PIN)
gpio_hold_en(TIMED_LIGHT_PIN);
#endif // TIMED_LIGHT_PIN
esp_sleep_enable_timer_wakeup((seconds * 1000U * 1000U));
if (mAliveWasRead)
@ -410,9 +420,8 @@ void onHomieEvent(const HomieEvent &event)
}
}
int determineNextPump()
int determineNextPump(bool isLowLight)
{
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
int pumpToUse = -1;
for (int i = 0; i < MAX_PLANTS; i++)
{
@ -601,6 +610,13 @@ void setup()
WiFi.mode(WIFI_OFF);
Serial.flush();
//restore state before releasing pin, to prevent flickering
#if defined(TIMED_LIGHT_PIN)
pinMode(TIMED_LIGHT_PIN, OUTPUT);
digitalWrite(TIMED_LIGHT_PIN, timedLightOn);
gpio_hold_dis(TIMED_LIGHT_PIN);
#endif // TIMED_LIGHT_PIN
gpio_hold_dis(OUTPUT_PUMP0);
gpio_hold_dis(OUTPUT_PUMP1);
gpio_hold_dis(OUTPUT_PUMP2);
@ -683,9 +699,20 @@ void setup()
waterLevelVol.setDefaultValue(5000); /* 5l in ml */
lipoSensorAddr.setDefaultValue("");
waterSensorAddr.setDefaultValue("");
pumpIneffectiveWarning.setDefaultValue(600).setValidator([](long candidate)
pumpIneffectiveWarning.setDefaultValue(5).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (20)); });
pumpIneffectiveWarning.setDefaultValue(5);
#if defined(TIMED_LIGHT_PIN)
timedLightStart.setDefaultValue(18).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (25)); });
timedLightEnd.setDefaultValue(23).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (22)); });
timedLightOnlyWhenDark.setDefaultValue(true);
timedLightVoltageCutoff.setDefaultValue(3.8).setValidator([](double candidate)
{ return (candidate > 3.3) && (candidate < (4.2)); });
#endif // TIMED_LIGHT_PIN
Homie.setLoopFunction(homieLoop);
Homie.onEvent(onHomieEvent);
@ -891,9 +918,10 @@ void plantcontrol()
Serial.flush();
}
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
bool hasWater = true; //FIXMEmWaterGone > waterLevelMin.get();
//FIXME no water warning message
lastPumpRunning = determineNextPump();
lastPumpRunning = determineNextPump(isLowLight);
if (lastPumpRunning != -1 && !hasWater)
{
log(LOG_LEVEL_ERROR, LOG_PUMP_BUTNOTANK_MESSAGE, LOG_PUMP_BUTNOTANK_CODE);
@ -917,6 +945,13 @@ void plantcontrol()
}
}
#if defined(TIMED_LIGHT_PIN)
bool shouldLight = determineTimedLightState(isLowLight);
timedLightOn = shouldLight;
digitalWrite(TIMED_LIGHT_PIN, shouldLight);
#endif // TIMED_LIGHT_PIN
/* Always handle one of the deep sleep duration */
if (lastPumpRunning == -1 || !hasWater)
{
@ -939,6 +974,42 @@ void plantcontrol()
/** @}*/
bool determineTimedLightState(bool lowLight){
bool onlyAllowedWhenDark = timedLightOnlyWhenDark.get();
long hoursStart = timedLightStart.get();
long hoursEnd = timedLightEnd.get();
//ntp missing
if(getCurrentTime() < 10000){
timedLightNode.setProperty("state").send(String("Off, missing ntp"));
return false;
}
if(onlyAllowedWhenDark && !lowLight){
timedLightNode.setProperty("state").send(String("Off, not dark"));
return false;
}
if (((hoursStart > hoursEnd) &&
(getCurrentHour() >= hoursStart || getCurrentHour() <= hoursEnd)) ||
/* Handle e.g. start = 8, end = 21 */
((hoursStart < hoursEnd) &&
(getCurrentHour() >= hoursStart && getCurrentHour() <= hoursEnd)))
{
if(battery.getVoltage(BATTSENSOR_INDEX_BATTERY) >= timedLightVoltageCutoff.get() ){
timedLightNode.setProperty("state").send(String("On"));
return true;
}else {
timedLightNode.setProperty("state").send(String("Off, due to missing voltage"));
return false;
}
} else {
timedLightNode.setProperty("state").send(String("Off, outside worktime"));
return false;
}
}
void log(int level, String message, int statusCode)
{
String buffer;