Introduction: DIY - Automated Garden Irrigation - (Arduino / IOT)

About: Making things with Arduino, Coding and 3D printing

This project will show you how to build an irrigation controller for a home garden. Capable of measuring soil moisture readings and activating irrigation from a garden tap if the soil becomes too dry. The controller also includes a temperature and humidity sensor. The controller will not activate the garden tap if the temperature is too low. Sensor readings and statistics about water usage / run times are recorded on ThingsBoard IOT for visualisation and analytics. Alerts and emails are triggered if the irrigation controller stops transmitting data, the soil becomes too dry or too saturated.

Prerequisites

  • Arduino knowledge including at least basic coding for Arduino and soldering.
  • 1x pressurised garden tap

Bill Of Materials

  • Garden irrigation poly pipe, jets, drippers etc.
  • Two dial electronic tap timer ( ie: Aqua Systems Electronic Digital Tap Timer)
  • Tap pressure reducer 300kpa
  • Arduino Uno
  • Lora Arduino Shield
  • Lora Gateway (Not needed if you have a local Things Network gateway in range)
  • DHT11 Temperature Humidity sensor
  • 5v Relay
  • Telephone Cable
  • Cable Ties
  • Automotive Split Corrugated Tubing
  • Automotive Terminal Connector Strips
  • 2x Galvanised nails
  • 1x Resistor
  • Silicon / Caulk
  • PVC Cement
  • PVC Primer
  • PVC Pipe 32mm width x 60mm length
  • PVC Pipe 90mm width x 30cm length
  • 3x PVC Push End Caps 90mm
  • 1x PVC Screw End Cap 90mm
  • 1x PVC Threaded Insert Fitting 90mm
  • 1x PVC Push End Caps 32mm
  • 1x 3.2V power source (tap timer) [batteries, AC multivolt adapter]
  • 1x 6-12V power source (arduino) [batteries, USB, USB to AC adapter]
  • thread seal tape
  • electrical tape

Step 1: Install Garden Irrigation

Layout poly pipe, fit jets, drip lines and drippers. The irrigation controller will work with any irrigation fit out. At it's core it is measuring soil moisture readings and activating the tap timer if and when the soil is too dry. The controller can be calibrated to set the low point for saturation, how long the tap timer should be turned on for and how often the controller should check the saturation.

These settings can be changed on the arduino and stored in EPROM memory. The settings can also be updated by the IOT integration. This project will run the controller every four hours and turn on the tap for 3 minutes if the soil is too dry. It may run a few times in a row if dry/hot or once a day or two otherwise.

Step 2: Fit Tap Timer

Fit the tap timer and experiment with the adjustable dials to work out a rough frequency and run time that works best for you irrigation installation. We will be removing the timer and modifying it to work with an Arduino.

Step 3: Arduino Build

Use the wiring diagram as a guide for the build. In the photos telephone cable wiring has been used and screw terminal strips for junction points. Some soldering is required.

Tap Timer Modification

Carefully take apart the tap timer. We will be hard wiring the two adjustable dials so they can be controlled by the arduino instead of the manual dials. The left frequency dial will be hard wired to the reset position so that the right dial can be toggled between the on/off position. The right dial will have one wire coming from the centre right contact and the outer right contact as shown. By default the timer will be in the off position. If the two wires come into contact the timer will turn on. With the two wires connected to a 5V relay, an arduino can then close/open contact between the two wires. With one wire in the common relay terminal and the other in the normally closed terminal we will ensure that the timer is turned off when the arduino is turned off. Setting the relay pin to HIGH will turn on the timer; setting it to LOW will turn off the timer.

Soil Probe

For this project the two nails are soldered to wire connected to screw terminals. One nail's terminal goes straight to ground. The other connects to an analog input in the arduino and a resistor. The resistor connects to the arduinos 5v signal. Shown in the wring diagram.

Temp/Humidity Sensor

The DHT11 Temp/Humidity Sensor is wired into the arduino's 5V, ground and a digital pin on the arduino.

Lora shield

This project also used a Dragino Lora Shield (not shown in the wiring diagram).

PVC Base

The PVC Base for the arduino used in this project was designed so that the temp/humidity sensor could be exposed while keeping all other components secured inside the waterproof PVC enclosure. A small hole is drilled/cut for the sensor and silicon is used to hold it in place while stopping moisture from reaching the arduino. Shown in the diagram.

Step 4: Arduino Programming

Connect the components together via a breadboard or terminal strips for programming and testing

EPROM Configuration

First we need to write configuration variables to EPROM memory. Run the following code on your arduino:

Code available on Github

Here the DRY_VALUE is set at 960. 1024 means that the soil is completely dry, 0 means complete saturation, 960 was a good saturation level for the resistor, cable length and nails used. This may vary depending on your own configuration.

VALVE_OPEN is set at 180000 miliseconds (3 minutes). When/if the tap timer is turned on it will be left open for 3 minutes.

RUN_INTERVAL is set at 14400000 miliseconds (4 hours). This means that the controller will check the soil moisture every four hours and turn on the tap timer for 3 minutes if saturation is low (greater than 960).

The code above can be changed and these values modified at any time.

Program Code

Code available on Github

Dependencies:

This example used the Dragino Lora shield and specifically the Lora concurrent example with the shield connecting directly to the Dragino Lora Gateway.

This can be adapted to use the Things Network by removing the code under the section "BEGIN: lora vars" and changing the program to include the following Dragino example or adapted to work with other radios/wifi shields etc.

The supplied code assumes that DHT11_PIN is digital pin 4, the RELAY_PIN is digital pin 3 and the soil moisture analog pin is analog input 0.

A debug variable can be set to true so that Serial debug messages can be logged at baudrate 9600.

Step 5: Enclosure Build

Cut the PVC pipe to suit the tap timer and Arduino base. Drill holes for the tap timer tap fitting and hose fitting. Drill holes in the pipe wide enough for the automotive conduit, slip 10cm lengths of the conduit into the holes and tease out wires from the arduino and tap timer. This should include:

From the Arduino

  • Power supply wires and/or a usb cable from the arduino's USB port.
  • Soil Moisture cables (VCC,GND,A0)
  • Two wires from the NC & Common screw terminals of the Relay

From the tap timer

  • Power supply cables
  • Two wires from the right dial contacts

Step 6: Test Controller Before Gluing

Make sure everything is still working before sealing everything up.

The photos above show a sample setup in an esky where the soil moisture probe was placed in a pot and the tap timer was fitted with water coming from a soft drink bottle.

One dripper was attached to the tap timer.

This was a good way to test that the setup didn't over or under water the plant.

This example could be run for as long as needed to calibrate the controller.

Step 7: Glue / Waterproof Enclosures

Use PVC Primer and PVC Cement to secure end caps and coupling.

Use caulk/silicon to fill any gaps around the auto conduit and tap timer fittings.

Here a screw end cap is used on the arduino enclosure for accessibility.

Step 8: Install

Install on a clear day. The components and wires will need to stay dry before they are sealed.

Place the controller somewhere centred between where the garden tap is located and where the soil probe will be placed.

Fit the tap timer and make sure it is unpowered until the install is finished.

Fit the soil probe.

Attach strip terminals to each component then lay phone cable from each component's screw terminals making sure the cable is covered in auto conduit. Connecting everything together

Seal all terminals and any other exposed parts with thread seal tape then electrical tape.

Seal any loose/exposed areas of the split conduit with thread seal tape then electrical tape.

Connect the timer to a 3.2v power source. Either a battery pack or to an 3.2V DC - AC adapter running to a mains outlet.

Connect the Arduino to a 6-12V DC power source. Either a battery pack or to a USB / DC-AC adapter running to a mains outlet.

Power Up and test!

Step 9: ThingsBoard Integration - Monitoring and Reporting

This example used A Dragino Lora Shield connected to a Dragino Lora Gateway. Whether using this setup, another Lora setup or any other IOT connectivity the data collected by the irrigation controller can be forwarded onto an IOT platform like Thingsboard. By default the program transmits the following data string where each character byte is hex encoded:

TXXXHXXXSXXXXRX

Where T is followed by the temperature, H is followed by the humidity, S is followed by the saturation level and R is followed by a single digit relating to what action it performed at the last run interval. This can be either 0-5 where each digit means:

0: The program is initialising
1: Temperature Sensor fault
2: Temperature was too low to run
3: Soil moisture too dry so the tap timer was activated
4: Soil moisture fine so the tap timer was not activated
5: The irrigation controller has been deactivated

There are several ways to install a copy of Thingsboard on your own equipment or you can set up a free account on our ThingsBoard installation here.

Set up your device in Thingsboard

Follow these instructions to add a new device in Thingsboard calling it "Irrigation Controller".

Push Telemetry data from device

Follow these instructions to set up a method of pushing telemtry data from the device to Thingboard via MQTT, HTTP or CoAp.

On our server we are pushing the following JSON to https://thingsboard.meansofproduction.tech/api/v1/... every four hours when the device is run (with live data):

{"temperature":13, "humidity":78, "active": true,"saturation":941,"lastRunResult":"RUN_RESULT_NO_WATER"}

Also we are pushing the following attributes to https://thingsboard.meansofproduction.tech/api/v1/... periodically with data on when the node was last seen:

{"lastSeen":"2018-06-04 12:00:00", "secondsSinceLastSeen":1543}

This is used for alerts which are triggered if the device stops transmitting data.

Create a Dashboard

Create a dashboard as described here. Our widgets include:

A simple card widget created from the lastRunResult telemetry field.
A vertical digital guage for the temperature telemetry field
A Timeseries table created from the lastRunResult telemetry field showing the last days data.
A horizontal bar showing the saturation telemetry field. This uses a data post-processing function:

return 1024-value;

And sets a minimum and maximum value 0-100. This way the saturation level can be expressed as a percentage.

A guage to show the humidity value.
A time series bar chart which includes the temp, humidity and run result, grouped into 5 hour periods for the last week, aggregated to show max values. This gives us one bar for a four hour run event. A data post-procesing function is used to express the run result as either 0 or 120 depending on whether or not water was run. That gives an easy visual feedback to see how often water is running in a week.

A static HTML card that shows an image of the garden.

Email alerts

We used rules to set up email alerts for the irrigation controller. All use message filters and a Send mail Action Plugin Action.

To send an email alert if the irrigation controller fails to send data we used 'Device Attributes Filter' with the following filter:

typeof cs.secondsSinceLastSeen !== 'undefined' && cs.secondsSinceLastSeen > 21600

To send an email if the soil becomes too dry use the following Telemetry filter

typeof saturation != "undefined" && saturation > 1010

To send an email based if the soil becomes too moist use the following Telemetry filter

typeof saturation != "undefined" && saturation < 910