PROJECT OBJECTIVE: Build an improved automated watering system for your garden that decides, based on soil humidity measured in 16 different places, temperature and time, when to water your plants.

HARDWARE REQUIREMENTS: Provided in the Mango Labs Mechatronics Maker Kit: Arduino-compatible board, USB cable, RTC module, SSR module, temperature sensor, RGB LED module, 2 x 10K resistors, 26 male to male jumper cables, 2 male to female jumper cables, multiplexer board, 3 mini breadboards, 12v power supply.

Additional hardware:computer, electrovalve (I used a washing machine valve that is easy to find), 2 male plugs, 1 female plug, glue gun, 32 galvanized nails, thin solid core wire (telephone or network cable, the length will depend on the position of your sensors), 16 AWG cable (the length will depend on your installation. Vulcanized/outdoor cable or terminals should work fine), CR2032 coin battery, small star screwdriver, pliers/crimper.

SOFTWARE REQUIREMENTS:Arduino environment (or online editor). Download the RTC library here and the Multiplexer library here. Unzip and paste the folder in the Arduino libraries folder. It’s in the same location as your default sketches. You can look it up under File/Preferences Sketchbook location.

KNOW-HOW REQUIREMENTS: Basic Arduino environment knowledge (learn more here). Basic electrical skills.


  1. Connect everything as shown in the diagram.
  2. Check out the Smart Watering project for more detailed explanations; this is an expansion of that lab idea.
  3. Compile and upload this sketch to your board.
  4. Attention: As you are using high voltage, please be very careful and check that you don’t have any exposed leads or any shorts before plugging to mains. Don’t power the Arduino-compatible board from the USB port of your computer.
  5. To be safe, screw the solid state relay board to a non-conductive board together with the outlet. (You can also stick or screw the breadboard and screw the Arduino Uno-compatible board to the same board.)
  6. Connect one pole of the outlet to the SSR board and from the SSR board to your plug, and the other pole of your outlet directly to the other pole of the plug.
    Don’t strip more insulation than needed for the SSR board. You only need to strip 5 mm. Insert the entire exposed end into the screw terminal. Tighten the screws. Check that there aren’t any conductors exposed. For the outlet, you will probably need to strip a little more insulation. This will depend on the outlet you are using, but around 10 mm should be fine. Check that your cables are properly inserted and tightly screwed into the outlet before closing it.
  7. Wire the nails and stick them into the ground approximately 2.5 cm to 4 cm apart. Take care to to use the same spacing between the nails for all the sensors you will install.
  8. Wire the electrovalve and connect the male plug.
  9. Connect the electrovalve to your water supply/spout. If you are using a washing machine electrovalve you can use a regular washing machine hose (mine is 3/4″). Connect a hose to the output (I heated my hose a little to make it fit).
  10. Power your Arduino Uno-compatible board with an external power supply.
  11. Plug the electrovalve into your SSR-controlled outlet.
  12. The LED should blink white three times and repeat every six minutes. If the soil is moist, the LED will stay green. It will change to yellow if it is somewhat dry, and to red if it’s very dry.


Learn More
This project is an expansion of the smart watering lab idea so please first visit it first, since in this lab idea I will only focus on the additional elements.
To be able to expand easily to 16 analog sensors I’ll use the analog capabilities of the HC4067 multiplexer. One of the moisture sensor nails will go to each input of the multiplexer; the other has to be connected to 5 volts. To make it easier I made a 5 volts power rail with small wire jumpers (here you can find a detailed description of how to make the jumpers). You will need an extra small jumper to bridge every hole in the breadboard.
Learn More
You could make mini jumpers and bridge every point but I find it easier to use bigger jumpers and bridge every two holes in the breadboard twice. Once you have your power bridge finished, clip the breadboards together and connect everything as shown on the diagram.
Learn More
Network cable could work if you strip enough insulation on the sensor end to be able to distribute the 4 moisture sensors farther apart. It comes very handy to have 4 pairs of twisted and color coded wires to be able to tell the sensors apart and have tidy connections.
For the moisture sensors I recommend using solid core wire coiled around the nails but you could also use thin cable (I would tin it if possible). In this case I found a telephone cable that will be useful because of its double insulation. You want to have the sensors evenly distributed around your garden so a 2 or 4 conductor cable such as a telephone or network cable will make things easier to wire, allowing you to route 1, 2 or 4 sensors in each cable.
At the other end of the network cable color coded wires will make connecting to the multiplexer easy. The moisture sensors have no polarity so it doesn’t matter at which side you put the striped or whole color wires.
If you want to use less than 16 moisture sensors change the smax variable to the number of sensors you will use.
Follow the diagram to wire the circuit and take special care checking that all the wiring that goes to mains is OK. Upload the sketch from here or copy the code below to your Arduino-compatible board. Time will automatically be set on the RTC board so be sure to have the coin battery already installed; this way, it won’t reset when you unplug it. Unplug the USB and plug the power supply to your Arduino-compatible board to perform a last check.
It’s a good idea to protect your electronics from water. A fast and cheap way to do it is to put everything in a plastic container. Connect your electrovalve to your water supply using a hose and a hose clamp or a washing machine hose. Pin your nails all around your garden, plug the12v power supply to your Arduino-compatible board, plug your electrovalve to the SSR controlled female plug, plug your SSR to mains and you should be done.
Don’t forget to check out the smart watering lab idea for more detailed instructions!

The system checks for normal conditions for every sensor at startup and will light the LED red if something is wrong (it will also send a message through the serial port indicating if there’s a problem in a specific sensor). Every 6 minutes it will check the input variables (and blink white) to decide if watering is needed.


//by Dr Mangus for Mango Labs
//expanded to use 16 humidity sensors
//around your garden

//inspired by
//Grady Hillhouse (March 2015) project

// Improved smart watering
/* Measure humidity in  16 places (or less) of your garden
 * and calulate the average. If some point is to dry turn on a flag
 * and water even if average is above setpoint.
   (tested with IDE 1.8.5 under Windows 10)
  ARDUINO conected to:
   +5V □---------□                      Range  : -25°C to 125°C
                10kΩ = Rw               R_nom  :  10kΩ bei 25°C
   A1  o---------o----------○           T_nom  :           25°C
                         Thermistor     ß-Koeff:         3950
   GND ■---------■----------■           R ~ 1/T
   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ _________________
   A0  o-----------o Z
   D2  o-----------o EN
   D4  o-----------o S0
   D5  o-----------o S1
   D6 o-----------o S2
   D7 o-----------o S3     
   +5V □-----------□ Vcc     
   GND ■-----------■ GND     
    Every output of the multiplexer(Y0...Y15) is connecteed to one nail 
    and the other nail is connected to 5V. Keep distance even between all nails
      RGB LED
   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ _________________
   D9  o-----------o R
   D10  o-----------o G   
   D11 o-----------o B     
   GND ■-----------■ -    

   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ _________________
   A4  o-----------o SDA
   A5  o-----------o SCL 
   +5V □-----------□ Vcc     
   GND ■-----------■ GND     
   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ _________________
   D3  o-----------o CH1  
   +5V □-----------□ DC+     
   GND ■-----------■ DC-     

#include "RTClib.h"
#include "MUX74HC4067.h"

//create a clock instance
RTC_DS1307 rtc;

// Creates a MUX74HC4067 instance
// 1st argument is the Arduino PIN to which the EN pin connects
// 2nd-5th arguments are the Arduino PINs to which the S0-S3 pins connect
MUX74HC4067 mux(2, 4, 5, 6, 7);

#define smax 16             // number of moisture sensors you will install
#define LOG_INTERVAL 360000 //milliseconds between entries (6 minutes = 360000)
// I/O declarations
#define LEDPinRed  9
#define LEDPinGreen 10
#define LEDPinBlue 11
#define ssrPin 3

int wateringTime = 600000; //Set the watering time (10 min for a start)

const float wateringThreshold = 65; //Value in humidity % below which the garden gets watered
// (estimated, based on soil resistivity)

//Thermistor declarations 
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000      
// temp. for nominal resistance (almost always 25 C)
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 10
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 10050    
int samples[NUMSAMPLES];

float Temp = 0; //Scaled value of soil temp (degrees C)
float soilMoistureRaw = 0; //Raw analog input of soil moisture sensor (Ain)
float soilMoisture = 0; //Scaled value of volumetric water content in soil (percent)
float humidity = 0; //Relative humidity (%)
int state = 0;
bool watering = false;
bool wateredToday = false;
DateTime now;

void error(char *str)
  Serial.print("error: ");
  // red LED indicates error
  digitalWrite(LEDPinRed, HIGH);

void setup() {
  //Initialize serial connection
  Serial.begin(9600); //Just for testing
  pinMode(LEDPinRed, OUTPUT); //LED red pin
  pinMode(LEDPinGreen, OUTPUT); //LED green pin
  pinMode(LEDPinBlue, OUTPUT); //LED blue pin
  pinMode(ssrPin, OUTPUT); //solenoid pin
  digitalWrite(ssrPin, HIGH); //Make sure the valve is off (inverted logic)

  // Configures how the SIG pin will be interfaced
  // e.g. The SIG pin connects to PIN A0 on the Arduino,
  //      and PIN A0 is a analog input
  mux.signalPin(A0, INPUT, ANALOG);
  //Establish connection with real time clock
  if (!rtc.begin()) {
        error("RTC failed com");
  //Set the time and date on the real time clock if necessary
  if (! rtc.isrunning()) {
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

// Check if thermistor is inside normal range
Temp = readTemp();
if ((Temp > 45) || (Temp < -25)){
    error("temp sensor out of range");

//Check if humidity sensor is inside normal range
for (byte i = 0; i < smax; ++i) { // Reads moisture sensors to smax. Returns a value from 0 to 1023 soilMoistureRaw =; if ((soilMoistureRaw> 1000) || (soilMoistureRaw < 0)){
    error("humidity sensor out of range");

  now =;

void loop() {
   int haverage = 0; 
   int data = 0;
   bool dryflag = 0;
  //delay software
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  //Three white blinks means start of new cycle
  setColourRgb(75, 90, 100);
  setColourRgb(0, 0, 0);
  setColourRgb(75, 90, 100);
  setColourRgb(0, 0, 0);
  setColourRgb(75, 90, 100);
  setColourRgb(0, 0, 0);
  //Reset wateredToday variable if it's a new day
  if (!( {
    wateredToday = false;
  now =;
  Serial.print(now.year(), DEC);
  Serial.print(now.month(), DEC);
  Serial.print(, DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(now.minute(), DEC);
  Serial.print(now.second(), DEC);
  Serial.print(", ");

  //Collect Variables
  Temp = readTemp();
  for (byte i = 0; i < smax; ++i)
    // Reads moisture sensors to smax. Returns a value from 0 to 1023 and maps to
    //real max and min on the soil. Generates a flag (dryflag) if any point is very dry
    data =;

    Serial.print("moisture at point ");
    Serial.print(" is at ");
    Serial.print(map(data, 150, 950, 0, 1000)/10);
    haverage = haverage + data;
    if (data < 150){ dryflag = 1; } delay(5); } haverage = haverage / 10; haverage = haverage / smax; Serial.print("average moisture is:"); Serial.print(haverage); Serial.println("%"); Serial.println(); delay(20); //Soil Water Content soilMoisture = haverage; Serial.print(Temp); Serial.println("*C, "); // LED display based on soil humidity if (soilMoisture > 24 && soilMoisture < 50)
      setColourRgb(200, 200, 0); //yellow
      else if (soilMoisture < 25 || dryflag == 1) setColourRgb(255, 0, 0); //red else setColourRgb(0, 100, 0); // watering RULES //extreme dryness at any point if ((dryflag == 1) && (Temp > 10)) {
    //water the garden
    digitalWrite(ssrPin, LOW);
        Serial.print("Extreme dryness watering");
        setColourRgb(0, 0, 255);  //blue
        wateringTime = wateringTime * 1.5;  //extend the watering time 
    digitalWrite(ssrPin, HIGH);
  else {
    state = 0;

  //normal conditions
  if ((soilMoisture < wateringThreshold) && (now.hour() > 8) && (now.hour() < 11) && (Temp > 4) && (wateredToday = false)) {
    //water the garden
    digitalWrite(ssrPin, LOW);
        Serial.print("Normal watering");
        setColourRgb(0, 0, 255);  //blue
    digitalWrite(ssrPin, HIGH);
    wateredToday = true;  //record that we're watering
  else {
    state = 0;
//extreme heat
if ((soilMoisture < wateringThreshold) && (now.hour() > 10) && (now.hour() < 19) && (Temp > 27)) {
    //water the garden
    digitalWrite(ssrPin, LOW);
        Serial.print("Extreme heat watering");
        setColourRgb(0, 0, 255);  //blue
        wateringTime = wateringTime / 2;  //half the watering time 
    digitalWrite(ssrPin, HIGH);
  else {
    state = 0;
//protecting plants against freezing
if ((soilMoisture < wateringThreshold) && (now.hour() > 18) && (now.hour() < 22) && (Temp > 4) && (Temp < 9)) {
    //water the garden
    digitalWrite(ssrPin, LOW);
        Serial.print("Cold protection watering");
        setColourRgb(0, 0, 255);  //blue
        wateringTime = wateringTime / 2;  //half the watering time 
    digitalWrite(ssrPin, HIGH);
  else {
    state = 0;

switch (state) {
    case 0:
       Serial.print("Not watering");

float readTemp(){
   uint8_t i;
  float average;
   // take N samples in a row, with a slight delay
  for (i=0; i< NUMSAMPLES; i++) { 
   samples[i] = analogRead(THERMISTORPIN);
  // average all the samples out
  average = 0;
  for (i=0; i< NUMSAMPLES; i++) {
     average += samples[i];
  average /= NUMSAMPLES;
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  float steinhart;
  steinhart = average / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
    return steinhart;   

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(LEDPinRed, red);
  analogWrite(LEDPinGreen, green);
  analogWrite(LEDPinBlue, blue);