Merge branch 'master' of https://github.com/0110/PlantCtrl into master
This commit is contained in:
commit
8043263772
@ -12,7 +12,8 @@
|
|||||||
"istream": "cpp",
|
"istream": "cpp",
|
||||||
"limits": "cpp",
|
"limits": "cpp",
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"functional": "cpp"
|
"functional": "cpp",
|
||||||
|
"string": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,58 @@
|
|||||||
# PlantControl
|
# PlantControl
|
||||||
## Hardware
|
## Hardware
|
||||||
|
|
||||||
Uses ESP32MniniKit
|
Uses ESP32MiniKit
|
||||||
|
|
||||||
### Used Pins:
|
### Used Pins:
|
||||||
* IO27 for DS18B20 temperature sensor
|
* See '''include/ControllerConfiguration.h'''
|
||||||
|
|
||||||
## Software
|
## Software
|
||||||
* Mqtt topics
|
* MQTT topics
|
||||||
* temperature
|
|
||||||
* switch1
|
# Hardware
|
||||||
* Settings:
|
## Features
|
||||||
* ds18b20 - Enables Temperature measurement
|
* Support for up to
|
||||||
* deepsleep - Setup intervall how long the controller sleeps
|
* 7 Moister sensors
|
||||||
|
* 7 Pumps
|
||||||
|
* Sensors
|
||||||
|
* Solar powered (voltage)
|
||||||
|
* Lipo-Powered (voltage)
|
||||||
|
* Temperature
|
||||||
|
* Custom GPIO
|
||||||
|
|
||||||
|
# Features
|
||||||
|
## Empires Wunschliste
|
||||||
|
* Pflanze
|
||||||
|
* Pumpe
|
||||||
|
* Zeitspann (wann laufen darf)
|
||||||
|
* Helligkeitstrigger (Um den Morgen zum pumpen zu erkennen)
|
||||||
|
* Maximal Dauer zum Pumpen (als Zeit oder Milliliter)
|
||||||
|
* Zeitspanne zwischen zwei Pumpvorgängen
|
||||||
|
* Moister sensor
|
||||||
|
* Oberen
|
||||||
|
* Unteren Wert
|
||||||
|
* Tank
|
||||||
|
* Füllstand Anzeige (in Liter)
|
||||||
|
* Minimum Wasserstand (in cm damit Pumpen nicht leer laufen; enspricht 0 nutzbaren Liter)
|
||||||
|
* Trigger-Erinnerungen um Wasser nachzufüllen
|
||||||
|
* Maximaler Wasserstand des Tanks (in cm & Liter)
|
||||||
|
* System
|
||||||
|
* Tiefentladungsschutz vom LIPO (fest im Controller die Spannung festlegen)
|
||||||
|
* 3.5V unterschritten, dann nur noch Deepsleep
|
||||||
|
* MQTT Topic, wenn Spannung unterschritten wurde
|
||||||
|
* Lipo innerhalb 24h nicht geladen -> MQTT Topic
|
||||||
|
* Deep-Sleep
|
||||||
|
* Mode1:
|
||||||
|
* Nur Sensor werte einsameln
|
||||||
|
* Wird verlassen bei Aktionen
|
||||||
|
* Pumpe schalten
|
||||||
|
* MQTT Nachrichten
|
||||||
|
* nach x Minuten nur in Mode1
|
||||||
|
* Mode2:
|
||||||
|
* WLAN aktivieren und Werte über MQTT raus hauen
|
||||||
|
* aktuelle Werte raushauen
|
||||||
|
* MQTT lesen
|
||||||
|
* Mode3:
|
||||||
|
* Deepsleep verboten (MQTT topic, retained)
|
||||||
|
* alle Pumpen & Sensoren deaktiviert
|
||||||
|
|
||||||
|
9
esp32/data/homie/Readme.md
Normal file
9
esp32/data/homie/Readme.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Filesystem
|
||||||
|
## Configuration
|
||||||
|
Use the config-example.json from the host folder and create here a config.json file.
|
||||||
|
## HowTo upload
|
||||||
|
Start Platform.io
|
||||||
|
Open a new Atom-Terminal and generate the filesystem with the following command :
|
||||||
|
```pio run -t buildfs```
|
||||||
|
Upload this new generated filesystem with:
|
||||||
|
```pio run -t uploadfs```
|
@ -18,19 +18,32 @@
|
|||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"deepsleep": 60000,
|
"deepsleep" : 60000,
|
||||||
|
"nightsleep" : 60000,
|
||||||
"pumpdeepsleep": 1000,
|
"pumpdeepsleep": 1000,
|
||||||
"watermaxlevel": 50,
|
"watermaxlevel": 50,
|
||||||
"watermin" : 5,
|
"watermin" : 5,
|
||||||
"plants" : 3,
|
"plants" : 3,
|
||||||
|
"moist0" : 2000,
|
||||||
"moist1" : 2000,
|
"moist1" : 2000,
|
||||||
"moist2" : 2000,
|
"moist2" : 2000,
|
||||||
"moist3" : 2000,
|
"moist3" : 2000,
|
||||||
|
"moist4" : 2000,
|
||||||
|
"moist5" : 2000,
|
||||||
|
"moist6" : 2000,
|
||||||
|
"plant0MaxPumpTime": 1000,
|
||||||
"plant1MaxPumpTime": 1000,
|
"plant1MaxPumpTime": 1000,
|
||||||
"plant2MaxPumpTime": 1000,
|
"plant2MaxPumpTime": 1000,
|
||||||
"plant3MaxPumpTime": 1000,
|
"plant3MaxPumpTime": 1000,
|
||||||
|
"plant4MaxPumpTime": 1000,
|
||||||
|
"plant5MaxPumpTime": 1000,
|
||||||
|
"plant6MaxPumpTime": 1000,
|
||||||
|
"plant0MinPumpIdle": 10000,
|
||||||
"plant1MinPumpIdle": 10000,
|
"plant1MinPumpIdle": 10000,
|
||||||
"plant2MinPumpIdle": 10000,
|
"plant2MinPumpIdle": 10000,
|
||||||
"plant3MinPumpIdle": 10000
|
"plant3MinPumpIdle": 10000,
|
||||||
|
"plant4MinPumpIdle": 10000,
|
||||||
|
"plant5MinPumpIdle": 10000,
|
||||||
|
"plant6MinPumpIdle": 10000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#ifndef CONTROLLER_CONFIG_H
|
#ifndef CONTROLLER_CONFIG_H
|
||||||
#define CONTROLLER_CONFIG_H
|
#define CONTROLLER_CONFIG_H
|
||||||
|
|
||||||
#define FIRMWARE_VERSION "1.0.1"
|
#define FIRMWARE_VERSION "1.0.2"
|
||||||
|
|
||||||
#define ADC_TO_VOLT(adc) ((adc) * 3.3 ) / 4095)
|
#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)
|
||||||
@ -47,7 +47,8 @@
|
|||||||
#define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */
|
#define MIN_TIME_RUNNING 5UL /**< Amount of seconds the controller must stay awoken */
|
||||||
#define MAX_PLANTS 7
|
#define MAX_PLANTS 7
|
||||||
#define EMPTY_LIPO_MULTIPL 3 /**< Multiplier to increase time for sleeping when lipo is empty */
|
#define EMPTY_LIPO_MULTIPL 3 /**< Multiplier to increase time for sleeping when lipo is empty */
|
||||||
#define MINIMUM_LIPO_VOLT 3.3f /**< Minimum voltage of the Lipo, that must be present */
|
#define MINIMUM_LIPO_VOLT 3.6f /**< Minimum voltage of the Lipo, that must be present */
|
||||||
|
#define NO_LIPO_VOLT 2.0f /**< No Lipo connected */
|
||||||
#define MINIMUM_SOLAR_VOLT 4.0f /**< Minimum voltage of the sun, to detect daylight */
|
#define MINIMUM_SOLAR_VOLT 4.0f /**< Minimum voltage of the sun, to detect daylight */
|
||||||
|
|
||||||
#define HC_SR04 /**< Ultrasonic distance sensor to measure water level */
|
#define HC_SR04 /**< Ultrasonic distance sensor to measure water level */
|
||||||
|
@ -25,9 +25,12 @@ private:
|
|||||||
|
|
||||||
int mAnalogValue=0; /**< moist sensor values, used for a calculation */
|
int mAnalogValue=0; /**< moist sensor values, used for a calculation */
|
||||||
HomieNode *mPlant = NULL;
|
HomieNode *mPlant = NULL;
|
||||||
HomieSetting<long> *mSensorTriggerLevel=NULL;
|
HomieSetting<long> *mSensorDry;
|
||||||
HomieSetting<long> *mWateringTime=NULL;
|
HomieSetting<long> *mSensorWet;
|
||||||
HomieSetting<long> *mWateringIdleTime=NULL;
|
HomieSetting<long> *mPumpAllowedHourRangeStart;
|
||||||
|
HomieSetting<long> *mPumpAllowedHourRangeEnd;
|
||||||
|
HomieSetting<bool> *mPumpOnlyWhenLowLight;
|
||||||
|
HomieSetting<long> *mPumpCooldownInHours;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -38,10 +41,7 @@ public:
|
|||||||
* @param pinPump Pin of the Pump to use
|
* @param pinPump Pin of the Pump to use
|
||||||
*/
|
*/
|
||||||
Plant(int pinSensor, int pinPump,
|
Plant(int pinSensor, int pinPump,
|
||||||
HomieNode *plant,
|
int plantId);
|
||||||
HomieSetting<long> *sensorTriggerLevel,
|
|
||||||
HomieSetting<long> *wateringTime,
|
|
||||||
HomieSetting<long> *wateringIdleTime);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a value, to be measured
|
* @brief Add a value, to be measured
|
||||||
@ -81,7 +81,7 @@ public:
|
|||||||
* @return false
|
* @return false
|
||||||
*/
|
*/
|
||||||
bool isPumpRequired() {
|
bool isPumpRequired() {
|
||||||
return (this->mSensorTriggerLevel != NULL) && (this->mValue < this->mSensorTriggerLevel->get());
|
return (this->mSensorWet != NULL) && (this->mValue < this->mSensorWet->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
HomieInternals::SendingPromise& setProperty(const String& property) const {
|
HomieInternals::SendingPromise& setProperty(const String& property) const {
|
||||||
|
@ -12,17 +12,65 @@
|
|||||||
|
|
||||||
#include "PlantCtrl.h"
|
#include "PlantCtrl.h"
|
||||||
|
|
||||||
Plant::Plant(int pinSensor, int pinPump,
|
Plant::Plant(int pinSensor, int pinPump,int plantId) {
|
||||||
HomieNode *plant,
|
this->mPinSensor = pinSensor;
|
||||||
HomieSetting<long> *sensorTriggerLevel,
|
this->mPinPump = pinPump;
|
||||||
HomieSetting<long> *wateringTime,
|
|
||||||
HomieSetting<long> *wateringIdleTime) {
|
char plantIdChar = plantId+'0';
|
||||||
this->mPlant=plant;
|
|
||||||
this->mPinSensor = pinSensor;
|
/*
|
||||||
this->mPinPump = pinPump;
|
{
|
||||||
this->mSensorTriggerLevel=sensorTriggerLevel;
|
char* name = "moistZdry";
|
||||||
this->mWateringTime=wateringTime;
|
name[5]= plantIdChar;
|
||||||
this->mWateringIdleTime=wateringIdleTime;
|
mSensorDry = new HomieSetting<long>(name, "Moist sensor dry threshold");
|
||||||
|
mSensorDry->setDefaultValue(4095);
|
||||||
|
mSensorDry->setValidator([] (long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 4095) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* name = "moistZwet";
|
||||||
|
name[6]= plantIdChar;
|
||||||
|
mSensorWet = new HomieSetting<long>(name, "Moist sensor wet threshold");
|
||||||
|
mSensorWet->setDefaultValue(0);
|
||||||
|
mSensorWet->setValidator([] (long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 4095) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* name = "rangeZhourstart";
|
||||||
|
name[6]= plantIdChar;
|
||||||
|
mPumpAllowedHourRangeStart = new HomieSetting<long>(name, "Range pump allowed hour start");
|
||||||
|
mPumpAllowedHourRangeStart->setDefaultValue(8);
|
||||||
|
mPumpAllowedHourRangeStart->setValidator([] (long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 23) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* name = "rangeZhourend";
|
||||||
|
name[6]= plantIdChar;
|
||||||
|
mPumpAllowedHourRangeEnd = new HomieSetting<long>(name, "Range pump allowed hour end");
|
||||||
|
mPumpAllowedHourRangeEnd->setDefaultValue(20);
|
||||||
|
mPumpAllowedHourRangeEnd->setValidator([] (long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 23) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* name = "onlyWhenLowLightZ";
|
||||||
|
name[16]= plantIdChar;
|
||||||
|
mPumpOnlyWhenLowLight = new HomieSetting<bool>(name, "Enable the Pump only, when there is light but not enought to charge battery");
|
||||||
|
mPumpOnlyWhenLowLight->setDefaultValue(true);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* name = "cooldownpumpZ";
|
||||||
|
name[12]= plantIdChar;
|
||||||
|
mPumpCooldownInHours = new HomieSetting<long>(name, "How long to wait until the pump is activated again");
|
||||||
|
mPumpCooldownInHours->setDefaultValue(20);
|
||||||
|
mPumpCooldownInHours->setValidator([] (long candidate) {
|
||||||
|
return ((candidate >= 0) && (candidate <= 1024) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plant::addSenseValue(int analog) {
|
void Plant::addSenseValue(int analog) {
|
||||||
|
@ -25,6 +25,7 @@ const unsigned long TEMPREADCYCLE = 30000; /**< Check temperature all half minut
|
|||||||
|
|
||||||
bool mLoopInited = false;
|
bool mLoopInited = false;
|
||||||
bool mDeepSleep = false;
|
bool mDeepSleep = false;
|
||||||
|
bool mAlive=false; /**< Controller must not sleep */
|
||||||
|
|
||||||
int plantSensor1 = 0;
|
int plantSensor1 = 0;
|
||||||
|
|
||||||
@ -67,62 +68,27 @@ HomieNode sensorLipo("lipo", "Battery Status", "Lipo");
|
|||||||
HomieNode sensorSolar("solar", "Solar Status", "Solarpanel");
|
HomieNode sensorSolar("solar", "Solar Status", "Solarpanel");
|
||||||
HomieNode sensorWater("water", "WaterSensor", "Water");
|
HomieNode sensorWater("water", "WaterSensor", "Water");
|
||||||
HomieNode sensorTemp("temperature", "Temperature", "temperature");
|
HomieNode sensorTemp("temperature", "Temperature", "temperature");
|
||||||
|
HomieNode stayAlive("stay", "alive", "alive");
|
||||||
|
|
||||||
HomieSetting<long> deepSleepTime("deepsleep", "time in milliseconds to sleep (0 deactivats it)");
|
HomieSetting<long> deepSleepTime("deepsleep", "time in milliseconds to sleep (0 deactivats it)");
|
||||||
HomieSetting<long> deepSleepNightTime("nightsleep", "time in milliseconds to sleep (0 usese same setting: deepsleep at night, too)");
|
HomieSetting<long> deepSleepNightTime("nightsleep", "time in milliseconds to sleep (0 usese same setting: deepsleep at night, too)");
|
||||||
HomieSetting<long> wateringDeepSleep("pumpdeepsleep", "time seconds to sleep, while a pump is running");
|
HomieSetting<long> wateringDeepSleep("pumpdeepsleep", "time seconds to sleep, while a pump is running");
|
||||||
HomieSetting<long> plantCnt("plants", "amout of plants to control (1 ... 7)");
|
|
||||||
|
|
||||||
#ifdef HC_SR04
|
HomieSetting<long> waterLevelMax("watermaxlevel", "distance at maximum water level");
|
||||||
HomieSetting<long> waterLevel("watermaxlevel", "Water maximum level in centimeter (50 cm default)");
|
HomieSetting<long> waterLevelMin("waterminlevel", "distance at minimum water level (pumps still covered)");
|
||||||
HomieSetting<long> waterMinPercent("watermin", "Minimum percentage of water, to activate the pumps (default 5%)");
|
HomieSetting<long> waterLevelWarn("waterlevelwarn", "warn if below this water level %");
|
||||||
#endif
|
HomieSetting<long> waterLevelVol("waterVolume", "ml between minimum and maximum");
|
||||||
HomieSetting<long> plant0SensorTrigger("moist0", "Moist0 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant1SensorTrigger("moist1", "Moist1 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant2SensorTrigger("moist2", "Moist2 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant3SensorTrigger("moist3", "Moist3 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant4SensorTrigger("moist4", "Moist4 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant5SensorTrigger("moist5", "Moist5 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> plant6SensorTrigger("moist6", "Moist6 sensor value, when pump activates");
|
|
||||||
HomieSetting<long> wateringTime0("plant0MaxPumpTime", "time seconds Pump0 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime1("plant1MaxPumpTime", "time seconds Pump1 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime2("plant2MaxPumpTime", "time seconds Pump2 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime3("plant3MaxPumpTime", "time seconds Pump3 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime4("plant4MaxPumpTime", "time seconds Pump4 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime5("plant5MaxPumpTime", "time seconds Pump5 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringTime6("plant6MaxPumpTime", "time seconds Pump6 is running (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime0("plant0MinPumpIdle", "time in seconds Pump0 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime1("plant1MinPumpIdle", "time in seconds Pump1 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime2("plant2MinPumpIdle", "time in seconds Pump2 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime3("plant3MinPumpIdle", "time in seconds Pump3 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime4("plant4MinPumpIdle", "time in seconds Pump4 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime5("plant5MinPumpIdle", "time in seconds Pump5 will wait (60 is the default)");
|
|
||||||
HomieSetting<long> wateringIdleTime6("plant6MinPumpIdle", "time in seconds Pump6 will wait (60 is the default)");
|
|
||||||
|
|
||||||
Ds18B20 dallas(SENSOR_DS18B20);
|
Ds18B20 dallas(SENSOR_DS18B20);
|
||||||
|
|
||||||
Plant mPlants[MAX_PLANTS] = {
|
Plant mPlants[MAX_PLANTS] = {
|
||||||
#if (MAX_PLANTS >= 1)
|
Plant(SENSOR_PLANT0, OUTPUT_PUMP0, 0),
|
||||||
Plant(SENSOR_PLANT0, OUTPUT_PUMP0, &plant0, &plant0SensorTrigger, &wateringTime0, &wateringIdleTime0),
|
Plant(SENSOR_PLANT1, OUTPUT_PUMP1, 1),
|
||||||
#endif
|
Plant(SENSOR_PLANT2, OUTPUT_PUMP2, 2),
|
||||||
#if (MAX_PLANTS >= 2)
|
Plant(SENSOR_PLANT3, OUTPUT_PUMP3, 3),
|
||||||
Plant(SENSOR_PLANT1, OUTPUT_PUMP1, &plant1, &plant1SensorTrigger, &wateringTime1, &wateringIdleTime1),
|
Plant(SENSOR_PLANT4, OUTPUT_PUMP4, 4),
|
||||||
#endif
|
Plant(SENSOR_PLANT5, OUTPUT_PUMP5, 5),
|
||||||
#if (MAX_PLANTS >= 3)
|
Plant(SENSOR_PLANT6, OUTPUT_PUMP6, 6)
|
||||||
Plant(SENSOR_PLANT2, OUTPUT_PUMP2, &plant2, &plant2SensorTrigger, &wateringTime2, &wateringIdleTime2),
|
|
||||||
#endif
|
|
||||||
#if (MAX_PLANTS >= 4)
|
|
||||||
Plant(SENSOR_PLANT3, OUTPUT_PUMP3, &plant3, &plant3SensorTrigger, &wateringTime3, &wateringIdleTime3),
|
|
||||||
#endif
|
|
||||||
#if (MAX_PLANTS >= 5)
|
|
||||||
Plant(SENSOR_PLANT4, OUTPUT_PUMP4, &plant4, &plant4SensorTrigger, &wateringTime4, &wateringIdleTime4),
|
|
||||||
#endif
|
|
||||||
#if (MAX_PLANTS >= 6)
|
|
||||||
Plant(SENSOR_PLANT5, OUTPUT_PUMP5, &plant5, &plant5SensorTrigger, &wateringTime5, &wateringIdleTime5),
|
|
||||||
#endif
|
|
||||||
#if (MAX_PLANTS >= 7)
|
|
||||||
Plant(SENSOR_PLANT6, OUTPUT_PUMP6, &plant6, &plant6SensorTrigger, &wateringTime6, &wateringIdleTime6)
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void readAnalogValues() {
|
void readAnalogValues() {
|
||||||
@ -146,8 +112,6 @@ void readAnalogValues() {
|
|||||||
*/
|
*/
|
||||||
void loopHandler() {
|
void loopHandler() {
|
||||||
|
|
||||||
int waterLevelPercent = (100 * mWaterGone) / waterLevel.get();
|
|
||||||
|
|
||||||
/* Move from Setup to this position, because the Settings are only here available */
|
/* Move from Setup to this position, because the Settings are only here available */
|
||||||
if (!mLoopInited) {
|
if (!mLoopInited) {
|
||||||
// Configure Deep Sleep:
|
// Configure Deep Sleep:
|
||||||
@ -168,7 +132,7 @@ void loopHandler() {
|
|||||||
plant6.setProperty("switch").send(String("OFF"));
|
plant6.setProperty("switch").send(String("OFF"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(int i=0; i < plantCnt.get() && i < MAX_PLANTS; i++) {
|
for(int i=0; i < MAX_PLANTS; i++) {
|
||||||
mPlants[i].calculateSensorValue(AMOUNT_SENOR_QUERYS);
|
mPlants[i].calculateSensorValue(AMOUNT_SENOR_QUERYS);
|
||||||
mPlants[i].setProperty("moist").send(String(100 * mPlants[i].getSensorValue() / 4095 ));
|
mPlants[i].setProperty("moist").send(String(100 * mPlants[i].getSensorValue() / 4095 ));
|
||||||
/* the last Plant, that was watered is stored in non volatile memory */
|
/* the last Plant, that was watered is stored in non volatile memory */
|
||||||
@ -182,14 +146,14 @@ void loopHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sensorWater.setProperty("remaining").send(String(waterLevelPercent));
|
sensorWater.setProperty("remaining").send(String(waterLevelMax.get() - mWaterGone ));
|
||||||
Serial << "Water : " << mWaterGone << " cm (" << waterLevelPercent << "%)" << endl;
|
Serial << "Water : " << mWaterGone << " cm (" << String(waterLevelMax.get() - mWaterGone ) << "%)" << endl;
|
||||||
|
|
||||||
/* Check if a plant needs water */
|
/* Check if a plant needs water */
|
||||||
if (gCurrentPlant > 0) {
|
if (gCurrentPlant > 0) {
|
||||||
int plntIdx = (gCurrentPlant-1);
|
int plntIdx = (gCurrentPlant-1);
|
||||||
if (mPlants[plntIdx].isPumpRequired() &&
|
if (mPlants[plntIdx].isPumpRequired() &&
|
||||||
(waterLevelPercent > waterMinPercent.get()) &&
|
(mWaterGone > waterLevelMin.get()) &&
|
||||||
(digitalRead(mPlants[plntIdx].getPumpPin()) == LOW) ) {
|
(digitalRead(mPlants[plntIdx].getPumpPin()) == LOW) ) {
|
||||||
Serial << "Plant" << plntIdx << " needs water" << endl;
|
Serial << "Plant" << plntIdx << " needs water" << endl;
|
||||||
mPlants[plntIdx].setProperty("switch").send(String("ON"));
|
mPlants[plntIdx].setProperty("switch").send(String("ON"));
|
||||||
@ -226,10 +190,10 @@ void loopHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Main Loop functionality */
|
/* Main Loop functionality */
|
||||||
if (waterLevelPercent <= waterMinPercent.get()) {
|
if (mWaterGone <= waterLevelMin.get()) {
|
||||||
/* let the ESP sleep qickly, as nothing must be done */
|
/* let the ESP sleep qickly, as nothing must be done */
|
||||||
if ((millis() >= (MIN_TIME_RUNNING * MS_TO_S)) && (deepSleepTime.get() > 0)) {
|
if ((millis() >= (MIN_TIME_RUNNING * MS_TO_S)) && (deepSleepTime.get() > 0)) {
|
||||||
mDeepSleep = true;
|
mDeepSleep = true;
|
||||||
Serial << "No Water for pumps" << endl;
|
Serial << "No Water for pumps" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +202,6 @@ void loopHandler() {
|
|||||||
/* Pump is running, go to sleep after defined time */
|
/* Pump is running, go to sleep after defined time */
|
||||||
if (millis() >= ((MIN_TIME_RUNNING + 5) &&
|
if (millis() >= ((MIN_TIME_RUNNING + 5) &&
|
||||||
(deepSleepTime.get() > 0))) {
|
(deepSleepTime.get() > 0))) {
|
||||||
Serial << "No sleeping activated (maximum)" << endl;
|
|
||||||
mDeepSleep = true;
|
mDeepSleep = true;
|
||||||
} else if ((millis() >= ((MIN_TIME_RUNNING * MS_TO_S) + 0)) &&
|
} else if ((millis() >= ((MIN_TIME_RUNNING * MS_TO_S) + 0)) &&
|
||||||
(deepSleepTime.get() > 0)) {
|
(deepSleepTime.get() > 0)) {
|
||||||
@ -285,6 +248,26 @@ bool switchGeneralPumpHandler(const int pump, const HomieRange& range, const Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle Mqtt commands to keep controller alive
|
||||||
|
*
|
||||||
|
* @param range multiple transmitted values (not used for this function)
|
||||||
|
* @param value single value
|
||||||
|
* @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")) {
|
||||||
|
mAlive=true;
|
||||||
|
} else {
|
||||||
|
mAlive=false;
|
||||||
|
}
|
||||||
|
Serial << "HOMIE | Controller " << (mAlive ? " has coffee" : " is tired") << endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle Mqtt commands for the pumpe, responsible for the first plant
|
* @brief Handle Mqtt commands for the pumpe, responsible for the first plant
|
||||||
*
|
*
|
||||||
@ -380,44 +363,21 @@ void setup() {
|
|||||||
/* activate Wifi again */
|
/* activate Wifi again */
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
|
||||||
|
|
||||||
if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS) {
|
if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS) {
|
||||||
Serial << "HOMIE | Settings: " << HomieInternals::MAX_CONFIG_SETTING_SIZE << "/" << MAX_CONFIG_SETTING_ITEMS << endl;
|
Serial << "HOMIE | Settings: " << HomieInternals::MAX_CONFIG_SETTING_SIZE << "/" << MAX_CONFIG_SETTING_ITEMS << endl;
|
||||||
Serial << " | Update Limits.hpp : MAX_CONFIG_SETTING_SIZE to " << MAX_CONFIG_SETTING_ITEMS << endl;
|
Serial << " | Update Limits.hpp : MAX_CONFIG_SETTING_SIZE to " << MAX_CONFIG_SETTING_ITEMS << endl;
|
||||||
|
Serial << " | Update Limits.hpp : MAX_JSON_CONFIG_FILE_SIZE to 3000" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Homie_setFirmware("PlantControl", FIRMWARE_VERSION);
|
Homie_setFirmware("PlantControl", FIRMWARE_VERSION);
|
||||||
Homie.setLoopFunction(loopHandler);
|
Homie.setLoopFunction(loopHandler);
|
||||||
|
|
||||||
mConfigured = Homie.isConfigured();
|
mConfigured = Homie.isConfigured();
|
||||||
if (mConfigured) {
|
|
||||||
// Load the settings
|
// Load the settings
|
||||||
deepSleepTime.setDefaultValue(0);
|
deepSleepTime.setDefaultValue(0);
|
||||||
deepSleepNightTime.setDefaultValue(0);
|
deepSleepNightTime.setDefaultValue(0);
|
||||||
wateringTime0.setDefaultValue(60);
|
|
||||||
wateringTime1.setDefaultValue(60);
|
|
||||||
wateringTime2.setDefaultValue(60);
|
|
||||||
wateringTime3.setDefaultValue(60);
|
|
||||||
wateringTime4.setDefaultValue(60);
|
|
||||||
wateringTime5.setDefaultValue(60);
|
|
||||||
wateringTime6.setDefaultValue(60);
|
|
||||||
plantCnt.setDefaultValue(0).setValidator([] (long candidate) {
|
|
||||||
return ((candidate >= 0) && (candidate <= 6) );
|
|
||||||
});
|
|
||||||
plant1SensorTrigger.setDefaultValue(0);
|
|
||||||
plant2SensorTrigger.setDefaultValue(0);
|
|
||||||
plant3SensorTrigger.setDefaultValue(0);
|
|
||||||
#if (MAX_PLANTS >= 4)
|
|
||||||
plant4SensorTrigger.setDefaultValue(0);
|
|
||||||
plant5SensorTrigger.setDefaultValue(0);
|
|
||||||
plant6SensorTrigger.setDefaultValue(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HC_SR04
|
|
||||||
waterLevel.setDefaultValue(50);
|
|
||||||
waterMinPercent.setDefaultValue(5);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
if (mConfigured) {
|
||||||
// Advertise topics
|
// Advertise topics
|
||||||
plant1.advertise("switch").setName("Pump 1")
|
plant1.advertise("switch").setName("Pump 1")
|
||||||
.setDatatype("boolean")
|
.setDatatype("boolean")
|
||||||
@ -479,12 +439,15 @@ void setup() {
|
|||||||
.setDatatype("number")
|
.setDatatype("number")
|
||||||
.setUnit("V");
|
.setUnit("V");
|
||||||
sensorWater.advertise("remaining").setDatatype("number").setUnit("%");
|
sensorWater.advertise("remaining").setDatatype("number").setUnit("%");
|
||||||
|
|
||||||
|
// Mode 3
|
||||||
|
stayAlive.advertise("alive").setName("Alive").setDatatype("number").settable(aliveHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
Homie.setup();
|
Homie.setup();
|
||||||
|
|
||||||
/* Intialize inputs and outputs */
|
/* Intialize inputs and outputs */
|
||||||
for(int i=0; i < plantCnt.get(); i++) {
|
for(int i=0; i < MAX_PLANTS; i++) {
|
||||||
pinMode(mPlants[i].getPumpPin(), OUTPUT);
|
pinMode(mPlants[i].getPumpPin(), OUTPUT);
|
||||||
pinMode(mPlants[i].getSensorPin(), ANALOG);
|
pinMode(mPlants[i].getSensorPin(), ANALOG);
|
||||||
digitalWrite(mPlants[i].getPumpPin(), LOW);
|
digitalWrite(mPlants[i].getPumpPin(), LOW);
|
||||||
@ -510,7 +473,10 @@ void setup() {
|
|||||||
esp_sleep_enable_timer_wakeup(usSleepTime);
|
esp_sleep_enable_timer_wakeup(usSleepTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mConfigured && (ADC_5V_TO_3V3(lipoSenor) < MINIMUM_LIPO_VOLT) && (deepSleepTime.get()) ) {
|
if (mConfigured &&
|
||||||
|
(ADC_5V_TO_3V3(lipoSenor) < MINIMUM_LIPO_VOLT) &&
|
||||||
|
(ADC_5V_TO_3V3(lipoSenor) > NO_LIPO_VOLT) &&
|
||||||
|
(deepSleepTime.get()) ) {
|
||||||
long sleepEmptyLipo = (deepSleepTime.get() * EMPTY_LIPO_MULTIPL);
|
long sleepEmptyLipo = (deepSleepTime.get() * EMPTY_LIPO_MULTIPL);
|
||||||
Serial << "HOMIE | Change sleeping to " << sleepEmptyLipo << " ms as lipo is at " << ADC_5V_TO_3V3(lipoSenor) << "V" << endl;
|
Serial << "HOMIE | Change sleeping to " << sleepEmptyLipo << " ms as lipo is at " << ADC_5V_TO_3V3(lipoSenor) << "V" << endl;
|
||||||
esp_sleep_enable_timer_wakeup(sleepEmptyLipo * 1000U);
|
esp_sleep_enable_timer_wakeup(sleepEmptyLipo * 1000U);
|
||||||
@ -645,8 +611,17 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Serial << (millis()/ 1000) << "s running; sleeeping ..." << endl;
|
if (!mAlive) {
|
||||||
Serial.flush();
|
Serial << (millis()/ 1000) << "s running; sleeeping ..." << endl;
|
||||||
esp_deep_sleep_start();
|
Serial.flush();
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
} else {
|
||||||
|
mDeepSleep = false;
|
||||||
|
|
||||||
|
if (((millis()) % 10000) == 0) {
|
||||||
|
/* tell everybody how long we are awoken */
|
||||||
|
stayAlive.setProperty("alive").send( String(millis()/ 1000) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,5 @@
|
|||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32doit-devkit-v1
|
board = esp32doit-devkit-v1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
build_flags = -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
build_flags = -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||||
|
lib_deps = OneWire
|
||||||
|
@ -1,12 +1,43 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
|
#include <DS18B20.h>
|
||||||
|
|
||||||
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
|
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
|
||||||
#define TIME_TO_SLEEP 2 /* Time ESP32 will go to sleep (in seconds) */
|
#define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */
|
||||||
|
|
||||||
|
#define SENSOR_LIPO 34 /**< GPIO 34 (ADC1) */
|
||||||
|
#define SENSOR_SOLAR 35 /**< GPIO 35 (ADC1) */
|
||||||
|
|
||||||
|
#define SENSOR_DS18B20 2 /**< GPIO 2 */
|
||||||
|
|
||||||
|
|
||||||
|
#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 SENSOR_PLANT0 32 /**< GPIO 32 (ADC1) */
|
||||||
|
|
||||||
|
|
||||||
|
#define ADC_TO_VOLT(adc) ((adc) * 3.3 ) / 4095)
|
||||||
|
#define ADC_TO_VOLT_WITH_MULTI(adc, multi) (((adc) * 3.3 * (multi)) / 4095)
|
||||||
|
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
RTC_DATA_ATTR int bootCount = 0;
|
RTC_DATA_ATTR int bootCount = 0;
|
||||||
|
RTC_DATA_ATTR int pumpActive = 0;
|
||||||
int secondBootCount = 0;
|
int secondBootCount = 0;
|
||||||
|
|
||||||
|
Ds18B20 ds(SENSOR_DS18B20);
|
||||||
|
|
||||||
void print_wakeup_reason(){
|
void print_wakeup_reason(){
|
||||||
esp_sleep_wakeup_cause_t wakeup_reason;
|
esp_sleep_wakeup_cause_t wakeup_reason;
|
||||||
|
|
||||||
@ -22,25 +53,36 @@ void print_wakeup_reason(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAll2Off() {
|
||||||
|
digitalWrite(OUTPUT_PUMP0, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP1, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP2, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP3, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP4, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP5, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP6, LOW);
|
||||||
|
digitalWrite(OUTPUT_SENSOR, LOW);
|
||||||
|
digitalWrite(OUTPUT_PUMP, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
pinMode(GPIO_NUM_23, OUTPUT);
|
|
||||||
pinMode(GPIO_NUM_22, OUTPUT);
|
pinMode(OUTPUT_PUMP0, OUTPUT);
|
||||||
pinMode(GPIO_NUM_21, OUTPUT);
|
pinMode(OUTPUT_PUMP1, OUTPUT);
|
||||||
pinMode(GPIO_NUM_19, OUTPUT);
|
pinMode(OUTPUT_PUMP2, OUTPUT);
|
||||||
pinMode(GPIO_NUM_18, OUTPUT);
|
pinMode(OUTPUT_PUMP3, OUTPUT);
|
||||||
pinMode(GPIO_NUM_5, OUTPUT);
|
pinMode(OUTPUT_PUMP4, OUTPUT);
|
||||||
pinMode(GPIO_NUM_4, OUTPUT);
|
pinMode(OUTPUT_PUMP5, OUTPUT);
|
||||||
pinMode(GPIO_NUM_15, OUTPUT);
|
pinMode(OUTPUT_PUMP6, OUTPUT);
|
||||||
pinMode(GPIO_NUM_13, OUTPUT);
|
pinMode(OUTPUT_SENSOR, OUTPUT);
|
||||||
digitalWrite(GPIO_NUM_23, HIGH);
|
pinMode(OUTPUT_PUMP, OUTPUT);
|
||||||
digitalWrite(GPIO_NUM_22, HIGH);
|
|
||||||
digitalWrite(GPIO_NUM_21, HIGH);
|
pinMode(SENSOR_LIPO, ANALOG);
|
||||||
digitalWrite(GPIO_NUM_19, HIGH);
|
pinMode(SENSOR_SOLAR, ANALOG);
|
||||||
digitalWrite(GPIO_NUM_18, HIGH);
|
pinMode(SENSOR_PLANT0, ANALOG);
|
||||||
digitalWrite(GPIO_NUM_5, HIGH);
|
|
||||||
digitalWrite(GPIO_NUM_4, HIGH);
|
setAll2Off();
|
||||||
digitalWrite(GPIO_NUM_15, HIGH);
|
|
||||||
digitalWrite(GPIO_NUM_13, HIGH);
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
//Increment boot number and print it every reboot
|
//Increment boot number and print it every reboot
|
||||||
@ -75,34 +117,58 @@ void setup() {
|
|||||||
pinMode(GPIO_NUM_27, INPUT_PULLUP);
|
pinMode(GPIO_NUM_27, INPUT_PULLUP);
|
||||||
pinMode(GPIO_NUM_14, INPUT_PULLUP);
|
pinMode(GPIO_NUM_14, INPUT_PULLUP);
|
||||||
pinMode(GPIO_NUM_12, INPUT_PULLUP);
|
pinMode(GPIO_NUM_12, INPUT_PULLUP);
|
||||||
|
|
||||||
|
|
||||||
|
/* Sensor activieren */
|
||||||
|
digitalWrite(OUTPUT_SENSOR, HIGH);
|
||||||
|
|
||||||
|
/* activate power pump and pump 0 */
|
||||||
|
digitalWrite(OUTPUT_PUMP, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
|
||||||
Serial.println("------------");
|
|
||||||
Serial.flush();
|
|
||||||
delay(1000);
|
|
||||||
digitalWrite(GPIO_NUM_23, analogRead(GPIO_NUM_34) > 3500);
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_34));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_35));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_32));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_33));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_25));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_26));
|
|
||||||
|
|
||||||
Serial.println(analogRead(GPIO_NUM_27));
|
|
||||||
Serial.println(analogRead(GPIO_NUM_14));
|
|
||||||
Serial.println(analogRead(GPIO_NUM_12));
|
|
||||||
|
|
||||||
gpio_hold_en(GPIO_NUM_4);
|
|
||||||
gpio_hold_en(GPIO_NUM_13);
|
|
||||||
gpio_hold_en(GPIO_NUM_15);
|
|
||||||
gpio_deep_sleep_hold_en();
|
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
double value = analogRead(SENSOR_LIPO);
|
||||||
|
|
||||||
|
Serial.println(value);
|
||||||
|
|
||||||
|
float temp[2] = {0, 0};
|
||||||
|
float* pFloat = temp;
|
||||||
|
|
||||||
|
Serial.print("DS18B20 sensors: ");
|
||||||
|
Serial.println(ds.readDevices());
|
||||||
|
delay(200);
|
||||||
|
if (ds.readAllTemperatures(pFloat, 2) > 0) {
|
||||||
|
Serial.println(temp[0]);
|
||||||
|
Serial.println(temp[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double volt = ADC_5V_TO_3V3(value);
|
||||||
|
Serial.print("Lipo: ");
|
||||||
|
Serial.println(volt);
|
||||||
|
|
||||||
|
pumpActive = (pumpActive + 1) % 2;
|
||||||
|
if (pumpActive) {
|
||||||
|
digitalWrite(OUTPUT_PUMP0, HIGH);
|
||||||
|
} else {
|
||||||
|
digitalWrite(OUTPUT_PUMP0, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
double solarVal = analogRead(SENSOR_SOLAR);
|
||||||
|
|
||||||
|
Serial.println(solarVal);
|
||||||
|
|
||||||
|
double solarVolt = SOLAR_VOLT(solarVal);
|
||||||
|
Serial.print("Solar: ");
|
||||||
|
Serial.println(solarVolt);
|
||||||
|
|
||||||
|
Serial.print("Moist0: ");
|
||||||
|
Serial.println(analogRead(SENSOR_PLANT0));
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
gpio_deep_sleep_hold_en();
|
||||||
|
gpio_hold_en(GPIO_NUM_13);
|
||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user