diff --git a/esp32/include/ControllerConfiguration.h b/esp32/include/ControllerConfiguration.h index e124079..43ef4f0 100644 --- a/esp32/include/ControllerConfiguration.h +++ b/esp32/include/ControllerConfiguration.h @@ -11,55 +11,57 @@ #ifndef CONTROLLER_CONFIG_H #define CONTROLLER_CONFIG_H -#define FIRMWARE_VERSION "1.0.7" +#define FIRMWARE_VERSION "1.0.7" #define ADC_TO_VOLT(adc) ((adc) * 3.3 ) / 4095) -#define ADC_TO_VOLT_WITH_MULTI(adc, multi) (((adc) * 3.3 * (multi)) / 4095) +#define ADC_TO_VOLT_WITH_MULTI(adc, multi) (((adc)*3.3 * (multi)) / 4095) +#define MOIST_SENSOR_MAX_ADC 85 * 4095 / 100 +#define MOIST_SENSOR_MIN_ADC 25 * 4095 / 100 -#define SOLAR_VOLT(adc) ADC_TO_VOLT_WITH_MULTI(adc, 4.0306) /**< 100k and 33k voltage dividor */ -#define ADC_5V_TO_3V3(adc) ADC_TO_VOLT_WITH_MULTI(adc, 1.7) /**< 33k and 47k8 voltage dividor */ -#define MS_TO_S 1000 +#define SOLAR_VOLT(adc) ADC_TO_VOLT_WITH_MULTI(adc, 4.0306) /**< 100k and 33k voltage dividor */ +#define ADC_5V_TO_3V3(adc) ADC_TO_VOLT_WITH_MULTI(adc, 1.7) /**< 33k and 47k8 voltage dividor */ +#define MS_TO_S 1000 -#define SENSOR_LIPO 34 /**< GPIO 34 (ADC1) */ -#define SENSOR_SOLAR 35 /**< GPIO 35 (ADC1) */ -#define SENSOR_PLANT0 32 /**< GPIO 32 (ADC1) */ -#define SENSOR_PLANT1 33 /**< GPIO 33 (ADC1) */ -#define SENSOR_PLANT2 25 /**< GPIO 25 (ADC2) */ -#define SENSOR_PLANT3 26 /**< GPIO 26 (ADC2) */ -#define SENSOR_PLANT4 27 /**< GPIO 27 (ADC2) */ -#define SENSOR_PLANT5 14 /**< GPIO 14 (ADC2) */ -#define SENSOR_PLANT6 12 /**< GPIO 12 (ADC2) */ +#define SENSOR_LIPO 34 /**< GPIO 34 (ADC1) */ +#define SENSOR_SOLAR 35 /**< GPIO 35 (ADC1) */ +#define SENSOR_PLANT0 32 /**< GPIO 32 (ADC1) */ +#define SENSOR_PLANT1 33 /**< GPIO 33 (ADC1) */ +#define SENSOR_PLANT2 25 /**< GPIO 25 (ADC2) */ +#define SENSOR_PLANT3 26 /**< GPIO 26 (ADC2) */ +#define SENSOR_PLANT4 27 /**< GPIO 27 (ADC2) */ +#define SENSOR_PLANT5 14 /**< GPIO 14 (ADC2) */ +#define SENSOR_PLANT6 12 /**< GPIO 12 (ADC2) */ -#define OUTPUT_PUMP0 23 /**< GPIO 23 */ -#define OUTPUT_PUMP1 22 /**< GPIO 22 */ -#define OUTPUT_PUMP2 21 /**< GPIO 21 */ -#define OUTPUT_PUMP3 19 /**< GPIO 19 */ -#define OUTPUT_PUMP4 18 /**< GPIO 18 */ -#define OUTPUT_PUMP5 5 /**< GPIO 5 */ -#define OUTPUT_PUMP6 15 /**< GPIO 15 */ - -#define OUTPUT_SENSOR 16 /**< GPIO 16 - Enable Sensors */ -#define OUTPUT_PUMP 13 /**< GPIO 13 - Enable Pumps */ +#define OUTPUT_PUMP0 23 /**< GPIO 23 */ +#define OUTPUT_PUMP1 22 /**< GPIO 22 */ +#define OUTPUT_PUMP2 21 /**< GPIO 21 */ +#define OUTPUT_PUMP3 19 /**< GPIO 19 */ +#define OUTPUT_PUMP4 18 /**< GPIO 18 */ +#define OUTPUT_PUMP5 5 /**< GPIO 5 */ +#define OUTPUT_PUMP6 15 /**< GPIO 15 */ -#define SENSOR_DS18B20 2 /**< GPIO 2 */ -#define BUTTON 0 /**< GPIO 0 */ +#define OUTPUT_SENSOR 16 /**< GPIO 16 - Enable Sensors */ +#define OUTPUT_PUMP 13 /**< GPIO 13 - Enable Pumps */ -#define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */ -#define MAX_PLANTS 7 -#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 */ +#define SENSOR_DS18B20 2 /**< GPIO 2 */ +#define BUTTON 0 /**< GPIO 0 */ + +#define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */ +#define MAX_PLANTS 7 +#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 */ #define SOLAR_CHARGE_MIN_VOLTAGE 7 #define SOLAR_CHARGE_MAX_VOLTAGE 9 -#define HC_SR04 /**< Ultrasonic distance sensor to measure water level */ -#define SENSOR_SR04_ECHO 17 /**< GPIO 17 - Echo */ -#define SENSOR_SR04_TRIG 23 /**< GPIO 23 - Trigger */ +#define HC_SR04 /**< Ultrasonic distance sensor to measure water level */ +#define SENSOR_SR04_ECHO 17 /**< GPIO 17 - Echo */ +#define SENSOR_SR04_TRIG 23 /**< GPIO 23 - Trigger */ #define MAX_CONFIG_SETTING_ITEMS 50 /**< Parameter, that can be configured in Homie */ -#define PANIK_MODE_DEEPSLEEP (60*60*5U) /**< 5 hours in usecond */ -#define PANIK_MODE_DEEPSLEEP_US (PANIK_MODE_DEEPSLEEP*1000*1000) +#define PANIK_MODE_DEEPSLEEP (60 * 60 * 5U) /**< 5 hours in usecond */ +#define PANIK_MODE_DEEPSLEEP_US (PANIK_MODE_DEEPSLEEP * 1000 * 1000) #define TEMPERATURE_DELTA_TRIGGER_IN_C 1 #define MOIST_DELTA_TRIGGER_ADC 1337 diff --git a/esp32/include/DS18B20.h b/esp32/include/DS18B20.h index 7ab8e66..7910f40 100644 --- a/esp32/include/DS18B20.h +++ b/esp32/include/DS18B20.h @@ -21,32 +21,36 @@ #include -class Ds18B20 { - private: - OneWire* mDs; - int foundDevices; - public: - Ds18B20(int pin) { - this->mDs = new OneWire(pin); - } +class Ds18B20 +{ +private: + OneWire *mDs; + int foundDevices; - ~Ds18B20() { - delete this->mDs; - } - /** +public: + Ds18B20(int pin) + { + this->mDs = new OneWire(pin); + } + + ~Ds18B20() + { + delete this->mDs; + } + /** * @brief read amount sensots * check for available of DS18B20 sensors * @return amount of sensors */ - int readDevices(void); + int readDevices(void); - /** + /** * @brief Read all temperatures in celsius * * @param pTemperatures array of float valuies * @param maxTemperatures size of the given array * @return int amount of read temperature values */ - int readAllTemperatures(float* pTemperatures, int maxTemperatures); + int readAllTemperatures(float *pTemperatures, int maxTemperatures); }; #endif diff --git a/esp32/include/HomieConfiguration.h b/esp32/include/HomieConfiguration.h index 0151c68..f300a76 100644 --- a/esp32/include/HomieConfiguration.h +++ b/esp32/include/HomieConfiguration.h @@ -45,18 +45,18 @@ HomieSetting waterLevelMax("watermaxlevel", "distance (mm) at maximum wate HomieSetting waterLevelMin("waterminlevel", "distance (mm) at minimum water level (pumps still covered)"); HomieSetting waterLevelWarn("waterlevelwarn", "warn (mm) if below this water level %"); HomieSetting waterLevelVol("waterVolume", "(ml) between minimum and maximum"); -HomieSettingntpServer("ntpServer", "NTP server (pool.ntp.org as default)"); +HomieSetting ntpServer("ntpServer", "NTP server (pool.ntp.org as default)"); /** Plant specific ones */ -#define GENERATE_PLANT(plant, strplant) \ - HomieSetting mSensorDry##plant = HomieSetting("moistdry" strplant, "Plant " strplant "- Moist sensor dry threshold"); \ - HomieSetting mPumpAllowedHourRangeStart##plant = HomieSetting("rangehourstart" strplant, "Plant" strplant " - Range pump allowed hour start (0-23)"); \ - HomieSetting mPumpAllowedHourRangeEnd##plant = HomieSetting("rangehourend" strplant, "Plant" strplant " - Range pump allowed hour end (0-23)"); \ +#define GENERATE_PLANT(plant, strplant) \ + HomieSetting mSensorDry##plant = HomieSetting("moistdry" strplant, "Plant " strplant "- Moist sensor dry threshold"); \ + HomieSetting mPumpAllowedHourRangeStart##plant = HomieSetting("rangehourstart" strplant, "Plant" strplant " - Range pump allowed hour start (0-23)"); \ + HomieSetting mPumpAllowedHourRangeEnd##plant = HomieSetting("rangehourend" strplant, "Plant" strplant " - Range pump allowed hour end (0-23)"); \ HomieSetting mPumpOnlyWhenLowLight##plant = HomieSetting("onlyWhenLowLightZ" strplant, "Plant" strplant " - Enable the Pump only, when there is light but not enought to charge battery"); \ - HomieSetting mPumpCooldownInHours##plant = HomieSetting("cooldownpump" 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 mPumpCooldownInHours##plant = HomieSetting("cooldownpump" 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}; + GENERATE_PLANT(0, "0"); GENERATE_PLANT(1, "1"); GENERATE_PLANT(2, "2"); @@ -65,6 +65,4 @@ GENERATE_PLANT(4, "4"); GENERATE_PLANT(5, "5"); GENERATE_PLANT(6, "6"); - - #endif /* HOMIE_PLANT_CONFIG_H */ \ No newline at end of file diff --git a/esp32/include/HomieTypes.h b/esp32/include/HomieTypes.h index 28c9d59..2c915c5 100644 --- a/esp32/include/HomieTypes.h +++ b/esp32/include/HomieTypes.h @@ -13,14 +13,15 @@ #include -#define DEACTIVATED_PLANT 5000 +#define DEACTIVATED_PLANT 5000 -typedef struct PlantSettings_t { - HomieSetting* pSensorDry; - HomieSetting* pPumpAllowedHourRangeStart; - HomieSetting* pPumpAllowedHourRangeEnd; - HomieSetting* pPumpOnlyWhenLowLight; - HomieSetting* pPumpCooldownInHours; +typedef struct PlantSettings_t +{ + HomieSetting *pSensorDry; + HomieSetting *pPumpAllowedHourRangeStart; + HomieSetting *pPumpAllowedHourRangeEnd; + HomieSetting *pPumpOnlyWhenLowLight; + HomieSetting *pPumpCooldownInHours; } PlantSettings_t; #endif \ No newline at end of file diff --git a/esp32/include/PlantCtrl.h b/esp32/include/PlantCtrl.h index 1ba01de..6902d38 100644 --- a/esp32/include/PlantCtrl.h +++ b/esp32/include/PlantCtrl.h @@ -15,17 +15,18 @@ #include "HomieTypes.h" #include "RunningMedian.h" -class Plant { +class Plant +{ private: RunningMedian moistureRaw = RunningMedian(5); - HomieNode* mPlant = NULL; - int mPinSensor=0; /**< Pin of the moist sensor */ - int mPinPump=0; /**< Pin of the pump */ + HomieNode *mPlant = NULL; + int mPinSensor = 0; /**< Pin of the moist sensor */ + int mPinPump = 0; /**< Pin of the pump */ bool mConnected = false; public: - PlantSettings_t* mSetting; + PlantSettings_t *mSetting; /** * @brief Construct a new Plant object * @@ -33,9 +34,9 @@ public: * @param pinPump Pin of the Pump to use */ Plant(int pinSensor, int pinPump, - int plantId, - HomieNode* plant, - PlantSettings_t* setting); + int plantId, + HomieNode *plant, + PlantSettings_t *setting); void postMQTTconnection(void); @@ -46,7 +47,7 @@ public: * */ void addSenseValue(void); - + int getSensorValue() { return moistureRaw.getMedian(); } void deactivatePump(void); @@ -59,31 +60,39 @@ public: * @return true * @return false */ - bool isPumpRequired() { + bool isPumpRequired() + { bool isDry = getCurrentMoisture() > getSettingsMoisture(); bool isActive = isPumpTriggerActive(); return isDry && isActive; } - bool isPumpTriggerActive(){ + bool isPumpTriggerActive() + { return this->mSetting->pSensorDry->get() != DEACTIVATED_PLANT; } - float getCurrentMoisture(){ + float getCurrentMoisture() + { return this->moistureRaw.getMedian(); } - long getSettingsMoisture(){ - if(this->mSetting->pSensorDry != NULL){ + long getSettingsMoisture() + { + if (this->mSetting->pSensorDry != NULL) + { return this->mSetting->pSensorDry->get(); - } else { + } + else + { return DEACTIVATED_PLANT; } } - HomieInternals::SendingPromise& setProperty(const String& property) const { + HomieInternals::SendingPromise &setProperty(const String &property) const + { return mPlant->setProperty(property); } - bool switchHandler(const HomieRange& range, const String& value); + bool switchHandler(const HomieRange &range, const String &value); void init(void); @@ -91,16 +100,19 @@ public: * @brief determine, if the plant was recently casted * @param sinceLastActivation timestamp of last time */ - bool isInCooldown(long sinceLastActivation) { + bool isInCooldown(long sinceLastActivation) + { /* if the time difference is greater than one month, we know these are initial values */ - if (sinceLastActivation > (60 * 60 * 24 * 30)) { + if (sinceLastActivation > (60 * 60 * 24 * 30)) + { return false; } return (this->mSetting->pPumpCooldownInHours->get() > sinceLastActivation / 3600); } - bool isAllowedOnlyAtLowLight(void) { + bool isAllowedOnlyAtLowLight(void) + { return this->mSetting->pPumpOnlyWhenLowLight->get(); } }; diff --git a/esp32/include/RunningMedian.h b/esp32/include/RunningMedian.h index 4ba5516..d83b389 100644 --- a/esp32/include/RunningMedian.h +++ b/esp32/include/RunningMedian.h @@ -17,13 +17,11 @@ // not tested ==> use at own risk :) // #define RUNNING_MEDIAN_USE_MALLOC - // should at least be 5 to be practical, // odd sizes results in a 'real' middle element and will be a bit faster. // even sizes takes the average of the two middle elements as median -#define MEDIAN_MIN_SIZE 5 -#define MEDIAN_MAX_SIZE 19 - +#define MEDIAN_MIN_SIZE 5 +#define MEDIAN_MAX_SIZE 19 class RunningMedian { @@ -45,7 +43,7 @@ public: float getAverage(uint8_t nMedian); float getHighest() { return getSortedElement(_cnt - 1); }; - float getLowest() { return getSortedElement(0); }; + float getLowest() { return getSortedElement(0); }; // get n'th element from the values in time order float getElement(const uint8_t n); @@ -58,7 +56,6 @@ public: // returns current used elements, getCount() <= getSize() uint8_t getCount() { return _cnt; }; - protected: boolean _sorted; uint8_t _size; @@ -66,8 +63,8 @@ protected: uint8_t _idx; #ifdef RUNNING_MEDIAN_USE_MALLOC - float * _ar; - uint8_t * _p; + float *_ar; + uint8_t *_p; #else float _ar[MEDIAN_MAX_SIZE]; uint8_t _p[MEDIAN_MAX_SIZE]; diff --git a/esp32/src/DS18B20.cpp b/esp32/src/DS18B20.cpp index 73c52cf..14d359f 100644 --- a/esp32/src/DS18B20.cpp +++ b/esp32/src/DS18B20.cpp @@ -11,40 +11,45 @@ #include "DS18B20.h" -#define STARTCONV 0x44 -#define READSCRATCH 0xBE // Read EEPROM -#define TEMP_LSB 0 -#define TEMP_MSB 1 -#define SCRATCHPADSIZE 9 -#define OFFSET_CRC8 8 /**< 9th byte has the CRC of the complete data */ +#define STARTCONV 0x44 +#define READSCRATCH 0xBE // Read EEPROM +#define TEMP_LSB 0 +#define TEMP_MSB 1 +#define SCRATCHPADSIZE 9 +#define OFFSET_CRC8 8 /**< 9th byte has the CRC of the complete data */ //Printf debugging //#define DS_DEBUG -int Ds18B20::readDevices() { +int Ds18B20::readDevices() +{ byte addr[8]; int amount = -1; - while (this->mDs->search(addr)) { + while (this->mDs->search(addr)) + { amount++; } this->mDs->reset_search(); return amount; } -int Ds18B20::readAllTemperatures(float* pTemperatures, int maxTemperatures) { +int Ds18B20::readAllTemperatures(float *pTemperatures, int maxTemperatures) +{ byte addr[8]; uint8_t scratchPad[SCRATCHPADSIZE]; int currentTemp = 0; - while (this->mDs->search(addr)) { + while (this->mDs->search(addr)) + { this->mDs->reset(); this->mDs->select(addr); this->mDs->write(STARTCONV); } delay(750); - - while (this->mDs->search(addr)) { + + while (this->mDs->search(addr)) + { this->mDs->reset(); this->mDs->select(addr); this->mDs->write(READSCRATCH); @@ -62,28 +67,32 @@ int Ds18B20::readAllTemperatures(float* pTemperatures, int maxTemperatures) { // byte 7: DS18S20: COUNT_PER_C // DS18B20 & DS1822: store for crc // byte 8: SCRATCHPAD_CRC - for (uint8_t i = 0; i < 9; i++) { + for (uint8_t i = 0; i < 9; i++) + { scratchPad[i] = this->mDs->read(); } uint8_t crc8 = this->mDs->crc8(scratchPad, 8); /* Only work an valid data */ - if (crc8 == scratchPad[OFFSET_CRC8]) { - int16_t fpTemperature = (((int16_t) scratchPad[TEMP_MSB]) << 11) - | (((int16_t) scratchPad[TEMP_LSB]) << 3); - float celsius = (float) fpTemperature * 0.0078125; + if (crc8 == scratchPad[OFFSET_CRC8]) + { + int16_t fpTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 11) | (((int16_t)scratchPad[TEMP_LSB]) << 3); + float celsius = (float)fpTemperature * 0.0078125; #ifdef DS_DEBUG - Serial.printf("\r\nTemp%d %f °C (Raw: %d, %x =? %x)\r\n", (currentTemp+1), celsius, fpTemperature, crc8, scratchPad[8]); + Serial.printf("\r\nTemp%d %f °C (Raw: %d, %x =? %x)\r\n", (currentTemp + 1), celsius, fpTemperature, crc8, scratchPad[8]); #endif /* check, if the buffer as some space for our data */ - if (currentTemp < maxTemperatures) { + if (currentTemp < maxTemperatures) + { pTemperatures[currentTemp] = celsius; - } else { + } + else + { return -1; } } currentTemp++; - } + } this->mDs->reset(); #ifdef DS_DEBUG Serial.println(" No more addresses."); diff --git a/esp32/src/PlantCtrl.cpp b/esp32/src/PlantCtrl.cpp index ec19476..0660dff 100644 --- a/esp32/src/PlantCtrl.cpp +++ b/esp32/src/PlantCtrl.cpp @@ -12,76 +12,82 @@ #include "PlantCtrl.h" -Plant::Plant(int pinSensor, int pinPump,int plantId, HomieNode* plant, PlantSettings_t* setting) { +Plant::Plant(int pinSensor, int pinPump, int plantId, HomieNode *plant, PlantSettings_t *setting) +{ this->mPinSensor = pinSensor; this->mPinPump = pinPump; this->mPlant = plant; - this->mSetting = setting; + this->mSetting = setting; } -void Plant::init(void) { +void Plant::init(void) +{ /* Initialize Home Settings validator */ this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT); - this->mSetting->pSensorDry->setValidator([] (long candidate) { - return (((candidate >= 0) && (candidate <= 4095) ) || candidate == DEACTIVATED_PLANT); + this->mSetting->pSensorDry->setValidator([](long candidate) { + return (((candidate >= 0) && (candidate <= 4095)) || candidate == DEACTIVATED_PLANT); }); this->mSetting->pPumpAllowedHourRangeStart->setDefaultValue(8); // start at 8:00 - this->mSetting->pPumpAllowedHourRangeStart->setValidator([] (long candidate) { - return ((candidate >= 0) && (candidate <= 23) ); + this->mSetting->pPumpAllowedHourRangeStart->setValidator([](long candidate) { + return ((candidate >= 0) && (candidate <= 23)); }); this->mSetting->pPumpAllowedHourRangeEnd->setDefaultValue(20); // stop pumps at 20:00 - this->mSetting->pPumpAllowedHourRangeEnd->setValidator([] (long candidate) { - return ((candidate >= 0) && (candidate <= 23) ); + this->mSetting->pPumpAllowedHourRangeEnd->setValidator([](long candidate) { + return ((candidate >= 0) && (candidate <= 23)); }); this->mSetting->pPumpOnlyWhenLowLight->setDefaultValue(true); this->mSetting->pPumpCooldownInHours->setDefaultValue(20); // minutes - this->mSetting->pPumpCooldownInHours->setValidator([] (long candidate) { - return ((candidate >= 0) && (candidate <= 1024) ); + this->mSetting->pPumpCooldownInHours->setValidator([](long candidate) { + return ((candidate >= 0) && (candidate <= 1024)); }); /* Initialize Hardware */ pinMode(this->mPinPump, OUTPUT); pinMode(this->mPinSensor, ANALOG); - digitalWrite(this->mPinPump, LOW); + digitalWrite(this->mPinPump, LOW); } -void Plant::addSenseValue(void) { - this->moistureRaw.add( analogRead(this->mPinSensor) ); +void Plant::addSenseValue(void) +{ + this->moistureRaw.add(analogRead(this->mPinSensor)); } -void Plant::postMQTTconnection(void) { +void Plant::postMQTTconnection(void) +{ const String OFF = String("OFF"); - this->mConnected=true; + this->mConnected = true; this->mPlant->setProperty("switch").send(OFF); } -void Plant::deactivatePump(void) { +void Plant::deactivatePump(void) +{ digitalWrite(this->mPinPump, LOW); - if (this->mConnected) { + if (this->mConnected) + { const String OFF = String("OFF"); this->mPlant->setProperty("switch").send(OFF); } } -void Plant::activatePump(void) { +void Plant::activatePump(void) +{ digitalWrite(this->mPinPump, HIGH); - if (this->mConnected) { + if (this->mConnected) + { const String OFF = String("ON"); this->mPlant->setProperty("switch").send(OFF); } } -void Plant::advertise(void) { +void Plant::advertise(void) +{ // Advertise topics - this->mPlant->advertise("switch").setName("Pump 1") - .setDatatype("boolean"); + this->mPlant->advertise("switch").setName("Pump 1").setDatatype("boolean"); //FIXME add .settable(this->switchHandler) - this->mPlant->advertise("moist").setName("Percent") - .setDatatype("number") - .setUnit("%"); + this->mPlant->advertise("moist").setName("Percent").setDatatype("number").setUnit("%"); + this->mPlant->advertise("moistraw").setName("adc").setDatatype("number").setUnit("3.3/4096V"); } - /* FIXME bool Plant::switchHandler(const HomieRange& range, const String& value) { if (range.isRange) return false; // only one switch is present diff --git a/esp32/src/RunningMedian.cpp b/esp32/src/RunningMedian.cpp index e18f0e8..b482d12 100644 --- a/esp32/src/RunningMedian.cpp +++ b/esp32/src/RunningMedian.cpp @@ -31,8 +31,8 @@ RunningMedian::RunningMedian(const uint8_t size) _size = constrain(size, MEDIAN_MIN_SIZE, MEDIAN_MAX_SIZE); #ifdef RUNNING_MEDIAN_USE_MALLOC - _ar = (float *) malloc(_size * sizeof(float)); - _p = (uint8_t *) malloc(_size * sizeof(uint8_t)); + _ar = (float *)malloc(_size * sizeof(float)); + _p = (uint8_t *)malloc(_size * sizeof(uint8_t)); #endif clear(); @@ -63,18 +63,22 @@ void RunningMedian::clear() void RunningMedian::add(float value) { _ar[_idx++] = value; - if (_idx >= _size) _idx = 0; // wrap around - if (_cnt < _size) _cnt++; + if (_idx >= _size) + _idx = 0; // wrap around + if (_cnt < _size) + _cnt++; _sorted = false; } float RunningMedian::getMedian() { - if (_cnt == 0) return NAN; + if (_cnt == 0) + return NAN; - if (_sorted == false) sort(); + if (_sorted == false) + sort(); - if (_cnt & 0x01) // is it odd sized? + if (_cnt & 0x01) // is it odd sized? { return _ar[_p[_cnt / 2]]; } @@ -83,7 +87,8 @@ float RunningMedian::getMedian() float RunningMedian::getAverage() { - if (_cnt == 0) return NAN; + if (_cnt == 0) + return NAN; float sum = 0; for (uint8_t i = 0; i < _cnt; i++) @@ -95,13 +100,16 @@ float RunningMedian::getAverage() float RunningMedian::getAverage(uint8_t nMedians) { - if ((_cnt == 0) || (nMedians == 0)) return NAN; + if ((_cnt == 0) || (nMedians == 0)) + return NAN; - if (_cnt < nMedians) nMedians = _cnt; // when filling the array for first time + if (_cnt < nMedians) + nMedians = _cnt; // when filling the array for first time uint8_t start = ((_cnt - nMedians) / 2); uint8_t stop = start + nMedians; - if (_sorted == false) sort(); + if (_sorted == false) + sort(); float sum = 0; for (uint8_t i = start; i < stop; i++) @@ -113,7 +121,8 @@ float RunningMedian::getAverage(uint8_t nMedians) float RunningMedian::getElement(const uint8_t n) { - if ((_cnt == 0) || (n >= _cnt)) return NAN; + if ((_cnt == 0) || (n >= _cnt)) + return NAN; uint8_t pos = _idx + n; if (pos >= _cnt) // faster than % @@ -125,18 +134,21 @@ float RunningMedian::getElement(const uint8_t n) float RunningMedian::getSortedElement(const uint8_t n) { - if ((_cnt == 0) || (n >= _cnt)) return NAN; + if ((_cnt == 0) || (n >= _cnt)) + return NAN; - if (_sorted == false) sort(); + if (_sorted == false) + sort(); return _ar[_p[n]]; } // n can be max <= half the (filled) size float RunningMedian::predict(const uint8_t n) { - if ((_cnt == 0) || (n >= _cnt / 2)) return NAN; + if ((_cnt == 0) || (n >= _cnt / 2)) + return NAN; - float med = getMedian(); // takes care of sorting ! + float med = getMedian(); // takes care of sorting ! if (_cnt & 0x01) { return max(med - _ar[_p[_cnt / 2 - n]], _ar[_p[_cnt / 2 + n]] - med); @@ -162,7 +174,8 @@ void RunningMedian::sort() flag = false; } } - if (flag) break; + if (flag) + break; } _sorted = true; } diff --git a/esp32/src/main.cpp b/esp32/src/main.cpp index 8d4b6b5..a066305 100644 --- a/esp32/src/main.cpp +++ b/esp32/src/main.cpp @@ -16,52 +16,48 @@ #include "time.h" #include "esp_sleep.h" #include "RunningMedian.h" -#include #include const unsigned long TEMPREADCYCLE = 30000; /**< Check temperature all half minutes */ -#define AMOUNT_SENOR_QUERYS 8 -#define SENSOR_QUERY_SHIFTS 3 -#define SOLAR4SENSORS 6.0f -#define TEMP_INIT_VALUE -999.0f -#define TEMP_MAX_VALUE 85.0f -#define HalfHour 60 +#define AMOUNT_SENOR_QUERYS 8 +#define SENSOR_QUERY_SHIFTS 3 +#define SOLAR4SENSORS 6.0f +#define TEMP_INIT_VALUE -999.0f +#define TEMP_MAX_VALUE 85.0f +#define HalfHour 60 /********************* 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 rtcMoistureTrigger0 = 0; /** 100) + { + pct = 100; + } + mPlants[i].setProperty("moist").send(String(pct)); + mPlants[i].setProperty("moistraw").send(String(mPlants[i].getSensorValue())); } - sensorWater.setProperty("remaining").send(String(waterLevelMax.get() - mWaterGone )); - Serial << "W : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone ) << "%)" << endl; + sensorWater.setProperty("remaining").send(String(waterLevelMax.get() - mWaterGone)); + Serial << "W : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone) << "%)" << endl; lastWaterValue = mWaterGone; - sensorLipo.setProperty("percent").send( String(100 * lipoRawSensor.getAverage() / 4095) ); - sensorLipo.setProperty("volt").send( String(getBatteryVoltage()) ); - sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage() ) / 4095)); - sensorSolar.setProperty("volt").send( String(getSolarVoltage()) ); + sensorLipo.setProperty("percent").send(String(100 * lipoRawSensor.getAverage() / 4095)); + sensorLipo.setProperty("volt").send(String(getBatteryVoltage())); + sensorSolar.setProperty("percent").send(String((100 * solarRawSensor.getAverage()) / 4095)); + sensorSolar.setProperty("volt").send(String(getSolarVoltage())); - float t1 = temp1.getMedian(); - if (t1 != NAN) { - sensorTemp.setProperty("control").send( String(t1)); + if (t1 != NAN) + { + sensorTemp.setProperty("control").send(String(t1)); } float t2 = temp2.getMedian(); - if (t2 != NAN) { - sensorTemp.setProperty("temp").send( String(t2)); + if (t2 != NAN) + { + sensorTemp.setProperty("temp").send(String(t2)); } //give mqtt time, use via publish callback instead? delay(100); - bool lipoTempWarning = t1!=85 && t2!=85 && abs(t1 - t2) > 10; - if(lipoTempWarning){ + bool lipoTempWarning = t1 != 85 && t2 != 85 && abs(t1 - t2) > 10; + if (lipoTempWarning) + { Serial.println("Lipo temp incorrect, panic mode deepsleep TODO"); //espDeepSleepFor(PANIK_MODE_DEEPSLEEP); //return; } - for(int i=0; i < MAX_PLANTS; i++) { + for (int i = 0; i < MAX_PLANTS; i++) + { setMoistureTrigger(i, mPlants[i].mSetting->pSensorDry->get()); } - - bool hasWater = true;//FIXMEmWaterGone > waterLevelMin.get(); + bool hasWater = true; //FIXMEmWaterGone > waterLevelMin.get(); //FIXME no water warning message lastPumpRunning = determineNextPump(); - if(lastPumpRunning != -1 && !hasWater){ + if (lastPumpRunning != -1 && !hasWater) + { Serial.println("Want to pump but no water"); } - if(lastPumpRunning != -1 && hasWater){ + if (lastPumpRunning != -1 && hasWater) + { digitalWrite(OUTPUT_PUMP, HIGH); setLastActivationForPump(lastPumpRunning, getCurrentTime()); mPlants[lastPumpRunning].activatePump(); } - if(lastPumpRunning == -1 || !hasWater){ - if(getSolarVoltage() < SOLAR_CHARGE_MIN_VOLTAGE){ - gotoMode2AfterThisTimestamp = getCurrentTime()+deepSleepNightTime.get(); + if (lastPumpRunning == -1 || !hasWater) + { + if (getSolarVoltage() < SOLAR_CHARGE_MIN_VOLTAGE) + { + gotoMode2AfterThisTimestamp = getCurrentTime() + deepSleepNightTime.get(); Serial.println("No pumps to activate and low light, deepSleepNight"); espDeepSleepFor(deepSleepNightTime.get()); rtcDeepSleepTime = deepSleepNightTime.get(); - }else { - gotoMode2AfterThisTimestamp = getCurrentTime()+deepSleepTime.get(); + } + else + { + gotoMode2AfterThisTimestamp = getCurrentTime() + deepSleepTime.get(); Serial.println("No pumps to activate, deepSleep"); espDeepSleepFor(deepSleepTime.get()); rtcDeepSleepTime = deepSleepTime.get(); } - - }else { + } + else + { gotoMode2AfterThisTimestamp = 0; Serial.println("Running pump, watering deepsleep"); espDeepSleepFor(wateringDeepSleep.get(), true); } - } -long getMoistureTrigger(int plantId){ - if(plantId == 0){ +long getMoistureTrigger(int plantId) +{ + if (plantId == 0) + { return rtcMoistureTrigger0; } - if(plantId == 1){ + if (plantId == 1) + { return rtcMoistureTrigger1; } - if(plantId == 2){ + if (plantId == 2) + { return rtcMoistureTrigger2; } - if(plantId == 3){ + if (plantId == 3) + { return rtcMoistureTrigger3; } - if(plantId == 4){ + if (plantId == 4) + { return rtcMoistureTrigger4; } - if(plantId == 5){ + if (plantId == 5) + { return rtcMoistureTrigger5; } - if(plantId == 6){ + if (plantId == 6) + { return rtcMoistureTrigger6; - } + } return -1; } - - -void setLastActivationForPump(int plantId, long value){ - if(plantId == 0){ +void setLastActivationForPump(int plantId, long value) +{ + if (plantId == 0) + { rtcLastActive0 = value; } - if(plantId == 1){ + if (plantId == 1) + { rtcLastActive1 = value; } - if(plantId == 2){ + if (plantId == 2) + { rtcLastActive2 = value; } - if(plantId == 3){ + if (plantId == 3) + { rtcLastActive3 = value; } - if(plantId == 4){ + if (plantId == 4) + { rtcLastActive4 = value; } - if(plantId == 5){ + if (plantId == 5) + { rtcLastActive5 = value; } - if(plantId == 6){ + if (plantId == 6) + { rtcLastActive6 = value; - } + } } -long getLastActivationForPump(int plantId){ - if(plantId == 0){ +long getLastActivationForPump(int plantId) +{ + if (plantId == 0) + { return rtcLastActive0; } - if(plantId == 1){ + if (plantId == 1) + { return rtcLastActive1; } - if(plantId == 2){ + if (plantId == 2) + { return rtcLastActive2; } - if(plantId == 3){ + if (plantId == 3) + { return rtcLastActive3; } - if(plantId == 4){ + if (plantId == 4) + { return rtcLastActive4; } - if(plantId == 5){ + if (plantId == 5) + { return rtcLastActive5; } - if(plantId == 6){ + if (plantId == 6) + { return rtcLastActive6; } return -1; @@ -341,7 +397,8 @@ long getLastActivationForPump(int plantId){ * @brief Sensors, that are connected to GPIOs, mandatory for WIFI. * These sensors (ADC2) can only be read when no Wifi is used. */ -void readSensors() { +void readSensors() +{ Serial << "Read Sensors" << endl; readSystemSensors(); @@ -352,8 +409,10 @@ void readSensors() { delay(100); /* wait before reading something */ - for (int readCnt=0;readCnt < AMOUNT_SENOR_QUERYS; readCnt++) { - for(int i=0; i < MAX_PLANTS; i++) { + for (int readCnt = 0; readCnt < AMOUNT_SENOR_QUERYS; readCnt++) + { + for (int i = 0; i < MAX_PLANTS; i++) + { mPlants[i].addSenseValue(); } } @@ -363,112 +422,123 @@ void readSensors() { Serial << "DS18B20" << String(dallas.readDevices()) << endl; delay(200); - /* Required to read the temperature once */ float temp[2] = {TEMP_MAX_VALUE, TEMP_MAX_VALUE}; - float* pFloat = temp; + float *pFloat = temp; int sensors = dallas.readAllTemperatures(pFloat, 2); - if (sensors > 0) { + if (sensors > 0) + { Serial << "t1: " << String(temp[0]) << endl; temp1.add(temp[0]); } - if (sensors > 1) { + if (sensors > 1) + { Serial << "t2: " << String(temp[1]) << endl; temp2.add(temp[1]); } - /* Use the Ultrasonic sensor to measure waterLevel */ - + digitalWrite(SENSOR_SR04_TRIG, LOW); delayMicroseconds(2); digitalWrite(SENSOR_SR04_TRIG, HIGH); delayMicroseconds(10); digitalWrite(SENSOR_SR04_TRIG, LOW); float duration = pulseIn(SENSOR_SR04_ECHO, HIGH); - waterRawSensor.add((duration*.343)/2); + waterRawSensor.add((duration * .343) / 2); /* deactivate the sensors */ digitalWrite(OUTPUT_SENSOR, LOW); } //Homie.getMqttClient().disconnect(); -void onHomieEvent(const HomieEvent& event) { - switch(event.type) { - case HomieEventType::SENDING_STATISTICS: - Homie.getLogger() << "My statistics" << endl; - break; - case HomieEventType::MQTT_READY: - Serial.printf("NTP Setup with server %s\r\n", ntpServer.get()); - configTime(0, 0, ntpServer.get()); - //wait for rtc sync? - rtcDeepSleepTime = deepSleepTime.get(); - Serial << "Setup plants" << endl; - for(int i=0; i < MAX_PLANTS; i++) { - mPlants[i].postMQTTconnection(); - } +void onHomieEvent(const HomieEvent &event) +{ + switch (event.type) + { + case HomieEventType::SENDING_STATISTICS: + Homie.getLogger() << "My statistics" << endl; + break; + case HomieEventType::MQTT_READY: + Serial.printf("NTP Setup with server %s\r\n", ntpServer.get()); + configTime(0, 0, ntpServer.get()); + //wait for rtc sync? + rtcDeepSleepTime = deepSleepTime.get(); + Serial << "Setup plants" << endl; + for (int i = 0; i < MAX_PLANTS; i++) + { + mPlants[i].postMQTTconnection(); + } - mode2MQTT(); - break; - case HomieEventType::READY_TO_SLEEP: - Homie.getLogger() << "rtsleep" << endl; - esp_deep_sleep_start(); - break; - case HomieEventType::OTA_STARTED: - Homie.getLogger() << "OTA started" << endl; - digitalWrite(OUTPUT_SENSOR, HIGH); - digitalWrite(OUTPUT_PUMP, HIGH); - gpio_hold_dis(GPIO_NUM_13); //pump pwr - gpio_deep_sleep_hold_dis(); - for (int i=0; i < MAX_PLANTS; i++) { - mPlants[i].deactivatePump(); - } - mode3Active=true; - break; - case HomieEventType::OTA_SUCCESSFUL: + mode2MQTT(); + break; + case HomieEventType::READY_TO_SLEEP: + Homie.getLogger() << "rtsleep" << endl; + esp_deep_sleep_start(); + break; + case HomieEventType::OTA_STARTED: + Homie.getLogger() << "OTA started" << endl; + digitalWrite(OUTPUT_SENSOR, HIGH); + digitalWrite(OUTPUT_PUMP, HIGH); + gpio_hold_dis(GPIO_NUM_13); //pump pwr + gpio_deep_sleep_hold_dis(); + for (int i = 0; i < MAX_PLANTS; i++) + { + mPlants[i].deactivatePump(); + } + mode3Active = true; + break; + case HomieEventType::OTA_SUCCESSFUL: Homie.getLogger() << "OTA successfull" << endl; - digitalWrite(OUTPUT_SENSOR, LOW); - digitalWrite(OUTPUT_PUMP, LOW); - ESP.restart(); - break; - default: - break; + digitalWrite(OUTPUT_SENSOR, LOW); + digitalWrite(OUTPUT_PUMP, LOW); + ESP.restart(); + break; + default: + break; } } -int determineNextPump(){ +int determineNextPump() +{ float solarValue = getSolarVoltage(); - bool isLowLight =(solarValue > SOLAR_CHARGE_MIN_VOLTAGE || 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? int pumpToUse = -1; - for(int i=0; i < MAX_PLANTS; i++) { + for (int i = 0; i < MAX_PLANTS; i++) + { Plant plant = mPlants[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 - if(plant.isInCooldown(sinceLastActivation) ){ - Serial.printf("%d Skipping due to cooldown\r\n", i); + if (plant.isInCooldown(sinceLastActivation)) + { + Serial.printf("%d Skipping due to cooldown %ld \r\n", i, sinceLastActivation); setMoistureTrigger(i, DEACTIVATED_PLANT); continue; } //skip as it is not low light - if(!isLowLight && plant.isAllowedOnlyAtLowLight()){ + if (!isLowLight && plant.isAllowedOnlyAtLowLight()) + { Serial.printf("%d No pump required: due to light\r\n", i); continue; } - if(plant.isPumpRequired()){ + if (plant.isPumpRequired()) + { Serial.printf("%d Requested pumping\r\n", i); pumpToUse = i; } - if(plant.isPumpTriggerActive()){ + else if (plant.isPumpTriggerActive()) + { Serial.printf("%d No pump required: disabled trigger %f / %ld\r\n", i, plant.getCurrentMoisture(), plant.getSettingsMoisture()); - }else { + } + else + { Serial.printf("%d No pump required: disabled trigger\r\n", i); } - } return pumpToUse; } @@ -481,38 +551,44 @@ int determineNextPump(){ * @return true when the command was parsed and executed succuessfully * @return false on errors when parsing the request */ -bool aliveHandler(const HomieRange& range, const String& value) { - if (range.isRange) return false; // only one controller is present - if (value.equals("ON") || value.equals("On") || value.equals("1")) { - mode3Active=true; - } else { - mode3Active=false; +bool aliveHandler(const HomieRange &range, const String &value) +{ + if (range.isRange) + return false; // only one controller is present + if (value.equals("ON") || value.equals("On") || value.equals("1")) + { + mode3Active = true; } - + else + { + mode3Active = false; + } + return true; } -void homieLoop(){ - +void homieLoop() +{ } -void systemInit(){ +void systemInit() +{ WiFi.mode(WIFI_STA); Homie_setFirmware("PlantControl", FIRMWARE_VERSION); // Set default values - + //in seconds deepSleepTime.setDefaultValue(60); deepSleepNightTime.setDefaultValue(600); wateringDeepSleep.setDefaultValue(5); ntpServer.setDefaultValue("pool.ntp.org"); - /* waterLevelMax 1000 */ /* 100cm in mm */ - waterLevelMin.setDefaultValue(50); /* 5cm in mm */ - waterLevelWarn.setDefaultValue(500); /* 50cm in mm */ - waterLevelVol.setDefaultValue(5000); /* 5l in ml */ + /* waterLevelMax 1000 */ /* 100cm in mm */ + waterLevelMin.setDefaultValue(50); /* 5cm in mm */ + waterLevelWarn.setDefaultValue(500); /* 50cm in mm */ + waterLevelVol.setDefaultValue(5000); /* 5l in ml */ Homie.setLoopFunction(homieLoop); Homie.onEvent(onHomieEvent); @@ -520,63 +596,70 @@ void systemInit(){ Homie.setup(); mConfigured = Homie.isConfigured(); - if (mConfigured) { - for(int i=0; i < MAX_PLANTS; i++) { + if (mConfigured) + { + for (int i = 0; i < MAX_PLANTS; i++) + { mPlants[i].advertise(); } sensorTemp.advertise("control") - .setName("Temperature") - .setDatatype("number") - .setUnit("°C"); + .setName("Temperature") + .setDatatype("number") + .setUnit("°C"); sensorTemp.advertise("temp") - .setName("Temperature") - .setDatatype("number") - .setUnit("°C"); + .setName("Temperature") + .setDatatype("number") + .setUnit("°C"); sensorLipo.advertise("percent") - .setName("Percent") - .setDatatype("number") - .setUnit("%"); + .setName("Percent") + .setDatatype("number") + .setUnit("%"); sensorLipo.advertise("volt") - .setName("Volt") - .setDatatype("number") - .setUnit("V"); + .setName("Volt") + .setDatatype("number") + .setUnit("V"); sensorSolar.advertise("percent") - .setName("Percent") - .setDatatype("number") - .setUnit("%"); + .setName("Percent") + .setDatatype("number") + .setUnit("%"); sensorSolar.advertise("volt") - .setName("Volt") - .setDatatype("number") - .setUnit("V"); + .setName("Volt") + .setDatatype("number") + .setUnit("V"); sensorWater.advertise("remaining").setDatatype("number").setUnit("%"); } stayAlive.advertise("alive").setName("Alive").setDatatype("number").settable(aliveHandler); } - -bool mode1(){ +bool mode1() +{ Serial.println("==== Mode 1 ===="); Serial << getCurrentTime() << " curtime" << endl; readSensors(); - //queue sensor values for + //queue sensor values for - if (rtcDeepSleepTime == 0){ + if (rtcDeepSleepTime == 0) + { Serial.println("1 missing rtc value, going to mode2"); return true; } - for(int i = 0; i < MAX_PLANTS; i++){ - long trigger =getMoistureTrigger(i); - if (trigger == 0) { + for (int i = 0; i < MAX_PLANTS; i++) + { + long trigger = getMoistureTrigger(i); + if (trigger == 0) + { Serial << "Missing rtc trigger " << i << endl; return true; } - if(trigger == DEACTIVATED_PLANT){ + if (trigger == DEACTIVATED_PLANT) + { continue; } - if(mPlants[i].getSensorValue() <= trigger){ + if (mPlants[i].getSensorValue() <= trigger) + { Serial << "plant dry starting mode 2" << i << endl; return true; } @@ -585,26 +668,32 @@ bool mode1(){ //check how long it was already in mode1 if to long goto mode2 long cTime = getCurrentTime(); - if(cTime < 100000){ + if (cTime < 100000) + { Serial.println("Starting mode 2 due to missing ntp"); //missing ntp time boot to mode3 return true; } - if(gotoMode2AfterThisTimestamp < cTime){ + if (gotoMode2AfterThisTimestamp < cTime) + { Serial.println("Starting mode 2 after specified mode1 time"); return true; - } else { + } + else + { Serial << "Mode2 Timer " << gotoMode2AfterThisTimestamp << " curtime " << cTime << endl; } return false; } -void mode2(){ +void mode2() +{ Serial.println("==== Mode 2 ===="); systemInit(); /* Jump into Mode 3, if not configured */ - if (!mConfigured) { + if (!mConfigured) + { Serial.println("==== Mode 3 ===="); mode3Active = true; } @@ -614,12 +703,15 @@ void mode2(){ * @brief Startup function * Is called once, the controller is started */ -void setup() { +void setup() +{ Serial.begin(115200); Serial.setTimeout(1000); // Set timeout of 1 second - Serial << endl << endl; + Serial << endl + << endl; /* Intialize Plant */ - for(int i=0; i < MAX_PLANTS; i++) { + for (int i = 0; i < MAX_PLANTS; i++) + { mPlants[i].init(); } @@ -631,11 +723,12 @@ void setup() { /* Power pins */ pinMode(OUTPUT_PUMP, OUTPUT); - + /* Disable Wifi and bluetooth */ WiFi.mode(WIFI_OFF); - if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS) { + if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS) + { //increase the config settings to 50 and the json to 3000 Serial << "Limits.hpp" << endl; } @@ -643,20 +736,24 @@ void setup() { // Big TODO use here the settings in RTC_Memory //Panik mode, the Lipo is empty, sleep a long long time: - if ((getBatteryVoltage() < MINIMUM_LIPO_VOLT) && - (getBatteryVoltage() > NO_LIPO_VOLT)) { + 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_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF); - esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL,ESP_PD_OPTION_ON); + esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF); esp_deep_sleep_start(); } - if(mode1()){ + if (mode1()) + { mode2(); - } else { + } + else + { Serial.println("nop"); espDeepSleepFor(rtcDeepSleepTime); } @@ -667,26 +764,33 @@ void setup() { * Executs the Homie base functionallity or triggers sleeping, if requested. */ long nextBlink = 0; -void loop() { - if (!mDeepsleep || mode3Active) { +void loop() +{ + if (!mDeepsleep || mode3Active) + { Homie.loop(); - } else { - Serial << "Bye" << endl; + } + else + { + Serial << "Bye" << endl; Serial.flush(); esp_deep_sleep_start(); } - if(millis() > 30000 && !mode3Active){ - Serial << (millis()/ 1000) << "not terminated watchdog putting to sleep" << endl; + if (millis() > 30000 && !mode3Active) + { + Serial << (millis() / 1000) << "not terminated watchdog putting to sleep" << endl; Serial.flush(); espDeepSleepFor(rtcDeepSleepTime); } /* Toggel Senor LED to visualize mode 3 */ - if(mode3Active){ - if (nextBlink < millis()) { + if (mode3Active) + { + if (nextBlink < millis()) + { nextBlink = millis() + 500; - digitalWrite(OUTPUT_SENSOR, ! digitalRead(OUTPUT_SENSOR)); + digitalWrite(OUTPUT_SENSOR, !digitalRead(OUTPUT_SENSOR)); } } }