Merge branch 'master' of github.com:0110/PlantCtrl
This commit is contained in:
commit
68386ce02f
@ -94,7 +94,7 @@
|
|||||||
#define MOIST_SENSOR_MIN_FRQ 500 // 0.5kHz (500Hz margin)
|
#define MOIST_SENSOR_MIN_FRQ 500 // 0.5kHz (500Hz margin)
|
||||||
|
|
||||||
#define ANALOG_SENSOR_MAX_MV 1300 //successive approximation of good range
|
#define ANALOG_SENSOR_MAX_MV 1300 //successive approximation of good range
|
||||||
#define ANALOG_SENSOR_MIN_MV 300 //successive approximation of good range
|
#define ANALOG_SENSOR_MIN_MV 100 //successive approximation of good range
|
||||||
|
|
||||||
#define SOLAR_VOLT_FACTOR 11
|
#define SOLAR_VOLT_FACTOR 11
|
||||||
#define BATTSENSOR_INDEX_SOLAR 0
|
#define BATTSENSOR_INDEX_SOLAR 0
|
||||||
|
@ -45,6 +45,8 @@ static const char *SENSOR_STRING[] = {
|
|||||||
#define MISSING_SENSOR -2
|
#define MISSING_SENSOR -2
|
||||||
//plant uses only cooldown and duration, moisture is measured but ignored, allowedHours is ignored (eg. make a 30min on 30min off cycle)
|
//plant uses only cooldown and duration, moisture is measured but ignored, allowedHours is ignored (eg. make a 30min on 30min off cycle)
|
||||||
#define HYDROPONIC_MODE -3
|
#define HYDROPONIC_MODE -3
|
||||||
|
//plant uses cooldown and duration and workhours, moisture is measured but ignored
|
||||||
|
#define TIMER_ONLY -4
|
||||||
|
|
||||||
typedef struct PlantSettings_t
|
typedef struct PlantSettings_t
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
#define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request"
|
#define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request"
|
||||||
#define LOG_PUMP_AND_DOWNLOADMODE_CODE 2
|
#define LOG_PUMP_AND_DOWNLOADMODE_CODE 2
|
||||||
|
|
||||||
|
#define LOG_VERY_COLD_WATER "Water potentially frozen, ignoring pump request"
|
||||||
|
#define LOG_VERY_COLD_WATER -7
|
||||||
|
|
||||||
//msg is dynamic defined
|
//msg is dynamic defined
|
||||||
#define LOG_PUMP_INEFFECTIVE -4
|
#define LOG_PUMP_INEFFECTIVE -4
|
||||||
#define LOG_PUMP_STARTED_CODE 10
|
#define LOG_PUMP_STARTED_CODE 10
|
||||||
|
@ -73,6 +73,12 @@ public:
|
|||||||
return SENSOR_STRING[mode];
|
return SENSOR_STRING[mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTimerOnly()
|
||||||
|
{
|
||||||
|
long current = this->mSetting->pSensorDry->get();
|
||||||
|
return equalish(current, TIMER_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
bool isHydroponic()
|
bool isHydroponic()
|
||||||
{
|
{
|
||||||
long current = this->mSetting->pSensorDry->get();
|
long current = this->mSetting->pSensorDry->get();
|
||||||
@ -92,7 +98,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isPumpRequired()
|
bool isPumpRequired()
|
||||||
{
|
{
|
||||||
if (isHydroponic())
|
if (isHydroponic() || isTimerOnly())
|
||||||
{
|
{
|
||||||
// hydroponic only uses timer based controll
|
// hydroponic only uses timer based controll
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,7 +30,7 @@ void Plant::init(void)
|
|||||||
/* Initialize Home Settings validator */
|
/* Initialize Home Settings validator */
|
||||||
this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT);
|
this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT);
|
||||||
this->mSetting->pSensorDry->setValidator([](long candidate)
|
this->mSetting->pSensorDry->setValidator([](long candidate)
|
||||||
{ return (((candidate >= 0.0) && (candidate <= 100.0)) || equalish(candidate, DEACTIVATED_PLANT) || equalish(candidate, HYDROPONIC_MODE)); });
|
{ return (((candidate >= 0.0) && (candidate <= 100.0)) || equalish(candidate, DEACTIVATED_PLANT) || equalish(candidate, HYDROPONIC_MODE) || equalish(candidate, TIMER_ONLY)); });
|
||||||
|
|
||||||
this->mSetting->pPumpAllowedHourRangeStart->setDefaultValue(8); // start at 8:00
|
this->mSetting->pPumpAllowedHourRangeStart->setDefaultValue(8); // start at 8:00
|
||||||
this->mSetting->pPumpAllowedHourRangeStart->setValidator([](long candidate)
|
this->mSetting->pPumpAllowedHourRangeStart->setValidator([](long candidate)
|
||||||
@ -38,7 +38,7 @@ void Plant::init(void)
|
|||||||
this->mSetting->pPumpAllowedHourRangeEnd->setDefaultValue(20); // stop pumps at 20:00
|
this->mSetting->pPumpAllowedHourRangeEnd->setDefaultValue(20); // stop pumps at 20:00
|
||||||
this->mSetting->pPumpAllowedHourRangeEnd->setValidator([](long candidate)
|
this->mSetting->pPumpAllowedHourRangeEnd->setValidator([](long candidate)
|
||||||
{ return ((candidate >= 0) && (candidate <= 23)); });
|
{ return ((candidate >= 0) && (candidate <= 23)); });
|
||||||
this->mSetting->pPumpOnlyWhenLowLight->setDefaultValue(true);
|
this->mSetting->pPumpOnlyWhenLowLight->setDefaultValue(false);
|
||||||
this->mSetting->pPumpCooldownInSeconds->setDefaultValue(60 * 60); // 1 hour
|
this->mSetting->pPumpCooldownInSeconds->setDefaultValue(60 * 60); // 1 hour
|
||||||
this->mSetting->pPumpCooldownInSeconds->setValidator([](long candidate)
|
this->mSetting->pPumpCooldownInSeconds->setValidator([](long candidate)
|
||||||
{ return (candidate >= 0); });
|
{ return (candidate >= 0); });
|
||||||
@ -263,9 +263,9 @@ void Plant::advertise(void)
|
|||||||
{
|
{
|
||||||
// Advertise topics
|
// Advertise topics
|
||||||
mPump = this->mPlant->advertise("switch").setName("Pump").setDatatype("Boolean");
|
mPump = this->mPlant->advertise("switch").setName("Pump").setDatatype("Boolean");
|
||||||
this->mPlant->advertise("lastPump").setName("lastPump").setDatatype("Integer").setUnit("unixtime");
|
this->mPlant->advertise("lastPump").setName("lastPump").setDatatype("Integer").setUnit("unixtime").setRetained(true);
|
||||||
this->mPlant->advertise("moist").setName("Percent").setDatatype("Float").setUnit("%");
|
this->mPlant->advertise("moist").setName("Percent").setDatatype("Float").setUnit("%").setRetained(true);
|
||||||
this->mPlant->advertise("moistraw").setName("adc").setDatatype("Float").setUnit("3.3/4096V");
|
this->mPlant->advertise("moistraw").setName("adc").setDatatype("Float").setUnit("3.3/4096V").setRetained(true);
|
||||||
this->mPlant->advertise("state").setName("state").setDatatype("String");
|
this->mPlant->advertise("state").setName("state").setDatatype("String").setRetained(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include "ulp-pwm.h"
|
#include "ulp-pwm.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -56,6 +55,7 @@ int determineNextPump(bool lowLight);
|
|||||||
void plantcontrol();
|
void plantcontrol();
|
||||||
void readPowerSwitchedSensors();
|
void readPowerSwitchedSensors();
|
||||||
bool determineTimedLightState(bool lowLight);
|
bool determineTimedLightState(bool lowLight);
|
||||||
|
bool otaRunning = false;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NON VOLATILE VARIABLES in DEEP SLEEP
|
* NON VOLATILE VARIABLES in DEEP SLEEP
|
||||||
@ -90,6 +90,8 @@ long lastSendPumpUpdate = 0;
|
|||||||
long pumpTargetMl = -1;
|
long pumpTargetMl = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
float waterTemp = 30;
|
||||||
|
|
||||||
/*************************** Hardware abstraction *****************************/
|
/*************************** Hardware abstraction *****************************/
|
||||||
|
|
||||||
OneWire oneWire(SENSOR_ONEWIRE);
|
OneWire oneWire(SENSOR_ONEWIRE);
|
||||||
@ -267,6 +269,7 @@ void readOneWireSensors()
|
|||||||
{
|
{
|
||||||
mqttWrite(&sensorTemp, TEMPERATUR_SENSOR_WATER, String(temp));
|
mqttWrite(&sensorTemp, TEMPERATUR_SENSOR_WATER, String(temp));
|
||||||
Serial << "Water Temperatur " << temp << " °C " << endl;
|
Serial << "Water Temperatur " << temp << " °C " << endl;
|
||||||
|
waterTemp = temp;
|
||||||
}
|
}
|
||||||
/* Always send the sensor address with the temperatur value */
|
/* Always send the sensor address with the temperatur value */
|
||||||
mqttWrite(&sensorTemp, String(buf), String(temp));
|
mqttWrite(&sensorTemp, String(buf), String(temp));
|
||||||
@ -401,10 +404,7 @@ void onHomieEvent(const HomieEvent &event)
|
|||||||
{
|
{
|
||||||
mPlants[i].deactivatePump();
|
mPlants[i].deactivatePump();
|
||||||
}
|
}
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
otaRunning = true;
|
||||||
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
|
|
||||||
delay(100);
|
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1);
|
|
||||||
mDownloadMode = true;
|
mDownloadMode = true;
|
||||||
break;
|
break;
|
||||||
case HomieEventType::OTA_SUCCESSFUL:
|
case HomieEventType::OTA_SUCCESSFUL:
|
||||||
@ -461,7 +461,7 @@ int determineNextPump(bool isLowLight)
|
|||||||
log(LOG_LEVEL_DEBUG, String(String(i) + " No pump required: due to light"), LOG_DEBUG_CODE);
|
log(LOG_LEVEL_DEBUG, String(String(i) + " No pump required: due to light"), LOG_DEBUG_CODE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!plant.isHydroponic())
|
if (! (plant.isHydroponic() || plant.isTimerOnly()))
|
||||||
{
|
{
|
||||||
if (equalish(plant.getCurrentMoistureRaw(), MISSING_SENSOR))
|
if (equalish(plant.getCurrentMoistureRaw(), MISSING_SENSOR))
|
||||||
{
|
{
|
||||||
@ -493,10 +493,9 @@ int determineNextPump(bool isLowLight)
|
|||||||
}else {
|
}else {
|
||||||
plant.publishState("active");
|
plant.publishState("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!plant.isHydroponic())
|
if (! (plant.isHydroponic() || plant.isTimerOnly()))
|
||||||
{
|
{
|
||||||
consecutiveWateringPlant[i]++;
|
consecutiveWateringPlant[i]++;
|
||||||
}
|
}
|
||||||
@ -676,7 +675,6 @@ long duration = millis() - pumpStartTime;
|
|||||||
log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE);
|
log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE);
|
||||||
targetReached = true;
|
targetReached = true;
|
||||||
log(LOG_LEVEL_INFO, "Reached pump target ml " + String(pumpToRun), LOG_PUMP_STARTED_CODE);
|
log(LOG_LEVEL_INFO, "Reached pump target ml " + String(pumpToRun), LOG_PUMP_STARTED_CODE);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -697,7 +695,6 @@ long duration = millis() - pumpStartTime;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (millis() > pumpTarget)
|
if (millis() > pumpTarget)
|
||||||
{
|
{
|
||||||
mPlants[pumpToRun].setProperty("watertime").send(String(duration));
|
mPlants[pumpToRun].setProperty("watertime").send(String(duration));
|
||||||
@ -753,12 +750,14 @@ void safeSetup()
|
|||||||
|
|
||||||
pinMode(OUTPUT_ENABLE_SENSOR, OUTPUT);
|
pinMode(OUTPUT_ENABLE_SENSOR, OUTPUT);
|
||||||
|
|
||||||
|
static_assert(HomieInternals::MAX_CONFIG_SETTING_SIZE >= MAX_CONFIG_SETTING_ITEMS, "Limits.hpp not adjusted MAX_CONFIG_SETTING_ITEMS");
|
||||||
if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS)
|
if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS)
|
||||||
{
|
{
|
||||||
// increase the config settings
|
// increase the config settings
|
||||||
Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl;
|
Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
static_assert(HomieInternals::MAX_JSON_CONFIG_FILE_SIZE >= MAX_JSON_CONFIG_FILE_SIZE_CUSTOM, "Limits.hpp not adjusted MAX_JSON_CONFIG_FILE_SIZE");
|
||||||
if (HomieInternals::MAX_JSON_CONFIG_FILE_SIZE < MAX_JSON_CONFIG_FILE_SIZE_CUSTOM)
|
if (HomieInternals::MAX_JSON_CONFIG_FILE_SIZE < MAX_JSON_CONFIG_FILE_SIZE_CUSTOM)
|
||||||
{
|
{
|
||||||
// increase the config settings
|
// increase the config settings
|
||||||
@ -809,14 +808,12 @@ void safeSetup()
|
|||||||
}
|
}
|
||||||
readPowerSwitchedSensors();
|
readPowerSwitchedSensors();
|
||||||
|
|
||||||
|
|
||||||
Homie.setup();
|
Homie.setup();
|
||||||
|
|
||||||
Wire = TwoWire(0);
|
Wire = TwoWire(0);
|
||||||
Wire.setPins(SENSOR_TANK_SDA, SENSOR_TANK_SCL);
|
Wire.setPins(SENSOR_TANK_SDA, SENSOR_TANK_SCL);
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
|
|
||||||
|
|
||||||
/************************* Start One-Wire bus ***************/
|
/************************* Start One-Wire bus ***************/
|
||||||
int tempInitStartTime = millis();
|
int tempInitStartTime = millis();
|
||||||
uint8_t sensorCount = 0U;
|
uint8_t sensorCount = 0U;
|
||||||
@ -981,7 +978,14 @@ void loop()
|
|||||||
digitalWrite(OUTPUT_ENABLE_SENSOR, !digitalRead(OUTPUT_ENABLE_SENSOR));
|
digitalWrite(OUTPUT_ENABLE_SENSOR, !digitalRead(OUTPUT_ENABLE_SENSOR));
|
||||||
if (mConfigured)
|
if (mConfigured)
|
||||||
{
|
{
|
||||||
nextBlink = millis() + 500;
|
if (otaRunning)
|
||||||
|
{
|
||||||
|
nextBlink = millis() + 100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextBlink = millis() + 501;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1078,12 +1082,14 @@ void plantcontrol()
|
|||||||
|
|
||||||
#endif // TIMED_LIGHT_PIN
|
#endif // TIMED_LIGHT_PIN
|
||||||
|
|
||||||
|
bool isLiquid = waterTemp > 5;
|
||||||
bool hasWater = true; // FIXME remaining > waterLevelMin.get();
|
bool hasWater = true; // FIXME remaining > waterLevelMin.get();
|
||||||
// FIXME no water warning message
|
// FIXME no water warning message
|
||||||
pumpToRun = determineNextPump(isLowLight);
|
pumpToRun = determineNextPump(isLowLight);
|
||||||
// early aborts
|
// early aborts
|
||||||
if (pumpToRun != -1)
|
if (pumpToRun != -1)
|
||||||
{
|
{
|
||||||
|
if(isLiquid){
|
||||||
if (hasWater)
|
if (hasWater)
|
||||||
{
|
{
|
||||||
if (mDownloadMode)
|
if (mDownloadMode)
|
||||||
@ -1098,6 +1104,11 @@ void plantcontrol()
|
|||||||
pumpToRun = -1;
|
pumpToRun = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
log(LOG_LEVEL_ERROR, LOG_PUMP_BUTNOTANK_MESSAGE, LOG_PUMP_BUTNOTANK_CODE);
|
||||||
|
pumpToRun = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// go directly to sleep, skipping the pump loop
|
// go directly to sleep, skipping the pump loop
|
||||||
if (pumpToRun == -1)
|
if (pumpToRun == -1)
|
||||||
@ -1129,9 +1140,11 @@ bool determineTimedLightState(bool lowLight)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int curHour = getCurrentHour();
|
int curHour = getCurrentHour();
|
||||||
|
|
||||||
bool condition1 = ((hoursStart > hoursEnd) &&
|
bool condition1 = ((hoursStart > hoursEnd) &&
|
||||||
(curHour >= hoursStart || curHour <= hoursEnd));
|
(curHour >= hoursStart || curHour <= hoursEnd));
|
||||||
bool condition2 = /* Handle e.g. start = 8, end = 21 */
|
bool condition2 = /* Handle e.g. start = 8, end = 21 */
|
||||||
|
|
||||||
((hoursStart < hoursEnd) &&
|
((hoursStart < hoursEnd) &&
|
||||||
(curHour >= hoursStart && curHour <= hoursEnd));
|
(curHour >= hoursStart && curHour <= hoursEnd));
|
||||||
timedLightNode.setProperty("debug").send(String(curHour) + " " + String(hoursStart) + " " + String(hoursEnd) + " " + String(condition1) + " " + String(condition2));
|
timedLightNode.setProperty("debug").send(String(curHour) + " " + String(hoursStart) + " " + String(hoursEnd) + " " + String(condition1) + " " + String(condition2));
|
||||||
|
Loading…
Reference in New Issue
Block a user