# Tutorial on how to build an automated water irrigation system
Erik Öberg, eo223ex
This tutorial will cover how to build an automated water irrigation system. The water irrigation system will be controlled by moisture sensor and when the senor detects that the soils moisture falls below the desired value the pumps will activate. The desired moisture level can be configured through an AdafruitIO dashboard.
A rough estimate on how long time it takes to complete the project is 1 hour.
# Objective
I have chosen this project because I can not keep my plants alive. [As a IT student I want to embrace the culture and spend a lot of time automating a simple task rather than just learning how to do it](https://i.imgur.com/O295IVX.png). The project purpose is thus fully automate the task of watering plants.
I think the main insight that can be gained is basic IOT knowledge, specifcly how to get serveral sensors to work towards a common goal.
# Material
| Name | Price |Description|
| -------- | -------- |--------|
| [Arduino MKR1010](https://www.electrokit.com/produkt/arduino-mkr-wifi-1010/) | 379.00 SEK | Arduino MKR1000 is a microcontroller with a built in 1×1 PCB-antenna. It offers several digital and analog input and output pins.|
| [Bread board](https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/) | 59.00 SEK | Used for solderless connections for sensors.|
| [Soil moisture sensor](https://www.amazon.se/gp/product/B07HJ6N1S4/ref=ppx_yo_dt_b_asin_title_o00_s01?ie=UTF8&psc=1)| 72,99k |Gets the moisture in the soil. |
| [Relay module](https://www.electrokit.com/produkt/relamodul-5v/) | 39.00 SEK |A relay module is an electrical switch, when activated it either opens or closes an electrical circuit.|
| Wires male female 3-pin x1 | - |Wires to connect the sensors|
| Jumper wires x 3 | - |Wires to connect the senors|
| [Water pump](https://www.kjell.com/se/produkter/el-verktyg/arduino/arduino-tillbehor/vatskepump-240-lh-p87079) | 299.90 SEK |Pumps water|
| [Charger and cable](https://www.amazon.se/b/ref=dp_bc_aui_C_5?ie=UTF8&node=20637908031)|-|To power the pump and the MRK1010|
|Tube for the pump|-|Allow the pump to feed water to the plant|
|Total cost|~850SEK|

# Computer setup
All of the instructions will be for a windows computer, the steps may vary for other operating systems.
I have chosen the *Arduino IDE*. First [download](https://www.arduino.cc/en/software) this IDE, this is the only software that is needed.
After the installation has finished download the software for the board you're using. This software can be downloaded under Tools > Board > Boards Manager and search for the board you're using. I'm using the MKR1010 so I need the following software.

After the installation have finished navigate to Sketch > Include Library >Library Manager or Ctrl + Shift + i. Download the library Adafruit IO Arduino

To upload code, open the Arduino IDE first create a new sketch under File > New or press Ctrl + N. Paste in code that can be found under the code section. To add a config file go to Sketch > Show Sketch Folder or press Ctrl + K. Here create a new header file by creating a new file and naming it config and giving it the extension h. Your folder should now look like this.

Close the folder and to upload the sketch to your Arduino press the upload button that is circled in the image below.

:::info
Remeber to alter the config file and set your WiFi and Adafruit information.
:::
# Putting everything together
How is all the electronics connected? Describe all the wiring, good if you can show a circuit diagram. Be specific on how to connect everything, and what to think of in terms of resistors, current and voltage. Is this only for a development setup or could it be used in production?
Optional, connect the arduino to a breadboard.
1. Connect the moisture sensor to the microcontroller.
* On the moisture sensor you have 3 pins, GND;VCC and AOUT/SIG.
* Connect the GND on the sensor to a GND pin microcontroller, see the black wire in the diagram.
* Connect the VCC to a 5V on the microcontroller, see the red wire in the diagram.
* Connect the AOUT/SIG to an analog pin on the microcontroller, see the yellow wire in the diagram. The example code is using A5 pin.
2. Connect the pump to the to microcontroller. This step may vary depending on the pump you're using, the example provided is using a pump that can't be directly connect the the arduino.
* Connect the relay to the microcontroller. The relay module has 3 pins, mine has the markings +,- and S.
* Connect the + to a V5 pin on the microcontroller, see the red wire in the diagram.
* Connect the - to a GND pin on the microcontroller, see the black wire in the diagram.
* Connect the S to a digital pin on the microcontroller,see the yellow wire in the diagram. The example code is using pin 6.
* Connect the external powersource to the relay. The negative wires from the power source and the pump is connect to the relay, use the middle and the NO slot. The positive wires from the pump and the external power source are connect directly.

This set up is only for development / learning purposes. For example, the pump has a much higher pumping capacity then necessary for the job.
# Platform
I'm using the [Adafruit](https://io.adafruit.com/) platform. This was the only platform that I tried and I stuck with it because I found it easy to use and Adafruit supports a wide variety of devices. Adafruit is a cloud based service that offers both a free and subscription based model.
The free version of Adafruit has some limitations on the Dashboards and the amount of data that can be sent. Also the UI of Adafruit is to my knowledge not customizable. If I were to scale out this project I would opt for [Azure IoT Hub](https://azure.microsoft.com/sv-se/pricing/details/iot-hub/) due to the fact I worked a lot with the services Microsoft offers and the .Net framework. This makes a customizable UI easy for me to achieve.
# The code
:::info
Note: The constants 'dry' and 'wet' values may vary from sensor to senor, thus you might need to modify these constants. To do this you need to connect the moisture sensor. First upload the code below. To get the 'dry' keep the sensor dry and to get the 'wet' value soak "completely" in water to get the max value.
:::
>
> void setup()
{
pinMode(6, OUTPUT);
}
void loop()
{
Serial.println(analogRead(A5));
delay(1000);
}
The code
```
#include "config.h"
// humiditySenor pin A5
#define humiditySenor A5
int targetHumidity = 30;
const int dry = 707;
const int wet = 282;
// setup event to send the currect humudity in the soil.
AdafruitIO_Feed *currentHumidityEvent = io.feed("lazyplantwatering.planthumidity");
// setup event to receive the target soil humdity
AdafruitIO_Feed *targetHumidityEvent = io.feed("lazyplantwatering.targethumidity");
// setup event manually trigger the waterpump
AdafruitIO_Feed *manualWaterTriggerEvent = io.feed("lazyplantwatering.manualtriggerpump");
void setup()
{
// start the serial connection
//Serial.begin(115200);
Serial.begin(9600);
pinMode(6, OUTPUT);
// wait for serial monitor to open
//while(! Serial);
// connect to io.adafruit.com
Serial.print("Connecting to Adafruit IO");
io.connect();
// wait for a connection
while(io.status() < AIO_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println(io.statusText());
// Setup eventhandlers from adafruit
targetHumidityEvent->onMessage(handleNewTargetHumdity);
manualWaterTriggerEvent->onMessage(handleWaterTrigger);
}
void loop()
{
io.run();
int value = analogRead(A5);
int humidity = map(value,wet,dry,100,0);
currentHumidityEvent->save(humidity);
if(humidity < targetHumidity)
{
StartTheWaterPump();
}
delay(5000);
}
void handleWaterTrigger(AdafruitIO_Data *data)
{
Serial.println("Manual promt to start the waterpump.");
if(data->toInt() == 1)
StartTheWaterPump();
delay(100);
}
void handleNewTargetHumdity(AdafruitIO_Data *data)
{
Serial.println("Updating the target humidity");
targetHumidity = data->toInt();
Serial.println(targetHumidity);
}
void StartTheWaterPump()
{
digitalWrite(6,HIGH);
delay(2500);
digitalWrite(6,LOW);
}
```
The configfile
```
// Your Adafruit info
#define IO_USERNAME "Your username"
#define IO_KEY "Your key"
// Your WiFi info
#define WIFI_SSID "Your ssid"
#define WIFI_PASS "Your password"
// uncomment the following line if you are using airlift
// #define USE_AIRLIFT
// uncomment the following line if you are using winc1500
// #define USE_WINC1500
// uncomment the following line if you are using mrk1010 or nano 33 iot
#define ARDUINO_SAMD_MKR1010
// comment out the following lines if you are using fona or ethernet
#include "AdafruitIO_WiFi.h"
#if defined(USE_AIRLIFT) || defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || \
defined(ADAFRUIT_PYPORTAL)
// Configure the pins used for the ESP32 connection
#if !defined(SPIWIFI_SS) // if the wifi definition isnt in the board variant
// Don't change the names of these #define's! they match the variant ones
#define SPIWIFI SPI
#define SPIWIFI_SS 10 // Chip select pin
#define NINA_ACK 9 // a.k.a BUSY or READY pin
#define NINA_RESETN 6 // Reset pin
#define NINA_GPIO0 -1 // Not connected
#endif
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS, SPIWIFI_SS,
NINA_ACK, NINA_RESETN, NINA_GPIO0, &SPIWIFI);
#else
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
#endif
/******************************* FONA **************************************/
// the AdafruitIO_FONA client will work with the following boards:
// - Feather 32u4 FONA -> https://www.adafruit.com/product/3027
// uncomment the following two lines for 32u4 FONA,
// and comment out the AdafruitIO_WiFi client in the WIFI section
// #include "AdafruitIO_FONA.h"
// AdafruitIO_FONA io(IO_USERNAME, IO_KEY);
/**************************** ETHERNET ************************************/
// the AdafruitIO_Ethernet client will work with the following boards:
// - Ethernet FeatherWing -> https://www.adafruit.com/products/3201
// uncomment the following two lines for ethernet,
// and comment out the AdafruitIO_WiFi client in the WIFI section
// #include "AdafruitIO_Ethernet.h"
// AdafruitIO_Ethernet io(IO_USERNAME, IO_KEY);
```
:::warning
The code found below are the event that is used by Adafruit. For example, I have created a group called 'lazyplantwatering' and a feed called 'planthumidity'. You have to do the exact same thing if you want to reuse the code or you can change these values so they match your feed.
```
// setup event to send the currect humudity in the soil.
AdafruitIO_Feed *currentHumidityEvent = io.feed("lazyplantwatering.planthumidity");
// setup event to receive the target soil humdity
AdafruitIO_Feed *targetHumidityEvent = io.feed("lazyplantwatering.targethumidity");
// setup event manually trigger the waterpump
AdafruitIO_Feed *manualWaterTriggerEvent = io.feed("lazyplantwatering.manualtriggerpump");
```
:::
# Transmitting the data / connectivity
The Arduino connects to the internet through WiFi, and for demo purposes data relating to the soil moisture is transmitted from the microcontroller every 5 seconds. In a real world scenario this would be scheduled to run 2-3 times per day. Or the pumps would only activate 2-3 times per day.
To transmit data to the Adafruit dashboard MQTT is used. The microcontroller connects to the Dashboard on Line 10 and the eventhandler for the feeds relating to starting the pumps manually and to set the target humidity. This code can be found on line 37.
The board only supports Bluetooth and WiFi. I wanted to be able to monitor the plants when I’m not at home and WiFi was the only option I had that could support this. I chose the MQTT transport protocol because the goal for this project was to water a plant and monitor the status, not to set up real time connectivity in the form of emails and such.
# Presenting the data
I’m using the dashboard from AdafruitIo. The interface that I have constructed is very simple, the bar on the left shows the current humidity in the plant. The slider in the middle sets the target humidity. And the last button starts the pump manually. Adafruit stores the data collected by the sensors for 60 days.

# Finalizing the design

[Short video demonstration](https://www.youtube.com/shorts/QknH06Jt5q4)
One thing that I would like to improve is to integrate a water level sensor. This is because the pump I’m using is soakable and these pumps will destroy themselves if they can’t get any water. This implementation would block the pump from starting if the water is below a certain level. This feature would be a good use case for a webhook.