The update
So what have changed? Well it now uses a WeMos D1 V2 mini (ESP8266 Wifi) instead of the Arduino Nano for the built in WiFi and compact size, the motor driver have been scraped and replaced with just two transistor, the voltage splitter have also been scraped and everything is powered with a random micro-USB phone charger.
The down side with the WeMos is that it only have one analogue pin and the sensors uses analogue pins. This was overcome by connecting both sensors to the one pin and having diods to prevent back current and messed up readings, this also resulted in some further problems because of the diods nature resulting in messed up readings once again. But by adding some delay between checking each plants this was corrected and I was getting good values.
You will have to test out what values that are right for your plants, the once in the code is good for me(basil and salad). You can set different levels for when the plants are to be watered and if they are to be held at a certain level(just be moist all the time) or maybe get to dry out a bit and then get a proper watering, it’s up to you and your plants.
I won’t attach the database structure or websites for the logging and displaying, but it’s not that complicated to figure out so you can probably sort it out your self (or strip the logging part from the code, up to you). But you can check out my readings here: Green Finger
I’m attaching a parts list, some pictures of my system and the code below(note that the code isn’t optimised in any way and probably contains unused stuff and things)
The stuff
1 x WeMos D1 Mini: https://www.banggood.com/WeMos-D1-Mini-V2-NodeMcu-4M-Bytes-Lua-WIFI-Internet-Of-Things-Development-Board-Based-ESP8266-p-1115398.html
2 x Moisture Sensor: https://www.banggood.com/Soil-Hygrometer-Humidity-Detection-Module-Moisture-Sensor-For-Arduino-p-79227.html
2 x Mini Pumps: https://www.banggood.com/Mini-Submersible-DC-Motor-Pump-3V-120LH-Low-Noise-Max-Lift-p-87235.html
1 x Housing: https://www.banggood.com/2pcs-DIY-Plastic-Project-Housing-Electronic-Junction-Case-Power-Supply-Box-p-1063302.html
2 x 10k Resistors
2 x 2N2222 Transistor
2x 1N4001 Diod
1 x Micro-USB phone charger
And some wires, heat shrink, soldering iron, solder etc. The usual.
The Code
/** * Project: Green Finger WiFi * Self watering system * Author: Henrik Norberg * E-mail: henrik@dbhn.se */ #include <ESP8266WiFi.h> const char* ssid = "Your WiFi Name"; const char* password = "WiFi Password"; WiFiClient client; // motor one int pump1 = D1; //Trigger pin for Pump 1 int pump2 = D2; //Trigger pin for Pump 2 int mostureSensor = A0; //Both mosture sensors on same pin int triggerSens1 = D7; //Power on/off sensor 1 to prevent corrotion int triggerSens2 = D8; //Power on/off sensor 2 to prevent corrotion //Moisture levels int lowLevel = 0; // Sensor states, 0 = Needs chacking, 1 = Ok or too dry/missing int sensor1 = 0; int sensor2 = 0; int sensorValue = 0; int numSensors = 2; //Numbers of sensors int i = 0; //Counter int delayShort = 300000; //Delay between waterings when dry. Default: 300000 = 5min int interval = 10800000; //Delay between waterings when dry. Default: 10800000 = 3h // Tracks the time since last event fired unsigned long previousMillis=0; int watering = 0; //Tell server if watering occured void setup() { // Serial Begin so we can see the data from the mosture sensor in our serial input window. Serial.begin(115200); // Connect to WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); // Print the IP address Serial.print("Use this URL : "); Serial.print("http://"); Serial.print(WiFi.localIP()); Serial.println("/"); // set all the motor control pins to outputs pinMode(pump1, OUTPUT); //pump 1 pinMode(pump2, OUTPUT); //pump 2 pinMode(triggerSens1, OUTPUT); //Trigger 1 pinMode(triggerSens2, OUTPUT); //Trigger 2 } void loop() { unsigned long currentMillis = millis(); delay(1000); if ((unsigned long)(currentMillis - previousMillis) >= interval) { digitalWrite(pump1, LOW); digitalWrite(pump2, LOW); sensor1 = 0; sensor2 = 0; Serial.println("Sensors set to 0"); delay(1000); watering = 0; lowLevel = 650; //Set default moisture low limit while (sensor1 == 0){ Serial.println("Sensor 1 on"); digitalWrite(triggerSens1, HIGH); // read the input from sensor1: mCheck(); Serial.println(sensorValue); digitalWrite(triggerSens1, LOW); Serial.println("Sensor 1 off"); if (sensorValue >= lowLevel && sensorValue <= 800 ){ lowLevel = 500; //Change moisture low limit so the plant gets more water Serial.println("Sensor 1 too dry, watering."); // turn on motor digitalWrite(pump1, HIGH); delay(2000); // now turn off motors digitalWrite(pump1, LOW); watering = 1; delay(delayShort); } else if (sensorValue >= 801) { sensor1 = 1; Serial.println("Sensor 1 too dry or missing."); } else { sensor1 = 1; Serial.println("Sensor 1 - Moisture OK!"); } Serial.println("\nStarting connection to server..."); /** An explanation for my server logging and it's security. The logging works by having a server with an SQL-database setup and a site that the ESP sends data to(or it just opens a webadress basicly). The url have a security key and the watering data. The security key is for hopefully preventing "unwelcomed" data entries, if the key don't match one in the database then the connection is killed. As a extra precaution the site for the data entry have a randomly generated name and can be placed where ever on the server. */ if (client.connect("www.domain.com", 80 //Your website WiFi.printDiag(Serial); String data = "swifty=RandomKey" //Generate a random key + (String) + "&plant=1" //What plant that it concerns + "&value=" +(String) sensorValue //Moisture level + "&water=" + (String) watering; //Was the plant watered? 0/1 client.println("POST /randomsitename.php HTTP/1.1"); //The site name, get a random name for this also client.println("Host: www.domain.com"); client.println("Content-Type: application/x-www-form-urlencoded"); client.print("Content-Length: "); client.println(data.length()); client.println(); client.print(data); Serial.println("\n"); Serial.println("My data string im POSTing looks like this: "); Serial.println(data); Serial.println("And it is this many bytes: "); Serial.println(data.length()); } if (client.connected()) { client.stop(); // DISCONNECT FROM THE SERVER } } i=0; while (i<=600) { //Wait 10min for better readings delay(1000); Serial.println(i); i++; } lowLevel = 650; //Set default moisture low limit watering = 0; while (sensor2 == 0){ // read the input from sensor2: digitalWrite(triggerSens2, HIGH); Serial.println("Sensor 2 on"); mCheck(); Serial.println(sensorValue); digitalWrite(triggerSens2, LOW); Serial.println("Sensor 2 off"); if (sensorValue >= 650 && sensorValue <= 800){ lowLevel = 550; //Change moisture low limit so the plant gets more water Serial.println("Sensor 2 too dry, watering."); // turn on motor // set speed out of possible range 0~255 digitalWrite(pump2, HIGH); delay(2000); // now turn off motors digitalWrite(pump2, LOW); watering = 1; delay(delayShort); } else if (sensorValue >=801) { sensor2 = 1; Serial.println("Sensor 2 too dry or missing."); } else { sensor2 = 1; Serial.println("Sensor 2 OK!"); } Serial.println("\nStarting connection to server..."); if (client.connect("www.domain.com", 80)){ WiFi.printDiag(Serial); String data = "swifty=RandomKey" + (String) + "&plant=2" + "&value=" +(String) sensorValue + "&water=" + (String) watering; client.println("POST /randomsitename.php HTTP/1.1"); client.println("Host: www.domain.com"); client.println("Content-Type: application/x-www-form-urlencoded"); client.print("Content-Length: "); client.println(data.length()); client.println(); client.print(data); Serial.println("\n"); Serial.println("My data string im POSTing looks like this: "); Serial.println(data); Serial.println("And it is this many bytes: "); Serial.println(data.length()); } if (client.connected()) { client.stop(); // DISCONNECT FROM THE SERVER } } delay(400); Serial.println("Done, sleep"); previousMillis = currentMillis; } } void mCheck(){ //Universal sensor checking i = 0; sensorValue = 0; delay(500); while (i<=10) { //"Purge" the diode delay(1000); analogRead(mostureSensor); Serial.println(i); i++; } i=0; sensorValue = analogRead(mostureSensor); Serial.println(sensorValue); return; }
The Future
In future development I would like to make it possible to remote control it for adjusting watering levels etc., add a water level detector to the water tank (so it don’t try to water if there isn’t any water, maybe also add a visual indicator for this), pritty up the wires running from the housing, add a room temperature/hygrometer sensor.