implemented irrigation logic + autotoggle by mqtt

This commit is contained in:
Timo Volkmann 2020-07-16 10:55:17 +02:00
parent decdf72f7d
commit 93561d4273
5 changed files with 116 additions and 40 deletions

View File

@ -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;
}
} }

View File

@ -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;
@ -114,7 +115,7 @@ void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
Serial.println(); Serial.println();
if (strcmp(topic, MQTT_LIGHT_PROPERTIES) == 0) { if (strcmp(topic, MQTT_LIGHT_PROPERTIES) == 0) {
Serial.println("receiving light treshold..."); Serial.println("receiving light treshold...");
Serial.println(topic); Serial.println(topic);
StaticJsonDocument<1024> doc; StaticJsonDocument<1024> doc;
DeserializationError err = deserializeJson(doc, payload); DeserializationError err = deserializeJson(doc, payload);
@ -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.");
} }
} }

View File

@ -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();

View File

@ -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() {

View File

@ -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);
}