wip new pump system
This commit is contained in:
parent
f13a25b34d
commit
f4e13454e3
@ -20,7 +20,6 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"deepsleep" : 60000,
|
"deepsleep" : 60000,
|
||||||
"nightsleep" : 60000,
|
"nightsleep" : 60000,
|
||||||
"pumpdeepsleep": 1000,
|
|
||||||
"watermaxlevel": 50,
|
"watermaxlevel": 50,
|
||||||
"watermin" : 5,
|
"watermin" : 5,
|
||||||
"plants" : 3,
|
"plants" : 3,
|
||||||
@ -44,6 +43,13 @@
|
|||||||
"plant3MinPumpIdle": 10000,
|
"plant3MinPumpIdle": 10000,
|
||||||
"plant4MinPumpIdle": 10000,
|
"plant4MinPumpIdle": 10000,
|
||||||
"plant5MinPumpIdle": 10000,
|
"plant5MinPumpIdle": 10000,
|
||||||
"plant6MinPumpIdle": 10000
|
"plant6MinPumpIdle": 10000,
|
||||||
|
"plant0PumpDuration": 5,
|
||||||
|
"plant1PumpDuration": 5,
|
||||||
|
"plant2PumpDuration": 5,
|
||||||
|
"plant3PumpDuration": 5,
|
||||||
|
"plant4PumpDuration": 5,
|
||||||
|
"plant5PumpDuration": 5,
|
||||||
|
"plant6PumpDuration": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
#define BATTSENSOR_INDEX_BATTERY 1
|
#define BATTSENSOR_INDEX_BATTERY 1
|
||||||
|
|
||||||
#define MQTT_TIMEOUT (1000 * 60) /**< After 10 seconds, MQTT is expected to be connected */
|
#define MQTT_TIMEOUT (1000 * 60) /**< After 10 seconds, MQTT is expected to be connected */
|
||||||
#define ESP_STALE_TIMEOUT (MQTT_TIMEOUT+(30*1000))
|
#define ESP_STALE_TIMEOUT (MQTT_TIMEOUT+(120*1000))
|
||||||
|
|
||||||
#define MAX_PLANTS 7
|
#define MAX_PLANTS 7
|
||||||
#define SOLAR_CHARGE_MIN_VOLTAGE 7 /**< Sun is rising (morning detected) */
|
#define SOLAR_CHARGE_MIN_VOLTAGE 7 /**< Sun is rising (morning detected) */
|
||||||
|
@ -73,7 +73,6 @@ HomieNode stayAlive("stay", "alive", "alive"); /**< Necessary for Mqtt Active C
|
|||||||
*/
|
*/
|
||||||
HomieSetting<long> deepSleepTime("sleep", "time in seconds to sleep");
|
HomieSetting<long> deepSleepTime("sleep", "time in seconds to sleep");
|
||||||
HomieSetting<long> deepSleepNightTime("nightsleep", "time in seconds to sleep (0 uses same setting: deepsleep at night, too)");
|
HomieSetting<long> deepSleepNightTime("nightsleep", "time in seconds to sleep (0 uses same setting: deepsleep at night, too)");
|
||||||
HomieSetting<long> wateringDeepSleep("pumpsleep", "time seconds to sleep, while a pump is running");
|
|
||||||
HomieSetting<long> pumpIneffectiveWarning("pumpConsecutiveWarn", "if the pump was triggered this amount directly after each cooldown, without resolving dryness, warn");
|
HomieSetting<long> pumpIneffectiveWarning("pumpConsecutiveWarn", "if the pump was triggered this amount directly after each cooldown, without resolving dryness, warn");
|
||||||
HomieSetting<long> waterLevelMax("tankmax", "distance (mm) at maximum water level");
|
HomieSetting<long> waterLevelMax("tankmax", "distance (mm) at maximum water level");
|
||||||
HomieSetting<long> waterLevelMin("tankmin", "distance (mm) at minimum water level (pumps still covered)");
|
HomieSetting<long> waterLevelMin("tankmin", "distance (mm) at minimum water level (pumps still covered)");
|
||||||
@ -107,7 +106,8 @@ HomieSetting<const char *> ntpServer("ntpServer", "NTP server (pool.ntp.org as d
|
|||||||
HomieSetting<long> mPumpAllowedHourRangeEnd##plant = HomieSetting<long>("hourend" strplant, "Plant" strplant " - Range pump allowed hour end (0-23)"); \
|
HomieSetting<long> mPumpAllowedHourRangeEnd##plant = HomieSetting<long>("hourend" strplant, "Plant" strplant " - Range pump allowed hour end (0-23)"); \
|
||||||
HomieSetting<bool> mPumpOnlyWhenLowLight##plant = HomieSetting<bool>("lowLight" strplant, "Plant" strplant " - Enable the Pump only, when there is no sunlight"); \
|
HomieSetting<bool> mPumpOnlyWhenLowLight##plant = HomieSetting<bool>("lowLight" strplant, "Plant" strplant " - Enable the Pump only, when there is no sunlight"); \
|
||||||
HomieSetting<long> mPumpCooldownInHours##plant = HomieSetting<long>("delay" strplant, "Plant" strplant " - How long to wait until the pump is activated again (minutes)"); \
|
HomieSetting<long> mPumpCooldownInHours##plant = HomieSetting<long>("delay" strplant, "Plant" strplant " - How long to wait until the pump is activated again (minutes)"); \
|
||||||
PlantSettings_t mSetting##plant = {&mSensorDry##plant, &mPumpAllowedHourRangeStart##plant, &mPumpAllowedHourRangeEnd##plant, &mPumpOnlyWhenLowLight##plant, &mPumpCooldownInHours##plant}; \
|
HomieSetting<long> pPumpDuration##plant = HomieSetting<long>("pumpDuration" strplant, "Plant" strplant " - time seconds or ml (if using flowmeter) to water when pump is active"); \
|
||||||
|
PlantSettings_t mSetting##plant = {&mSensorDry##plant, &mPumpAllowedHourRangeStart##plant, &mPumpAllowedHourRangeEnd##plant, &mPumpOnlyWhenLowLight##plant, &mPumpCooldownInHours##plant, &pPumpDuration##plant}; \
|
||||||
/**< Generate all settings for one plant \
|
/**< Generate all settings for one plant \
|
||||||
* \
|
* \
|
||||||
* Feature to start pumping only at morning: @link{SOLAR_CHARGE_MIN_VOLTAGE} and @link{SOLAR_CHARGE_MAX_VOLTAGE} \
|
* Feature to start pumping only at morning: @link{SOLAR_CHARGE_MIN_VOLTAGE} and @link{SOLAR_CHARGE_MAX_VOLTAGE} \
|
||||||
|
@ -23,6 +23,7 @@ typedef struct PlantSettings_t
|
|||||||
HomieSetting<long> *pPumpAllowedHourRangeEnd;
|
HomieSetting<long> *pPumpAllowedHourRangeEnd;
|
||||||
HomieSetting<bool> *pPumpOnlyWhenLowLight;
|
HomieSetting<bool> *pPumpOnlyWhenLowLight;
|
||||||
HomieSetting<long> *pPumpCooldownInHours;
|
HomieSetting<long> *pPumpCooldownInHours;
|
||||||
|
HomieSetting<long> *pPumpDuration;
|
||||||
} PlantSettings_t;
|
} PlantSettings_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -141,6 +141,10 @@ public:
|
|||||||
bool switchHandler(const HomieRange& range, const String& value);
|
bool switchHandler(const HomieRange& range, const String& value);
|
||||||
|
|
||||||
void setSwitchHandler(HomieInternals::PropertyInputHandler f);
|
void setSwitchHandler(HomieInternals::PropertyInputHandler f);
|
||||||
|
|
||||||
|
long getPumpDuration() {
|
||||||
|
return this->mSetting->pPumpDuration->get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,6 +51,12 @@ void Plant::init(void)
|
|||||||
return ((candidate >= 0) && (candidate <= 1024));
|
return ((candidate >= 0) && (candidate <= 1024));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this->mSetting->pPumpDuration->setDefaultValue(5);
|
||||||
|
this->mSetting->pPumpDuration->setValidator([](long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 1000));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/* Initialize Hardware */
|
/* Initialize Hardware */
|
||||||
Serial.println("Set GPIO mode " + String(mPinPump) + "=" + String(OUTPUT));
|
Serial.println("Set GPIO mode " + String(mPinPump) + "=" + String(OUTPUT));
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
|
@ -66,13 +66,11 @@ bool determineTimedLightState(bool lowLight);
|
|||||||
* NON VOLATILE VARIABLES in DEEP SLEEP
|
* NON VOLATILE VARIABLES in DEEP SLEEP
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
RTC_DATA_ATTR int lastPumpRunning = -1; /**< store last successfully waterd plant */
|
RTC_DATA_ATTR long lastWaterValue = 0; /**< to calculate the used water per plant */
|
||||||
RTC_DATA_ATTR long lastWaterValue = 0; /**< to calculate the used water per plant */
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
RTC_DATA_ATTR bool timedLightOn = false; /**< allow fast recovery after poweron */
|
RTC_DATA_ATTR bool timedLightOn = false; /**< allow fast recovery after poweron */
|
||||||
RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */
|
RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
|
||||||
RTC_DATA_ATTR long rtcLastWateringPlant[MAX_PLANTS] = {0};
|
RTC_DATA_ATTR long rtcLastWateringPlant[MAX_PLANTS] = {0};
|
||||||
RTC_DATA_ATTR long consecutiveWateringPlant[MAX_PLANTS] = {0};
|
RTC_DATA_ATTR long consecutiveWateringPlant[MAX_PLANTS] = {0};
|
||||||
@ -84,6 +82,7 @@ bool volatile mDownloadMode = false; /**< Controller must not sleep */
|
|||||||
bool volatile mSensorsRead = false; /**< Sensors are read without Wifi or MQTT */
|
bool volatile mSensorsRead = false; /**< Sensors are read without Wifi or MQTT */
|
||||||
bool volatile mAliveWasRead = false;
|
bool volatile mAliveWasRead = false;
|
||||||
bool volatile mMQTTReady = false;
|
bool volatile mMQTTReady = false;
|
||||||
|
int volatile pumpToRun = -1; /** pump to run at the end of the cycle */
|
||||||
|
|
||||||
bool mConfigured = false;
|
bool mConfigured = false;
|
||||||
long nextBlink = 0; /**< Time needed in main loop to support expected blink code */
|
long nextBlink = 0; /**< Time needed in main loop to support expected blink code */
|
||||||
@ -112,7 +111,7 @@ Plant mPlants[MAX_PLANTS] = {
|
|||||||
* LOCAL FUNCTIONS
|
* LOCAL FUNCTIONS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void espDeepSleepFor(long seconds, bool activatePump)
|
void espDeepSleep()
|
||||||
{
|
{
|
||||||
if (mDownloadMode)
|
if (mDownloadMode)
|
||||||
{
|
{
|
||||||
@ -138,42 +137,33 @@ void espDeepSleepFor(long seconds, bool activatePump)
|
|||||||
log(LOG_LEVEL_DEBUG, "NTP timeout before deepsleep", LOG_DEBUG_CODE);
|
log(LOG_LEVEL_DEBUG, "NTP timeout before deepsleep", LOG_DEBUG_CODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//allo hold for all digital pins
|
//allo hold for all digital pins
|
||||||
gpio_deep_sleep_hold_en();
|
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_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_SLOW_MEM, ESP_PD_OPTION_ON);
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_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);
|
||||||
|
|
||||||
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
|
gpio_hold_en(TIMED_LIGHT_PIN);
|
||||||
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
long secondsToSleep = -1;
|
||||||
|
|
||||||
|
if (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE)
|
||||||
{
|
{
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
log(LOG_LEVEL_INFO, String(String(mSolarVoltage) + "V! No pumps to activate and low light, deepSleepNight"), LOG_NOPUMP_LOWLIGHT);
|
||||||
|
secondsToSleep = deepSleepTime.get();
|
||||||
gpio_hold_en(OUTPUT_ENABLE_PUMP); //pump pwr
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gpio_hold_dis(OUTPUT_ENABLE_PUMP); //pump pwr
|
log(LOG_LEVEL_INFO, "No pumps to activate, deepSleep", LOG_NOPUMPS);
|
||||||
digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
|
secondsToSleep = deepSleepTime.get();
|
||||||
digitalWrite(OUTPUT_ENABLE_SENSOR, LOW);
|
|
||||||
for (int i = 0; i < MAX_PLANTS; i++)
|
|
||||||
{
|
|
||||||
mPlants[i].deactivatePump();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gpio_hold_en(OUTPUT_PUMP0);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP1);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP2);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP3);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP4);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP5);
|
|
||||||
gpio_hold_en(OUTPUT_PUMP6);
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
|
||||||
gpio_hold_en(TIMED_LIGHT_PIN);
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
|
||||||
|
|
||||||
|
esp_sleep_enable_timer_wakeup((secondsToSleep * 1000U * 1000U));
|
||||||
esp_sleep_enable_timer_wakeup((seconds * 1000U * 1000U));
|
|
||||||
if (mAliveWasRead)
|
if (mAliveWasRead)
|
||||||
{
|
{
|
||||||
delay(1000);
|
delay(1000);
|
||||||
@ -384,7 +374,7 @@ void onHomieEvent(const HomieEvent &event)
|
|||||||
}
|
}
|
||||||
mSensorsRead = true; // MQTT is working, deactivate timeout logic
|
mSensorsRead = true; // MQTT is working, deactivate timeout logic
|
||||||
|
|
||||||
configTime(0, 0, ntpServer.get());
|
configTime(3600, 3600, ntpServer.get());
|
||||||
|
|
||||||
{
|
{
|
||||||
getTopic(TEST_TOPIC, testopic)
|
getTopic(TEST_TOPIC, testopic)
|
||||||
@ -596,6 +586,61 @@ bool switch7(const HomieRange &range, const String &value)
|
|||||||
return mPlants[6].switchHandler(range, value);
|
return mPlants[6].switchHandler(range, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pumpStarted = false;
|
||||||
|
long pumpTarget = -1;
|
||||||
|
#ifdef FLOWMETER
|
||||||
|
long pumpTargetMl = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void pumpActiveLoop()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!pumpStarted)
|
||||||
|
{
|
||||||
|
//enable power
|
||||||
|
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
||||||
|
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
|
||||||
|
delay(100);
|
||||||
|
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1);
|
||||||
|
|
||||||
|
mPlants[pumpToRun].activatePump();
|
||||||
|
//set targets
|
||||||
|
pumpTarget = millis() + (mPlants[pumpToRun].getPumpDuration() * 1000);
|
||||||
|
#ifdef FLOWMETER
|
||||||
|
pumpTargetMl = mPlants[pumpToRun].getPumpDuration();
|
||||||
|
#endif
|
||||||
|
pumpStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool targetReached = false;
|
||||||
|
#ifdef FLOWMETER
|
||||||
|
long pumped = //readFlowMeterCounter * ratio;
|
||||||
|
if(pumped >= pumpTargetMl))
|
||||||
|
{
|
||||||
|
targetReached = true;
|
||||||
|
}
|
||||||
|
mPlants[pumpToRun].setProperty("waterusage").send(String(pumped));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (millis() > pumpTarget)
|
||||||
|
{
|
||||||
|
targetReached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetReached)
|
||||||
|
{
|
||||||
|
//disable all
|
||||||
|
digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
|
||||||
|
for (int i = 0; i < MAX_PLANTS; i++)
|
||||||
|
{
|
||||||
|
mPlants[i].deactivatePump();
|
||||||
|
}
|
||||||
|
//disable loop, to prevent multi processing
|
||||||
|
pumpStarted = false;
|
||||||
|
espDeepSleep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Startup function
|
* @brief Startup function
|
||||||
* Is called once, the controller is started
|
* Is called once, the controller is started
|
||||||
@ -611,21 +656,12 @@ void setup()
|
|||||||
WiFi.mode(WIFI_OFF);
|
WiFi.mode(WIFI_OFF);
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
|
|
||||||
//restore state before releasing pin, to prevent flickering
|
//restore state before releasing pin, to prevent flickering
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
pinMode(TIMED_LIGHT_PIN, OUTPUT);
|
pinMode(TIMED_LIGHT_PIN, OUTPUT);
|
||||||
digitalWrite(TIMED_LIGHT_PIN, timedLightOn);
|
digitalWrite(TIMED_LIGHT_PIN, timedLightOn);
|
||||||
gpio_hold_dis(TIMED_LIGHT_PIN);
|
gpio_hold_dis(TIMED_LIGHT_PIN);
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP0);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP1);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP2);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP3);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP4);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP5);
|
|
||||||
gpio_hold_dis(OUTPUT_PUMP6);
|
|
||||||
gpio_hold_dis(OUTPUT_ENABLE_PUMP);
|
|
||||||
|
|
||||||
/* Intialize Plant */
|
/* Intialize Plant */
|
||||||
for (int i = 0; i < MAX_PLANTS; i++)
|
for (int i = 0; i < MAX_PLANTS; i++)
|
||||||
@ -691,7 +727,6 @@ void setup()
|
|||||||
deepSleepTime.setDefaultValue(600).setValidator([](long candidate)
|
deepSleepTime.setDefaultValue(600).setValidator([](long candidate)
|
||||||
{ return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); });
|
{ return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); });
|
||||||
deepSleepNightTime.setDefaultValue(600);
|
deepSleepNightTime.setDefaultValue(600);
|
||||||
wateringDeepSleep.setDefaultValue(5);
|
|
||||||
ntpServer.setDefaultValue("pool.ntp.org");
|
ntpServer.setDefaultValue("pool.ntp.org");
|
||||||
|
|
||||||
/* waterLevelMax 1000 */ /* 100cm in mm */
|
/* waterLevelMax 1000 */ /* 100cm in mm */
|
||||||
@ -701,18 +736,17 @@ void setup()
|
|||||||
lipoSensorAddr.setDefaultValue("");
|
lipoSensorAddr.setDefaultValue("");
|
||||||
waterSensorAddr.setDefaultValue("");
|
waterSensorAddr.setDefaultValue("");
|
||||||
pumpIneffectiveWarning.setDefaultValue(5).setValidator([](long candidate)
|
pumpIneffectiveWarning.setDefaultValue(5).setValidator([](long candidate)
|
||||||
{ return (candidate > 0) && (candidate < (20)); });
|
{ return (candidate > 0) && (candidate < (20)); });
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
timedLightStart.setDefaultValue(18).setValidator([](long candidate)
|
timedLightStart.setDefaultValue(18).setValidator([](long candidate)
|
||||||
{ return (candidate > 0) && (candidate < (25)); });
|
{ return (candidate > 0) && (candidate < (25)); });
|
||||||
timedLightEnd.setDefaultValue(23).setValidator([](long candidate)
|
timedLightEnd.setDefaultValue(23).setValidator([](long candidate)
|
||||||
{ return (candidate > 0) && (candidate < (24)); });
|
{ return (candidate > 0) && (candidate < (24)); });
|
||||||
timedLightOnlyWhenDark.setDefaultValue(true);
|
timedLightOnlyWhenDark.setDefaultValue(true);
|
||||||
timedLightVoltageCutoff.setDefaultValue(3.8).setValidator([](double candidate)
|
timedLightVoltageCutoff.setDefaultValue(3.8).setValidator([](double candidate)
|
||||||
{ return (candidate > 3.3) && (candidate < (4.2)); });
|
{ return (candidate > 3.3) && (candidate < (4.2)); });
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
|
||||||
Homie.setLoopFunction(homieLoop);
|
Homie.setLoopFunction(homieLoop);
|
||||||
Homie.onEvent(onHomieEvent);
|
Homie.onEvent(onHomieEvent);
|
||||||
@ -779,7 +813,7 @@ void setup()
|
|||||||
if (restoredConfig)
|
if (restoredConfig)
|
||||||
{
|
{
|
||||||
deleteFile(CONFIG_FILE_BACKUP);
|
deleteFile(CONFIG_FILE_BACKUP);
|
||||||
espDeepSleepFor(1, false);
|
espDeepSleep();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -797,6 +831,28 @@ void setup()
|
|||||||
setupFinishedTimestamp = millis();
|
setupFinishedTimestamp = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void selfTest()
|
||||||
|
{
|
||||||
|
if (pumpToRun >= 0 && pumpToRun < MAX_PLANTS)
|
||||||
|
{
|
||||||
|
mPlants[pumpToRun].deactivatePump();
|
||||||
|
}
|
||||||
|
if (pumpToRun >= MAX_PLANTS)
|
||||||
|
{
|
||||||
|
digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
|
||||||
|
nextBlink = millis() + 500;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pumpToRun++;
|
||||||
|
nextBlink = millis() + 5000;
|
||||||
|
}
|
||||||
|
if (pumpToRun < MAX_PLANTS)
|
||||||
|
{
|
||||||
|
mPlants[pumpToRun].activatePump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Cyclic call
|
* @brief Cyclic call
|
||||||
* Executs the Homie base functionallity or triggers sleeping, if requested.
|
* Executs the Homie base functionallity or triggers sleeping, if requested.
|
||||||
@ -816,24 +872,7 @@ void loop()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lastPumpRunning >= 0 && lastPumpRunning < MAX_PLANTS)
|
selfTest();
|
||||||
{
|
|
||||||
mPlants[lastPumpRunning].deactivatePump();
|
|
||||||
}
|
|
||||||
if (lastPumpRunning >= MAX_PLANTS)
|
|
||||||
{
|
|
||||||
digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
|
|
||||||
nextBlink = millis() + 500;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastPumpRunning++;
|
|
||||||
nextBlink = millis() + 5000;
|
|
||||||
}
|
|
||||||
if (lastPumpRunning < MAX_PLANTS)
|
|
||||||
{
|
|
||||||
mPlants[lastPumpRunning].activatePump();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -858,6 +897,11 @@ void loop()
|
|||||||
Serial.flush();
|
Serial.flush();
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pumpToRun != -1)
|
||||||
|
{
|
||||||
|
pumpActiveLoop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -866,14 +910,6 @@ void loop()
|
|||||||
*/
|
*/
|
||||||
void plantcontrol()
|
void plantcontrol()
|
||||||
{
|
{
|
||||||
if (lastPumpRunning != -1)
|
|
||||||
{
|
|
||||||
long waterDiff = waterRawSensor.getAverage() - lastWaterValue;
|
|
||||||
mPlants[lastPumpRunning].setProperty("waterusage").send(String(waterDiff));
|
|
||||||
/* TODO convert diff into volume (milli liter) */
|
|
||||||
Serial << "Plant" << lastPumpRunning << ": Water diff " << waterDiff << " mm" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAliveWasRead)
|
if (mAliveWasRead)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_PLANTS; i++)
|
for (int i = 0; i < MAX_PLANTS; i++)
|
||||||
@ -922,95 +958,82 @@ void plantcontrol()
|
|||||||
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
|
bool isLowLight = (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE);
|
||||||
bool hasWater = true; //FIXMEmWaterGone > waterLevelMin.get();
|
bool hasWater = true; //FIXMEmWaterGone > waterLevelMin.get();
|
||||||
//FIXME no water warning message
|
//FIXME no water warning message
|
||||||
lastPumpRunning = determineNextPump(isLowLight);
|
pumpToRun = determineNextPump(isLowLight);
|
||||||
if (lastPumpRunning != -1 && !hasWater)
|
//early aborts
|
||||||
|
if (pumpToRun != -1)
|
||||||
{
|
{
|
||||||
log(LOG_LEVEL_ERROR, LOG_PUMP_BUTNOTANK_MESSAGE, LOG_PUMP_BUTNOTANK_CODE);
|
if (hasWater)
|
||||||
}
|
|
||||||
else if (lastPumpRunning != -1 && hasWater)
|
|
||||||
{
|
|
||||||
if (mDownloadMode)
|
|
||||||
{
|
{
|
||||||
log(LOG_LEVEL_INFO, LOG_PUMP_AND_DOWNLOADMODE, LOG_PUMP_AND_DOWNLOADMODE_CODE);
|
if (mDownloadMode)
|
||||||
|
{
|
||||||
|
log(LOG_LEVEL_INFO, LOG_PUMP_AND_DOWNLOADMODE, LOG_PUMP_AND_DOWNLOADMODE_CODE);
|
||||||
|
pumpToRun = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//prevent BOD to be paranoid
|
log(LOG_LEVEL_ERROR, LOG_PUMP_BUTNOTANK_MESSAGE, LOG_PUMP_BUTNOTANK_CODE);
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
pumpToRun = -1;
|
||||||
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
|
|
||||||
delay(100);
|
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1);
|
|
||||||
|
|
||||||
rtcLastWateringPlant[lastPumpRunning] = getCurrentTime();
|
|
||||||
mPlants[lastPumpRunning].activatePump();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(TIMED_LIGHT_PIN)
|
// go directly to sleep, skipping the pump loop
|
||||||
bool shouldLight = determineTimedLightState(isLowLight);
|
if (pumpToRun == -1)
|
||||||
timedLightOn = shouldLight;
|
|
||||||
digitalWrite(TIMED_LIGHT_PIN, shouldLight);
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
|
||||||
|
|
||||||
|
|
||||||
/* Always handle one of the deep sleep duration */
|
|
||||||
if (lastPumpRunning == -1 || !hasWater)
|
|
||||||
{
|
{
|
||||||
if (mSolarVoltage < SOLAR_CHARGE_MIN_VOLTAGE)
|
espDeepSleep();
|
||||||
{
|
|
||||||
log(LOG_LEVEL_INFO, String(String(mSolarVoltage) + "V! No pumps to activate and low light, deepSleepNight"), LOG_NOPUMP_LOWLIGHT);
|
|
||||||
espDeepSleepFor(deepSleepNightTime.get(), false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log(LOG_LEVEL_INFO, "No pumps to activate, deepSleep", LOG_NOPUMPS);
|
|
||||||
espDeepSleepFor(deepSleepTime.get(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
espDeepSleepFor(wateringDeepSleep.get(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(TIMED_LIGHT_PIN)
|
||||||
|
bool shouldLight = determineTimedLightState(isLowLight);
|
||||||
|
timedLightOn = shouldLight;
|
||||||
|
digitalWrite(TIMED_LIGHT_PIN, shouldLight);
|
||||||
|
#endif // TIMED_LIGHT_PIN
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @}*/
|
/** @}*/
|
||||||
|
|
||||||
|
bool determineTimedLightState(bool lowLight)
|
||||||
bool determineTimedLightState(bool lowLight){
|
{
|
||||||
bool onlyAllowedWhenDark = timedLightOnlyWhenDark.get();
|
bool onlyAllowedWhenDark = timedLightOnlyWhenDark.get();
|
||||||
long hoursStart = timedLightStart.get();
|
long hoursStart = timedLightStart.get();
|
||||||
long hoursEnd = timedLightEnd.get();
|
long hoursEnd = timedLightEnd.get();
|
||||||
|
|
||||||
//ntp missing
|
//ntp missing
|
||||||
if(getCurrentTime() < 10000){
|
if (getCurrentTime() < 10000)
|
||||||
|
{
|
||||||
timedLightNode.setProperty("state").send(String("Off, missing ntp"));
|
timedLightNode.setProperty("state").send(String("Off, missing ntp"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(onlyAllowedWhenDark && !lowLight){
|
if (onlyAllowedWhenDark && !lowLight)
|
||||||
|
{
|
||||||
timedLightNode.setProperty("state").send(String("Off, not dark"));
|
timedLightNode.setProperty("state").send(String("Off, not dark"));
|
||||||
timedLightLowVoltageTriggered = false;
|
timedLightLowVoltageTriggered = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((hoursStart > hoursEnd) &&
|
if (((hoursStart > hoursEnd) &&
|
||||||
(getCurrentHour() >= hoursStart || getCurrentHour() <= hoursEnd)) ||
|
(getCurrentHour() >= hoursStart || getCurrentHour() <= hoursEnd)) ||
|
||||||
/* Handle e.g. start = 8, end = 21 */
|
/* Handle e.g. start = 8, end = 21 */
|
||||||
((hoursStart < hoursEnd) &&
|
((hoursStart < hoursEnd) &&
|
||||||
(getCurrentHour() >= hoursStart && getCurrentHour() <= hoursEnd)))
|
(getCurrentHour() >= hoursStart && getCurrentHour() <= hoursEnd)))
|
||||||
{
|
{
|
||||||
if(!timedLightLowVoltageTriggered && battery.getVoltage(BATTSENSOR_INDEX_BATTERY) >= timedLightVoltageCutoff.get() ){
|
if (!timedLightLowVoltageTriggered && battery.getVoltage(BATTSENSOR_INDEX_BATTERY) >= timedLightVoltageCutoff.get())
|
||||||
timedLightNode.setProperty("state").send(String("On"));
|
{
|
||||||
return true;
|
timedLightNode.setProperty("state").send(String("On"));
|
||||||
}else {
|
return true;
|
||||||
timedLightNode.setProperty("state").send(String("Off, due to missing voltage"));
|
}
|
||||||
timedLightLowVoltageTriggered = true;
|
else
|
||||||
return false;
|
{
|
||||||
}
|
timedLightNode.setProperty("state").send(String("Off, due to missing voltage"));
|
||||||
|
timedLightLowVoltageTriggered = true;
|
||||||
} else {
|
return false;
|
||||||
timedLightNode.setProperty("state").send(String("Off, outside worktime"));
|
}
|
||||||
return false;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
timedLightNode.setProperty("state").send(String("Off, outside worktime"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(int level, String message, int statusCode)
|
void log(int level, String message, int statusCode)
|
||||||
|
Loading…
Reference in New Issue
Block a user