Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Toro Watering Controller (c) Mihaly Mayer 2021-May
- // version 3.5
- // Update: 2021.06.06 Cancel Watering
- //
- ADC_MODE(ADC_TOUT);
- #include <NTPClient.h>
- #include <ESP8266WiFiMulti.h>
- #include <ESP8266HTTPClient.h>
- #include <DHT.h>
- #include <Wire.h>
- #include <WiFiUdp.h>
- #include <ArduinoJson.h>
- #include <Wire.h>
- #include <ESP8266WebServer.h>
- #define DEBUG 0
- #define moistureDry 1024
- #define moistureWet 16
- #define HTTP_OK 200
- #define MILLISEC 1000
- #define ACTIVE "1"
- #define DELAY 15000
- unsigned long startmillis, currentmillis;
- int temperateMin = 15;
- int moistureMax = 512;
- int moisturePin = A0;
- int device_id = 5;
- float temperature = 0.0;
- float humidity = 0.0;
- float heat_index = 0.0;
- int soil = 0;
- int rain = 0;
- int moisure = 0;
- boolean watering = false;
- boolean actually_watering = false;
- int DHT_PIN = 2; // D4
- int RAIN_PIN = 5; // D1
- #define AVG_NOZZLE 4
- #define AVG_LITER 0.16
- #define MAX_RELAYS 6
- #define WATER_R1 4 // D2
- #define WATER_R2 0 // D3
- #define WATER_R3 12 // D6
- #define WATER_R4 13 // D7
- #define WATER_R5 15 // D8
- #define WATER_R6 16 // D5
- int water_relays[MAX_RELAYS] = {WATER_R1, WATER_R2, WATER_R3, WATER_R4, WATER_R5, WATER_R6};
- String water_relays_name[MAX_RELAYS] = {"WATER_R1", "WATER_R2", "WATER_R3", "WATER_R4", "WATER_R5", "WATER_R6"};
- #define MAX_TIMES 6
- String water_times[MAX_TIMES][3] = {{"07:00","1","1"},{"13:00","1","1"},{"15:00","1","1"},
- {"17:00","0","0"},{"18:00","0","0"},{"19:00","0","0"}};
- #define MAX_PROGRAMS 6
- int water_programs[MAX_PROGRAMS][MAX_RELAYS] = {{120,120,120,120,120,0},{0,120,120,0,0,0},{0,0,0,0,120,0},
- {120,120,120,120,120,0},{0,60,60,0,0,0},{30,30,0,0,30,0}};
- String router_name;
- String localip;
- long rssi_value = 0;
- float vcc_value = 0.0;
- String apiKeyValue = "...";
- const char* serverWeather = "http://192.168.0.23:8585/post-weather-extra-ip.php";
- const char* serverParams = "http://192.168.0.23:8585/rain_params.php";
- const char* serverWaterParams = "http://192.168.0.23:8585/water_params.php";
- const char* serverWaterUpdate = "http://192.168.0.23:8585/post_water_update.php";
- const char* serverWater = "http://192.168.0.23:8585/post-water.php";
- ESP8266WebServer ESPServer(9595);
- ESP8266WiFiMulti wifiMulti;
- IPAddress ip(192, 168, 0, 95);
- IPAddress gateway(192, 168, 0, 1);
- IPAddress dns(8,8,8,8);
- IPAddress subnet(255, 255, 255, 0);
- char WiFiPassword[] = "...";
- WiFiUDP ntpUDP;
- int GTMOffset = 2;
- NTPClient timeClient(ntpUDP, "pool.ntp.org", GTMOffset*60*60);
- boolean connectToWifi()
- {
- WiFi.config(ip, gateway, subnet, dns);
- while (wifiMulti.run() != WL_CONNECTED) delay(500);
- if (wifiMulti.run() == WL_CONNECTED)
- {
- Serial.println("WIFI ON");
- localip = WiFi.localIP().toString();
- timeClient.begin();
- return true;
- } else
- {
- Serial.println("WIFI OFF");
- return false;
- }
- }
- void get_sensor_Values()
- {
- DHT dht(DHT_PIN, DHT11);
- dht.begin();
- for (int index=0; index<5; index++)
- {
- humidity = dht.readHumidity();
- temperature = dht.readTemperature();
- heat_index = dht.computeHeatIndex();
- if (isnan(humidity) && isnan(temperature))
- {
- humidity = 0.0; temperature = 0.0; heat_index = 0.0;
- } else
- {
- heat_index = dht.computeHeatIndex(temperature,humidity, false);
- break;
- }
- delay(500);
- }
- getRainParams(serverParams);
- soil = analogRead(moisturePin);
- Serial.println("Temperature: " + String(temperature) + " - Humidity: " + String(humidity) + " - Soil: " + String(soil));
- if (rain == 1 || temperature <= temperateMin || soil <= moistureMax) {
- digitalWrite(RAIN_PIN,HIGH); // Rain Sensor ON (No watering)
- Serial.println("Relay HIGH - watering disable");
- watering = false;
- } else {
- Serial.println("Relay LOW - watering enable");
- digitalWrite(RAIN_PIN,LOW); // Rain Sensor OFF (Watering)
- watering = true;
- }
- }
- void getRainParams(String server)
- {
- WiFiClient client;
- HTTPClient http;
- String payload;
- DynamicJsonDocument doc(512);
- http.begin(client, server);
- int httpResponseCode = http.GET();
- if (httpResponseCode == HTTP_OK) {
- payload = http.getString();
- deserializeJson(doc, payload);
- JsonObject root = doc.as<JsonObject>();
- moistureMax = root["soil_param"].as<int>();
- rain = root["rain"].as<int>();
- temperateMin = root["temp_param"].as<int>();
- #ifdef DEBUG
- Serial.println("MoisureMax = " + String(moistureMax) + " - TemperateMin = " + String(temperateMin) + " - RainSet = " + String(rain));
- #endif
- }
- http.end();
- }
- void sendValues_to_database(String server, String key, float temp, float hum,
- float heat, float pres, float alt, int moisure, float soil, int device, String router, String localip, long rsi, float vcc)
- {
- WiFiClient client;
- HTTPClient http;
- http.begin(client, server);
- http.addHeader("Content-Type", "application/x-www-form-urlencoded");
- String httpRequestData = "api_key=" + key
- + "&temperature=" + String(temp)
- + "&humidity=" + String(hum)
- + "&heat=" + String(heat)
- + "&device=" + String(device)
- + "&pressure=" + String(pres)
- + "&altitude=" + String(alt)
- + "&moisure=" + String(moisure)
- + "&soil=" + String(soil)
- + "&router=" + router
- + "&ip=" + localip
- + "&rssi=" + String(rsi)
- + "&vcc=" + String(vcc);
- int httpResponseCode = http.POST(httpRequestData);
- http.end();
- #ifdef DEBUG
- Serial.println(httpRequestData);
- Serial.println(httpResponseCode);
- #endif
- }
- void sendWater_to_database(String server, String key, int wtime, float liter)
- {
- WiFiClient client;
- HTTPClient http;
- http.begin(client, server);
- http.addHeader("Content-Type", "application/x-www-form-urlencoded");
- String httpRequestData = "api_key=" + key
- + "&time=" + String(wtime) +
- + "&liter=" + String(liter);
- int httpResponseCode = http.POST(httpRequestData);
- http.end();
- #ifdef DEBUG
- Serial.println(httpRequestData);
- Serial.println(httpResponseCode);
- #endif
- }
- void updateWater_to_database(String server, String key, int water)
- {
- WiFiClient client;
- HTTPClient http;
- http.begin(client, server);
- http.addHeader("Content-Type", "application/x-www-form-urlencoded");
- String httpRequestData = "api_key=" + key
- + "&water=" + String(water);
- int httpResponseCode = http.POST(httpRequestData);
- http.end();
- #ifdef DEBUG
- Serial.println(httpRequestData);
- Serial.println(httpResponseCode);
- #endif
- }
- void relaysINIT()
- {
- for (int i = 0; i < MAX_RELAYS; i++)
- {
- pinMode(water_relays[i], OUTPUT);
- digitalWrite(water_relays[i], INPUT_PULLUP);
- digitalWrite(water_relays[i], HIGH);
- }
- }
- void send_sensor_Values()
- {
- router_name = WiFi.SSID();
- rssi_value = WiFi.RSSI();
- vcc_value = 5.00; // ((float)ESP.getVcc()/1000);
- sendValues_to_database(serverWeather, apiKeyValue, temperature, humidity, heat_index, 0.0, 0.0, rain ,soil,
- device_id, router_name, localip, rssi_value, vcc_value);
- }
- String getValue(String data, char separator, int index)
- {
- int found = 0;
- int strIndex[] = {0, -1};
- int maxIndex = data.length()-1;
- for(int i=0; i<= maxIndex && found <= index; i++){
- if(data.charAt(i) == separator || i == maxIndex){
- found++;
- strIndex[0] = strIndex[1]+1;
- strIndex[1] = (i == maxIndex) ? i+1 : i;
- }
- }
- return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
- }
- void get_water_Values(String server)
- {
- WiFiClient client;
- HTTPClient http;
- String payload = "";
- DynamicJsonDocument doc(1024);
- http.begin(client, server);
- int httpResponseCode = http.GET();
- if (httpResponseCode == HTTP_OK)
- payload = http.getString();
- http.end();
- if (payload != "")
- {
- String times = getValue(payload,';',0);
- deserializeJson(doc, times);
- JsonArray times_root = doc.as<JsonArray>();
- for (int i=0; i < MAX_TIMES; i++) {
- JsonObject obj = times_root[i];
- water_times[i][0] = obj["timestamp"].as<String>();
- water_times[i][1] = obj["program"].as<String>();
- water_times[i][2] = obj["active"].as<String>();
- Serial.println("Timestamp: " + water_times[i][0] +
- " - Program: " + water_times[i][1] +
- " - Active: " + water_times[i][2]);
- }
- String programs = getValue(payload,';',1);
- deserializeJson(doc, programs);
- JsonArray programs_root = doc.as<JsonArray>();
- for (int i=0; i < MAX_PROGRAMS; i++) {
- JsonObject obj = programs_root[i];
- water_programs[i][0] = obj["R1"].as<int>();
- water_programs[i][1] = obj["R2"].as<int>();
- water_programs[i][2] = obj["R3"].as<int>();
- water_programs[i][3] = obj["R4"].as<int>();
- water_programs[i][4] = obj["R5"].as<int>();
- water_programs[i][5] = obj["R6"].as<int>();
- }
- for (int i = 0; i < MAX_PROGRAMS; i++)
- {
- Serial.print("Program: " + String(i) + " - ");
- for (int j = 0; j < MAX_RELAYS; j++)
- Serial.print("R" + String(j+1) + ": " + String(water_programs[i][j]) + " second, ");
- Serial.println();
- }
- }
- }
- String get_actually_time(boolean sec)
- {
- timeClient.update();
- String times = leadingZero(String(timeClient.getHours())) + ":" + leadingZero(String(timeClient.getMinutes()));
- if (sec == true) times = times + ":" + leadingZero(String(timeClient.getSeconds()));
- return times;
- }
- String leadingZero(String value)
- {
- value.trim();
- if (value.length() == 1) return "0" + value;
- else return value;
- }
- void watering_program()
- {
- int wtime = 0;
- float wwater = 0.0;
- watering = false;
- String actually_time = get_actually_time(false);
- Serial.println("Time is: " + actually_time);
- for (int i = 0; i < MAX_TIMES; i++)
- {
- if (water_times[i][0].equals(actually_time) && water_times[i][2].equals(ACTIVE)) // watering time
- {
- int actually_program = water_times[i][1].toInt()-1;
- Serial.println("Actually program: " + String(actually_program));
- for (int j = 0; j < MAX_RELAYS; j++)
- {
- if ((watering == false) && (water_programs[actually_program][j] != 0))
- {
- updateWater_to_database(serverWaterUpdate, apiKeyValue, 1);
- actually_watering = true;
- relaysON(j, water_programs[actually_program][j]);
- actually_watering = false;
- wtime = wtime + water_programs[actually_program][j];
- wwater = wwater + ((water_programs[actually_program][j] * AVG_LITER) * AVG_NOZZLE);
- updateWater_to_database(serverWaterUpdate, apiKeyValue, 0);
- if (digitalRead(RAIN_PIN) == HIGH) j = MAX_RELAYS; // cancel Watering
- }
- }
- }
- }
- if (wtime != 0)
- {
- Serial.println(String(wtime) + " - " + String(wwater));
- sendWater_to_database(serverWater, apiKeyValue, wtime, wwater);
- }
- watering = true;
- }
- void relaysON(int relay, int time_min)
- {
- relaysINIT();
- switch (relay)
- {
- case 0:
- digitalWrite(WATER_R1, LOW);
- break;
- case 1:
- digitalWrite(WATER_R2, LOW);
- break;
- case 2:
- digitalWrite(WATER_R3, LOW);
- break;
- case 3:
- digitalWrite(WATER_R4, LOW);
- break;
- case 4:
- digitalWrite(WATER_R5, LOW);
- break;
- case 5:
- digitalWrite(WATER_R6, LOW);
- break;
- }
- Serial.println("Watering start with " + water_relays_name[relay] + " at " + get_actually_time(true) + " for " + String(time_min) + " second");
- unsigned long etime = timeClient.getEpochTime() + time_min;
- while (timeClient.getEpochTime() <= etime)
- {
- ESPServer.handleClient();
- }
- //delay(time_min * MILLISEC);
- Serial.println("Watering end with " + water_relays_name[relay] + " at " + get_actually_time(true));
- relaysINIT();
- }
- void handleRoot() {
- String html = "<html><head><meta http-equiv='refresh' content='60'><title>Watering System</title></head>";
- html = html + "<body>TORO Watering System (c) Mayer Mihaly 2021-Apr<br><b>Ready</b>";
- html = html + "<br><br>Time is " + get_actually_time(true);
- html = html + "<br><br>Watering ";
- if (watering)
- html = html + "ON";
- else
- html = html + "OFF";
- if (actually_watering)
- html = html + "<p style='color:#FF0000'><b>Actually is *** running ***</b></p>";
- else
- html = html + "<br>Actually is <b>not running</b><br>";
- html = html + "Temperature = " + String(temperature) + " (" + String(heat_index) + ")" +
- ", Humidity = " + String(humidity) +
- ", Soil = " + String(soil) +
- ", Rain = " + String(rain);
- html = html + "<br>";
- for (int i=0; i < MAX_TIMES; i++) {
- html = html + "<br>Timestamp: " + water_times[i][0] +
- " - Program: " + water_times[i][1] + " - Active: " + water_times[i][2];
- }
- html = html + "<br>";
- for (int i = 0; i < MAX_PROGRAMS; i++)
- {
- html = html + "<br>Program: " + String(i+1) + " - ";
- for (int j = 0; j < MAX_RELAYS; j++)
- html = html + "R" + String(j+1) + ": " + String(water_programs[i][j]) + " second, ";
- }
- html = html + "</body></html>";
- ESPServer.send(200, "text/html", html);
- }
- void handleOFF() {
- ESPServer.send(200, "text/html", "TORO Watering System<br>Watering is <b>OFF</b>");
- digitalWrite(RAIN_PIN,HIGH); // Rain Sensor ON (No watering)
- watering = true;
- }
- void handleON() {
- ESPServer.send(200, "text/html", "TORO Watering System<br>Watering is <b>ON</b>");
- digitalWrite(RAIN_PIN,LOW); // Rain Sensor OFF (Watering)
- watering = false;
- }
- void setup() {
- Serial.begin(115200);
- wifiMulti.addAP("thome2", WiFiPassword);
- wifiMulti.addAP("TP-LINK", WiFiPassword);
- wifiMulti.addAP("TP-LINK-2", WiFiPassword);
- connectToWifi();
- localip = WiFi.localIP().toString();
- pinMode(RAIN_PIN,OUTPUT);
- relaysINIT();
- startmillis = millis();
- ESPServer.on("/", HTTP_GET, handleRoot);
- ESPServer.on("/on", HTTP_GET, handleON);
- ESPServer.on("/off", HTTP_GET, handleOFF);
- timeClient.update();
- Serial.println("Time is: " + get_actually_time(false));
- }
- void loop() {
- if (wifiMulti.run() != WL_CONNECTED) connectToWifi();
- timeClient.update();
- ESPServer.begin();
- ESPServer.handleClient();
- currentmillis = millis();
- if ((currentmillis - startmillis) >= DELAY) {
- get_sensor_Values();
- send_sensor_Values();
- get_water_Values(serverWaterParams);
- Serial.println("watering=" + String(watering));
- if (watering == true)
- {
- watering_program();
- digitalWrite(RAIN_PIN,LOW); // Watering ON
- }
- startmillis = currentmillis;
- }
- if ((get_actually_time(true) >= "00:00:00") && (get_actually_time(true) <= "00:00:02"))
- ESP.restart();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement