Plant watering project - board failure protection with second arduino board

Hello everybody,

This is my first post on the official arduino forum.

I am working on a small personal project aimed at watering my garden plants while I am away from home (vegetables to be exact). The concept is very simple. I am using a basic moisture sensor to monitor the soil. Once the moisture drops below a predefined threshold value the arduino board will send a signal via digital output to a relay. A water pump, which is submerged in a well will be connected to this relay, so once the contacts are short-circuited water will start to flow. I will be using an irrigation hose. The concept of the circuit is presented in the attached picture.

|500x375

In the past I experienced some stability issues with arduino boards. It happened to me that after running for several days my program would hang or some strange behavior could be observed (for example random characters being printed on the LCD instead of the expected data). Perhaps this was due to poor coding which led to memory overflows, inconsistent data types etc., although I always look very carefully through my programs. Due to this fact I am trying to think of some way to monitor the performance of the watering system. I am thinking of using a second arduino board.

Imagine that due to some failure the relay with the attached pump will be constantly turned on. The water pump cannot carry on working for several hours (mainly because once all the water is pumped out it will overheat and might cause a hazardous situation).

One idea I thought about was to use a second arduino board with a second relay which would be also connected to the pump. This board would measure the value of the control signal which is being sent to the first relay by the first board. If it detects an "ON" state for a long enough period, which would indicate some sort of failure it would turn off the second relay for good and thus the pump will not be able to operate. What do you think about such a solution?

Is it possible to feed the output of the first arduino directly to an input pin of the second arduino as in the attached image? Both arduino boards will share the same supply source so they will have a common ground which I think is important in order to have proper readings.

I do not need a recovery process. Once the first board fails the pump is to be turned off for good (the plants may wilt).

Any suggestions are welcome.

Simon

Simon, Why not have a timeout on the first Arduino to prevent that happening? Also, a water level detector will stop your pump running dry when the tank is empty. [u]Post your code,[/u] otherwise, we're just guessing.

while I am away from home

In situations like this, design a fallback circuit which takes over incase your controller goes faulty.

I transferred the full schematic to fritzing. This is how it looks like:

The Code is as follows:

/*
 The LCD circuit:
 * LCD RS pin to digital pin 12 (I CHANGED TO PIN 5)
 * LCD Enable pin to digital pin 11 (I CHANGED TO PIN 10)
 * LCD D4 pin to digital pin 5 (I CHANGED TO PIN 7)
 * LCD D5 pin to digital pin 4 (I CHANGED TO PIN 6)
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
*/


#include <LiquidCrystal.h>
#include <dht.h>
#include <Wire.h>
#include "RTClib.h"


//##############
#define DHT11_PIN 9
dht DHT;

RTC_DS1307 RTC;
DateTime now;

LiquidCrystal lcd(5, 10, 7, 6, 3, 2);
int SoilSensorPin = A1;
int Relay1Pin = 8; 
int BuzzerPin = 11;
float SoilSensorValue;
//##############


//##############
void setup() {
  
  Serial.begin(9600); //Setup the serial monitor transmission rate
  lcd.begin(16, 2); // set up the LCD's number of columns and rows:
  
  
  delay(1000);//Let system settle
  
  pinMode(Relay1Pin, OUTPUT); 
  digitalWrite(Relay1Pin, HIGH); //High means the the relay  is OFF 
   
  pinMode(BuzzerPin, OUTPUT);
  
  Wire.begin();
  RTC.begin();
 
  delay(500);
 
  if (! RTC.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  else
   Serial.println("RTC OK!");
}
//##############


//##############
void loop() {

  ReadFromDHT ();
  ReadSoilSensorValue();
      
  PrintDHTdataSerial();
  PrintSoilSensorDataSerial();
  PrintTimeSerial ();
  
  Display_data_on_LCD();
  
  DetermineTurnOn ();
  
  
}
//##############


//##############
void DetermineTurnOn ()
{
  now = RTC.now(); //get time
  
  if ( (SoilSensorValue < 70) & (DHT.temperature < 26) )
    {
      digitalWrite(Relay1Pin, LOW); //Turn on the water pump
      tone(BuzzerPin,5000, 200);
    }
  else
    digitalWrite(Relay1Pin, HIGH);  
}
//##############


//##############
void ReadFromDHT()
{
   DHT.read11(DHT11_PIN); 
}
//##############


//##############
void ReadSoilSensorValue()
{
  SoilSensorValue = analogRead(SoilSensorPin);
  SoilSensorValue=(1023-SoilSensorValue)/1023*100; //Convert the read value to %
}
//##############


//##############
void PrintDHTdataSerial()
{
    Serial.print("Current humidity = ");
    Serial.print(DHT.humidity, 2);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(DHT.temperature, 2); 
    Serial.println("C  ");
}
//##############


//##############
void PrintSoilSensorDataSerial()
{
    Serial.print("Soil Sensor = ");
    Serial.print(SoilSensorValue,2);
    Serial.print("%\n");
}
//##############


//##############
void PrintTimeSerial ()
{
    now = RTC.now();
 
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(); 
}
//##############


//##############
void Display_data_on_LCD()
{
  
  
  LCD_disp_temperature(0);
  LCD_disp_humidity(1);
  delay(2000);
  lcd.clear();
  LCD_disp_temperature(0);
  LCD_disp_soil_moisture(1);
  delay(2000); 
  lcd.clear();
  LCD_disp_temperature(0);
  LCD_disp_time(1);
  delay(2000);
  
}  
//##############


//##############
void LCD_disp_time (int line) //argument = which line on LCD. Line must be zero or one
{
  now = RTC.now();
  lcd.setCursor(1, line);
  lcd.print(now.hour());
  lcd.print(":");
  lcd.print(now.minute());
  lcd.print(":");
  lcd.print(now.second());
}
//##############


//##############
void LCD_disp_temperature (int line) //argument = which line on LCD. Line must be zero or one
{
  lcd.setCursor(1, line);
  lcd.print("Temp:   ");
  lcd.print(DHT.temperature);
  lcd.print("oC");
}
//##############


//##############
void LCD_disp_humidity(int line) //line must be zero or one
{
  lcd.setCursor(1, line);
  lcd.print("Humid.: ");
  lcd.print(DHT.humidity);
  lcd.print("%");
}
//##############


//##############
void LCD_disp_soil_moisture(int line) //line must be zero or one
{
  lcd.setCursor(1, line);
  lcd.print("Moist.: ");
  lcd.print(SoilSensorValue);
  lcd.print("%");
}
//##############

How it works:

  • the current temperature and humidity is read from the DHT-11 sensor
  • the current soil moisture is read from the FC-28 sensor
  • the current time is also read from the RTC module
  • once the values are read they are displayed both on the Serial Monitor as well as on the attached LCD
  • depending on the readings from the FC-28 and DHT11-temperature the relay is turned on or off. For now do not pay any attention to the triggering conditions (they are just for testing)

Note: time and air humidity do not play any significant role. They are just as an extra feature.

First of all please let me know if the current setup is ok. After compiling and uploading the program everything seems to be working just fine. As you can observe the the 5V pin from the Arduino Nano i supplying all the elements. According the the data I found on the internet the built in voltage regulator can deliver up to 500mA so I think it will manage.

Now assume that due to some error the arduino will keep the relay on for too long (or perhaps even forever). How can I secure the circuit from such a situation? As mentioned in my first post I am thinking of monitoring the output that is going the relay by a second arduino board. If it detects an on-state for to long (lets say 15minutes) it will turn off the second relay.

This doesn’t look correct:

if ( (SoilSensorValue < 70) & (DHT.temperature < 26) )

Try:

if ( (SoilSensorValue < 70) && (DHT.temperature < 26) )

If you set ‘now’ as a global variable, outside loop(), you can use it to check how long the pump has been on for and turn it off if it has been on too long.

Thanks for pointing out the wrong 'and' operand :)

I have a couple of ideas on how the arduino can monitor itself. My concern is how to have a backup in case the arduino fails completely - let's say it stops executing the code and maintains the relay on. In such a case only an external device can cut off the power supply.

Hi. FC-28

  • This is a summary of the moisture sensor can be used to detect soil moisture, when soil water deficiency, the module outputs a high level, whereas output low level. Using this sensor to water the flowers make an automatic device, without people to manage your garden plants.
  • Sensitivity can be adjusted (figure blue digital potentiometer adjust)
  • Soil humidity module on the environment humidity the most sensitive, generally used to detect soil humidity
  • Module in soil moisture can not reach the setting threshold, DO mouth output high level, when soil moisture more than setting threshold value, module D0 output low level
  • Has fixed bolt hole, convenient installation
  • Comparator using LM393 chip, work stability
  • Two small plate interface specifications (3 wires)
  • - VCC external 3.3~5 V
  • - GND external GND
  • - DO small plate digital output interface (0 and 1)
  • - Digital output D0 can be directly connected with the single chip microcomputer, through the single chip microcomputer to detect high and low level, thus to detect soil humidity

The FC-28 has a digital output not an analog. You set a threshold value with the trimpot on the PCB.

Tom..... :)

Hi, again.
Find attached a circuit that may help with your project if you get a controller failure.

It relies on the fact that if you use a PWM signal to activate the relay, use 50% duty, and feed a cap C2 to keep it charged and biasing the internal relay PCB ON.

If a lockup occurs, either the output locking HIGH or LOW, C2 will discharge and remove bias from the transistor and hence turn the relay OFF.

C1 may be smaller than C2.
Its a mod to a TX watchdog timer used in a amateur radio packet modem and component values will need adjusting.

Just an idea.

Tom… :slight_smile:

anyone else notice that the two relays are in series ?

this means that if either fails for any reason, no water.

with two you will have twice the opportunity for failure.

malanski: Thanks for pointing out the wrong 'and' operand :)

I have a couple of ideas on how the arduino can monitor itself. My concern is how to have a backup in case the arduino fails completely - let's say it stops executing the code and maintains the relay on. In such a case only an external device can cut off the power supply.

Connect your pump through the Normally Open contacts of the relay and invert your logic so that, if the Arduino fails, the relay will drop out and the pump will stop. An Arduino is very unlikely to fail leaving an output high.

Henry_Best: Connect your pump through the Normally Open contacts of the relay and invert your logic so that, if the Arduino fails, the relay will drop out and the pump will stop. An Arduino is very unlikely to fail leaving an output high.

Unfortunately the Normally Open contacts are triggered by setting the arduino output to low and therefore I cannot inverse the logic.

TomGeorge: Hi, again. Find attached a circuit that may help with your project if you get a controller failure.

It relies on the fact that if you use a PWM signal to activate the relay, use 50% duty, and feed a cap C2 to keep it charged and biasing the internal relay PCB ON.

If a lockup occurs, either the output locking HIGH or LOW, C2 will discharge and remove bias from the transistor and hence turn the relay OFF.

C1 may be smaller than C2. Its a mod to a TX watchdog timer used in a amateur radio packet modem and component values will need adjusting.

Just an idea.

Tom..... :)

Let me make sure I understand how this circuit works. If the arduino locks with a high state then C1 will charge up and will stop conducting (it will become an open-circuit) and thus only C2 will provide the bias for the transistor for a short time until it discharges. If the arduino locks with a low state then again C2 will be the only voltage source that can bias the transistor and again it will eventually discharge. The relay will operate only if the driving signal is PWM 50% (sort of imitating an AC voltage). Am I correct?

malanski: Unfortunately the Normally Open contacts are triggered by setting the arduino output to low and therefore I cannot inverse the logic.

Normally open contacts are open when the relay is not activated. They close when the relay is activated, completing the external circuit. If your relay is activated by 0V, use the normally closed contacts and invert your logic so that LOW (or a failure) switches the pump off.

Henry_Best:
Normally open contacts are open when the relay is not activated. They close when the relay is activated, completing the external circuit. If your relay is activated by 0V, use the normally closed contacts and invert your logic so that LOW (or a failure) switches the pump off.

I understand now. This will however fail if the arduino turns off completely. In such a case the relay will not be powered and thus the normally closed contacts will stay closed even if the driving signal is zero.

malanski: I understand now. This will however fail if the arduino turns off completely. In such a case the relay will not be powered and thus the normally closed contacts will stay closed even if the driving signal is zero.

best to put the power on the COM on each relay. that way each sees the same wire on the COM connection. then put the motor lead onto the N/O terminal on each relay. that way, if either relay is energized, it will close the connection. if both are energized, it will close the connection. only if both are open will the motor not get power.

Here is a detailed schematic of my original idea. The upper arduino executes the same code as I posted in an earlier post. The second arduino monitors the signal which is being sent to the first relay. If it detects an ON-state for too long it will open the second relay thus stopping the water pump. This way I have greater security. There is a smaller probability that both boards will fail. Of course if one of them fails then my plants will be left without water but this is much better than having the pump continuously running. Can you see any drawbacks in this solution? I think the wiring is ok.

|500x451