implemented irrigation logic + autotoggle by mqtt
This commit is contained in:
parent
decdf72f7d
commit
93561d4273
@ -20,14 +20,16 @@ int readCapacitiveSoilMoistureSensor()
|
|||||||
delay(2);
|
delay(2);
|
||||||
}
|
}
|
||||||
int measurement = total / numReadings;
|
int measurement = total / numReadings;
|
||||||
Serial.print("soil moisture raw: ");
|
|
||||||
Serial.println(measurement);
|
|
||||||
// add the reading to the total:
|
|
||||||
//int measurement = analogRead(PIN_MS);
|
|
||||||
|
|
||||||
if (map(measurement, VALUE_AIR, VALUE_WATER, 0, 100) < 0) {
|
int finalRes = map(measurement, VALUE_AIR, VALUE_WATER, 0, 100);
|
||||||
|
Serial.print("current soil moisture: ");
|
||||||
|
Serial.println(finalRes);
|
||||||
|
|
||||||
|
if (finalRes < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (map(measurement, VALUE_AIR, VALUE_WATER, 0, 100) > 100) {
|
} else if (finalRes > 100) {
|
||||||
return 100;
|
return 100;
|
||||||
} else {return map(measurement, VALUE_AIR, VALUE_WATER, 0, 100);}
|
} else {
|
||||||
|
return finalRes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ extern "C" {
|
|||||||
#define MQTT_VALVE_COMMAND MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/valve"
|
#define MQTT_VALVE_COMMAND MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/valve"
|
||||||
#define MQTT_SOIL_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/soil"
|
#define MQTT_SOIL_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/soil"
|
||||||
#define MQTT_LIGHT_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/light"
|
#define MQTT_LIGHT_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/light"
|
||||||
|
#define MQTT_AUTO_PROPERTIES MQTT_TOPIC_BASE_SUB "/" MQTT_DEVICE_ID "/automatic"
|
||||||
|
|
||||||
TimerHandle_t mqttReconnectTimer;
|
TimerHandle_t mqttReconnectTimer;
|
||||||
TimerHandle_t wifiReconnectTimer;
|
TimerHandle_t wifiReconnectTimer;
|
||||||
@ -129,7 +130,7 @@ Serial.println("receiving light treshold...");
|
|||||||
if (strcmp(topic, MQTT_VALVE_COMMAND) == 0) {
|
if (strcmp(topic, MQTT_VALVE_COMMAND) == 0) {
|
||||||
Serial.println("toggling valve...");
|
Serial.println("toggling valve...");
|
||||||
Serial.println(topic);
|
Serial.println(topic);
|
||||||
toggleValve();
|
toggleValve(false);
|
||||||
}
|
}
|
||||||
if (strcmp(topic, MQTT_SOIL_PROPERTIES) == 0) {
|
if (strcmp(topic, MQTT_SOIL_PROPERTIES) == 0) {
|
||||||
Serial.println("receiving soil thresholds...");
|
Serial.println("receiving soil thresholds...");
|
||||||
@ -145,6 +146,19 @@ Serial.println("receiving light treshold...");
|
|||||||
Serial.println(err.c_str());
|
Serial.println(err.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (strcmp(topic, MQTT_AUTO_PROPERTIES) == 0) {
|
||||||
|
Serial.println("receiving auto settings...");
|
||||||
|
Serial.println(topic);
|
||||||
|
StaticJsonDocument<1024> doc;
|
||||||
|
DeserializationError err = deserializeJson(doc, payload);
|
||||||
|
if (err == DeserializationError::Ok) {
|
||||||
|
bool ir = doc["irrigation"];
|
||||||
|
bool li = doc["light"];
|
||||||
|
setAutoProperties(li, ir);
|
||||||
|
} else {
|
||||||
|
Serial.println(err.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupConnections() {
|
void setupConnections() {
|
||||||
@ -174,8 +188,8 @@ void publishMessage(const char *topic, const char *msg) {
|
|||||||
if(mqttClient.connected()) {
|
if(mqttClient.connected()) {
|
||||||
mqttClient.publish(topic, msg);
|
mqttClient.publish(topic, msg);
|
||||||
Serial.print(topic);
|
Serial.print(topic);
|
||||||
Serial.println(" successfully sent.\n");
|
Serial.println(" successfully sent.");
|
||||||
} else {
|
} else {
|
||||||
Serial.println("couldn't send message. waiting for reconnect.\n");
|
Serial.println("couldn't send message. waiting for reconnect.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/header.h
11
src/header.h
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
// Ventil
|
// Ventil
|
||||||
#define PIN_VALVE 32
|
#define PIN_VALVE 32
|
||||||
#define MAX_VALVE_TIMEOUT 10000
|
#define MAX_VALVE_TIMEOUT 5000
|
||||||
|
|
||||||
// STATUS LED
|
// STATUS LED
|
||||||
#define PIN_LED_R 2
|
#define PIN_LED_R 2
|
||||||
@ -63,7 +63,7 @@
|
|||||||
// MQTT_DEVICE_ID "/#"
|
// MQTT_DEVICE_ID "/#"
|
||||||
|
|
||||||
// PUBLISH FREQUENCY (MS)
|
// PUBLISH FREQUENCY (MS)
|
||||||
#define FREQUENCY 60000
|
#define FREQUENCY 20000
|
||||||
|
|
||||||
// moisture
|
// moisture
|
||||||
extern void setupCapacitiveSoilMoistureSensor();
|
extern void setupCapacitiveSoilMoistureSensor();
|
||||||
@ -96,12 +96,15 @@ int getCurrentHour();
|
|||||||
|
|
||||||
// sensors
|
// sensors
|
||||||
void readSensors();
|
void readSensors();
|
||||||
void toggleValve();
|
void toggleValve(bool automatic);
|
||||||
void setSoilProperties(int FC, int PWP, int SAT);
|
void setSoilProperties(int FC, int PWP, int SAT);
|
||||||
void setupStore();
|
void setupStore();
|
||||||
void setLightProperties(int NM, int minLX);
|
void setLightProperties(int NM, int minLX);
|
||||||
void restoreLightProbs();
|
void restoreLightProps();
|
||||||
void persistLightProps(int NM, int minLX);
|
void persistLightProps(int NM, int minLX);
|
||||||
|
void restoreAutoProps();
|
||||||
|
void persistAutoProps(bool light, bool irrigation);
|
||||||
|
void setAutoProperties(bool light, bool irrigation);
|
||||||
|
|
||||||
void takeSemaphore();
|
void takeSemaphore();
|
||||||
void releaseSemaphore();
|
void releaseSemaphore();
|
||||||
|
|||||||
@ -34,6 +34,8 @@ void setup() {
|
|||||||
Serial.println("Setup complete...");
|
Serial.println("Setup complete...");
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
// first read without delay
|
||||||
|
readSensors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
@ -21,8 +21,12 @@ int permanentWiltingPoint = 25;
|
|||||||
int soilSaturation = 69;
|
int soilSaturation = 69;
|
||||||
// Helligkeitswert der mindestens vorhanden sein muss
|
// Helligkeitswert der mindestens vorhanden sein muss
|
||||||
int minimumLightValueLX = 50;
|
int minimumLightValueLX = 50;
|
||||||
|
// switches for automatic light and irrigation control
|
||||||
|
bool automaticLight = true;
|
||||||
|
bool automaticIrrigation = true;
|
||||||
|
|
||||||
void readSensors() {
|
void readSensors() {
|
||||||
|
Serial.println();
|
||||||
StaticJsonDocument<128> doc;
|
StaticJsonDocument<128> doc;
|
||||||
float lxValue = readLightSensorValue();
|
float lxValue = readLightSensorValue();
|
||||||
Serial.print("Light intensity: ");
|
Serial.print("Light intensity: ");
|
||||||
@ -32,30 +36,33 @@ void readSensors() {
|
|||||||
if((lxValue < minimumLightValueLX) && checkForDay()) {
|
if((lxValue < minimumLightValueLX) && checkForDay()) {
|
||||||
triggerLight();
|
triggerLight();
|
||||||
}
|
}
|
||||||
//sprintf(buffer, "%f", lxValue);
|
|
||||||
//publishMessage(MQTT_BRIGHTNESS, buffer);
|
|
||||||
|
|
||||||
int mstValue = readCapacitiveSoilMoistureSensor();
|
int mstValue = readCapacitiveSoilMoistureSensor();
|
||||||
Serial.print("Soil moisture: ");
|
Serial.print("Soil moisture: ");
|
||||||
Serial.println(mstValue);
|
Serial.println(mstValue);
|
||||||
// sprintf(buffer, "%i", mstValue);
|
// if (mstValue > fieldCapacity) {
|
||||||
// publishMessage(MQTT_MOISTURE, buffer);
|
// Serial.println("Field capacity reached. No irrigation needed. ");
|
||||||
|
// }
|
||||||
|
// if (mstValue < permanentWiltingPoint) {
|
||||||
|
// Serial.println("Permanent wilting point reached. Plant needs irrigation. ");
|
||||||
|
// }
|
||||||
|
if (automaticIrrigation) {
|
||||||
|
toggleValve(true);
|
||||||
|
}
|
||||||
|
|
||||||
doc["moisture"] = mstValue;
|
doc["moisture"] = mstValue;
|
||||||
|
|
||||||
float humidityValue = readHumidity();
|
float humidityValue = readHumidity();
|
||||||
Serial.print("Humidity: ");
|
Serial.print("Humidity: ");
|
||||||
Serial.println(humidityValue);
|
Serial.println(humidityValue);
|
||||||
// sprintf(buffer, "%f", humidityValue);
|
|
||||||
// publishMessage(MQTT_HUMIDITY, buffer);
|
|
||||||
doc["humidity"] = humidityValue;
|
doc["humidity"] = humidityValue;
|
||||||
|
|
||||||
float temperatureValue = readTemperature();
|
float temperatureValue = readTemperature();
|
||||||
Serial.print("Temperature: ");
|
Serial.print("Temperature: ");
|
||||||
Serial.println(temperatureValue);
|
Serial.println(temperatureValue);
|
||||||
// sprintf(buffer, "%f", temperatureValue);
|
|
||||||
// publishMessage(MQTT_TEMPERATURE, buffer);
|
|
||||||
doc["temperature"] = temperatureValue;
|
doc["temperature"] = temperatureValue;
|
||||||
Serial.print("\n");
|
|
||||||
serializeJson(doc, buffer);
|
serializeJson(doc, buffer);
|
||||||
publishMessage(MQTT_SENSOR_DATA, buffer);
|
publishMessage(MQTT_SENSOR_DATA, buffer);
|
||||||
}
|
}
|
||||||
@ -76,31 +83,42 @@ bool closeValve() {
|
|||||||
|
|
||||||
void valveTask(void *parameter) {
|
void valveTask(void *parameter) {
|
||||||
takeSemaphore();
|
takeSemaphore();
|
||||||
|
bool isAutomatic = (bool)parameter;
|
||||||
|
Serial.println("Valve task triggered.");
|
||||||
unsigned long valveTimeoutTimer = millis();
|
unsigned long valveTimeoutTimer = millis();
|
||||||
bool valveOpen = openValve();
|
bool valveOpen = false;
|
||||||
|
int initialSoilMoisture = readCapacitiveSoilMoistureSensor();
|
||||||
|
|
||||||
|
if (initialSoilMoisture > permanentWiltingPoint) {
|
||||||
|
Serial.println("Soil contains enough water. No irrigation needed. ");
|
||||||
|
} else {
|
||||||
|
valveOpen = openValve();
|
||||||
|
}
|
||||||
|
|
||||||
while (valveOpen) {
|
while (valveOpen) {
|
||||||
delay(500);
|
delay(500);
|
||||||
int mstValue = readCapacitiveSoilMoistureSensor();
|
int mstValue = readCapacitiveSoilMoistureSensor();
|
||||||
|
|
||||||
if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) {
|
if (mstValue > fieldCapacity) { // && isAutomatic
|
||||||
|
Serial.println("Field capacity reached. No irrigation needed. ");
|
||||||
|
valveOpen = closeValve();
|
||||||
|
}
|
||||||
|
if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) {
|
||||||
|
Serial.println("Irrigation timeout reached. close valve. ");
|
||||||
valveOpen = closeValve();
|
valveOpen = closeValve();
|
||||||
}
|
}
|
||||||
// if (mstValue > 80) {
|
|
||||||
// valveOpen = closeValve();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
releaseSemaphore();
|
releaseSemaphore();
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleValve() {
|
void toggleValve(bool automatic) {
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
valveTask, /* Task function. */
|
valveTask, /* Task function. */
|
||||||
"valveTask", /* String with name of task. */
|
"valveTask", /* String with name of task. */
|
||||||
2048, /* Stack size in bytes. */
|
2048, /* Stack size in bytes. */
|
||||||
NULL, /* Parameter passed as input of the task */
|
&automatic, /* Parameter passed as input of the task */
|
||||||
1, /* Priority of the task. */
|
3, /* Priority of the task. */
|
||||||
NULL); /* Task handle. */
|
NULL); /* Task handle. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,15 +152,19 @@ void restoreSoilProps() {
|
|||||||
if (sat != 0) {
|
if (sat != 0) {
|
||||||
soilSaturation = sat;
|
soilSaturation = sat;
|
||||||
}
|
}
|
||||||
Serial.print(fieldCapacity);
|
Serial.print("fieldCapacity: ");
|
||||||
Serial.print(permanentWiltingPoint);
|
Serial.println(fieldCapacity);
|
||||||
Serial.print(soilSaturation);
|
Serial.print("permanentWiltingPoint: ");
|
||||||
|
Serial.println(permanentWiltingPoint);
|
||||||
|
Serial.print("soilSaturation: ");
|
||||||
|
Serial.println(soilSaturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupStore() {
|
void setupStore() {
|
||||||
NVS.begin("store");
|
NVS.begin("store");
|
||||||
restoreSoilProps();
|
restoreSoilProps();
|
||||||
restoreLightProbs();
|
restoreLightProps();
|
||||||
|
restoreAutoProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSoilProperties(int FC, int PWP, int SAT) {
|
void setSoilProperties(int FC, int PWP, int SAT) {
|
||||||
@ -160,7 +182,7 @@ void setSoilProperties(int FC, int PWP, int SAT) {
|
|||||||
|
|
||||||
void persistLightProps(int NM, int minLX) {
|
void persistLightProps(int NM, int minLX) {
|
||||||
takeSemaphore();
|
takeSemaphore();
|
||||||
Serial.println("persistSoilProps");
|
Serial.println("persistLightProps");
|
||||||
bool n = NVS.setInt("nanoMeter", NM);
|
bool n = NVS.setInt("nanoMeter", NM);
|
||||||
bool m = NVS.setInt("minimumLux", minLX);
|
bool m = NVS.setInt("minimumLux", minLX);
|
||||||
if (n && m) {
|
if (n && m) {
|
||||||
@ -168,12 +190,12 @@ void persistLightProps(int NM, int minLX) {
|
|||||||
NVS.commit();
|
NVS.commit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Serial.println("error occured while trying to persist soil properties");
|
Serial.println("error occured while trying to persist light properties");
|
||||||
}
|
}
|
||||||
releaseSemaphore();
|
releaseSemaphore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreLightProbs() {
|
void restoreLightProps() {
|
||||||
Serial.println("restoreLightProps");
|
Serial.println("restoreLightProps");
|
||||||
int nm = NVS.getInt("nanoMeter");
|
int nm = NVS.getInt("nanoMeter");
|
||||||
int minLX = NVS.getInt("minimumLux");
|
int minLX = NVS.getInt("minimumLux");
|
||||||
@ -183,7 +205,7 @@ void restoreLightProbs() {
|
|||||||
if (minLX != 0) {
|
if (minLX != 0) {
|
||||||
minimumLightValueLX = minLX;
|
minimumLightValueLX = minLX;
|
||||||
}
|
}
|
||||||
Serial.print(minimumLightValueLX);
|
Serial.println(minimumLightValueLX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLightProperties(int NM, int minLX) {
|
void setLightProperties(int NM, int minLX) {
|
||||||
@ -193,3 +215,36 @@ void setLightProperties(int NM, int minLX) {
|
|||||||
Serial.print("new minimum Light Value LX: ");
|
Serial.print("new minimum Light Value LX: ");
|
||||||
Serial.println(minimumLightValueLX);
|
Serial.println(minimumLightValueLX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void persistAutoProps(bool light, bool irrigation) {
|
||||||
|
takeSemaphore();
|
||||||
|
Serial.println("persistAutoProps");
|
||||||
|
// saved in NVS as Integer: 1 = true, 2 = false, 0 = not persisted, use standard settings
|
||||||
|
bool n = NVS.setInt("automaticLight", (light ? 1 : 2));
|
||||||
|
bool m = NVS.setInt("automaticIrrigation", (irrigation ? 1 : 2));
|
||||||
|
if (n && m) {
|
||||||
|
NVS.commit();
|
||||||
|
Serial.println("Auto properties sucessfully stored.");
|
||||||
|
} else {
|
||||||
|
Serial.println("error occured while trying to persist auto properties");
|
||||||
|
}
|
||||||
|
releaseSemaphore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoreAutoProps() {
|
||||||
|
Serial.println("restoreLightProps");
|
||||||
|
int li = NVS.getInt("automaticLight");
|
||||||
|
int ir = NVS.getInt("automaticIrrigation");
|
||||||
|
automaticLight = (bool) (li != 2);
|
||||||
|
automaticIrrigation = (bool) (ir != 2);
|
||||||
|
Serial.println(minimumLightValueLX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoProperties(bool light, bool irrigation) {
|
||||||
|
automaticLight = light;
|
||||||
|
automaticIrrigation = irrigation;
|
||||||
|
persistAutoProps(light, irrigation);
|
||||||
|
Serial.print("new auto settings: ");
|
||||||
|
Serial.println(automaticLight);
|
||||||
|
Serial.println(automaticIrrigation);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user