In this post we are going to construct a GSM based irrigation circuit which can be used to turn ON / OFF the motor pump or any electronic gadgets connect to it with just a missed call and you will be notified with an acknowledgement SMS back to owner’s mobile phone.
Implementing GSM Based Irrigation System
Here is another project which might bring delight among agriculturists across the globe, especially country like India where their economy and development is sky rocketing and agricultural land owners seeking a technological development for their side too.
This new design overcomes some of the issues which previous GSM based irrigation system had.
The major problem was senior citizens in rural area weren’t knowledgeable enough to send a text SMS. But they were knowledgeable enough to make calls and recognize whether the call is “not reachable” or “out of range” or “subscriber is busy” or the other party picked up their call.
We will be constructing an Arduino based circuit which can trigger a relay with a call. The call will be terminated after a couple of rings automatically and gives out an acknowledgement SMS back to the owner’s phone. Making a call to the circuit rather than a text SMS will cut down the network service cost by half.
Calling to GSM module will cost you nothing, but the acknowledgement SMS back from the GSM module might cost you.
The system will respond onlyto the owner’s mobile phone number. Any calls from any other number will be rejected.
Let’s dive in to the technical details.
Circuit Diagram:
The circuit consists of Arduino which is brain of the project and GSM module SIM 900 / SIM 800 which is the heart of the project. An optional 16 x 2 LCD display is included which can show you tons of information what’s going in the system.
A 9 V relay is utilized to turn on / off the connected motor pump (or any gadgets). Two DC jacks which will power the Arduino and GSM module.
In the previous GSM based irrigation system the program has to be loaded while the Tx and Rx pins are disconnected from GSM module.
With the new design it utilizes software serial communication and you no need to disconnect the Tx and Rx pins from GSM module while uploading the code.
The pin #2 of Arduino is connected to Tx pin of GSM module and pin #3 of Arduino is connect to Rx pin of the GSM module. Ground to ground between Arduino and GSM module also need to be connected.
A diode 1N4007 need to connected in reverse bias across the relay i.e. anode to collector of the transistor and cathode to positive supply.
This will prevent harmful high amplitude back EMF entering rest of the circuit from relay coil. The diode connection is not shown in the schematic.
The LCD display is connected with I2C module to reduce number of wires and reduce wire congestion.
Please note that you have to use I2C module if you are connecting 16 x 2 LCD display to the circuit.
Download the following Library file to compile the code (don’t use any other version of I2C Library file):
https://github.com/marcoschwartz/LiquidCrystal_I2C
Program code:
// ------------- Program Developed by R.GIRISH ---------- //
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>
SoftwareSerial gsm(2, 3); // RX, TX
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ----------- ----------- //
int address = 0; // <<<<<<< Change address = 10 in case of EEPROM failure.
int wr_call_add = 1; // <<<<<<<< Change wr_call_add = 11 in case of EEPROM failure.
int f_address = 2; // <<<<<<<<< Chnage f_address = 12 in case of EEPROM failure.
int eeprom_dead = 3; // <<<<<<<<<< Change eeprom_dead = 13 inc case of EEPROM failure.
// ----------- ----------- //
int wr_call_val = 0;
int f_value = 70;
int value = 0;
int ring = 0;
int i = 0;
int var = 0;
int eeprom_tst = 0;
int eeprom_tst_ack = 0;
int tst_var = 100;
int wr_call_tst = 100;
int eeprom_dead_val = 0;
String number = "";
String string = "";
const int output = 8;
boolean wait = true;
boolean at_flag = 1;
boolean net_flag = 1;
// ================ ============== //
char str[] = "91xxxxxxxxxx";
// ================= ============= //
// Replace xxxxxx your phone number starting with "91" which is India country code.
// Replce "91" with your own country code, if outside India.
void setup()
{
Serial.begin(9600);
lcd.init();
lcd.backlight();
gsm.begin(9600);
pinMode(output, OUTPUT);
if (EEPROM.read(f_address) != f_value)
{
EEPROM.write(f_address, f_value);
EEPROM.write(address, value);
EEPROM.write(wr_call_add, wr_call_val);
eeprom_dead_val = 0;
EEPROM.write(eeprom_dead, eeprom_dead_val);
}
if (EEPROM.read(eeprom_dead) == 1)
{
while (true)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EEPROM Error.");
lcd.setCursor(0, 1);
lcd.print("System Disabled.");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reload the code");
lcd.setCursor(0, 1);
lcd.print("with new address");
delay(1500);
}
}
if (EEPROM.read(address) == 0)
{
digitalWrite(output, LOW);
gsm_init();
lcd.clear();
if (EEPROM.read(wr_call_add) == 0)
{
lcd.setCursor(0, 0);
lcd.print("Sending SMS");
lcd.setCursor(0, 1);
lcd.print("Acknowledgement.");
delay(1000);
gsm.println("AT+CMGF=1");
delay(500);
gsm.print("AT+CMGS=");
gsm.print("\"");
gsm.print(str);
gsm.println("\"");
delay(1000);
gsm.println("Motor is OFF / System is Ready.");
delay(100);
gsm.println((char)26);
}
if (EEPROM.read(wr_call_add) == 1)
{
wr_call_val = 0;
EEPROM.write(wr_call_add, wr_call_val);
}
}
if (EEPROM.read(address) == 1)
{
eeprom_test();
output_begin();
}
}
void(* resetFunc) (void) = 0;
void loop()
{
serialEvent();
if (ring == 1)
{
number = "";
var = string.indexOf("+CLIP: \"");
if (var > 0)
{
number += string.substring(var + 8, var + 13 + 7);
}
if (number[0] == str[0] && number[1] == str[1] && number[2] == str[2] && number[3] == str[3]
&& number[4] == str[4] && number[5] == str[5] && number[6] == str[6] && number[7] == str[7]
&& number[8] == str[8] && number[9] == str[9] && number[10] == str[10] && number[11] == str[11])
{
gsm.println("ATH");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Incomming call");
lcd.setCursor(0, 1);
lcd.print("Number Verified.");
delay(2000);
if (EEPROM.read(address) == 0)
{
EEPROM.write(address, 1);
}
else if (EEPROM.read(address) == 1)
{
EEPROM.write(address, 0);
}
resetFunc();
}
if (!(number[0] == str[0] && number[1] == str[1] && number[2] == str[2] && number[3] == str[3]
&& number[4] == str[4] && number[5] == str[5] && number[6] == str[6] && number[7] == str[7]
&& number[8] == str[8] && number[9] == str[9] && number[10] == str[10] && number[11] == str[11]))
{
gsm.println("ATH");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Unknown number");
lcd.setCursor(0, 1);
lcd.print("Call Rejected.");
wr_call_val = 1;
EEPROM.write(wr_call_add, wr_call_val);
delay(2000);
resetFunc();
}
}
if (EEPROM.read(address) == 0)
{
serialEvent();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Standby");
lcd.setCursor(0, 1);
lcd.print("Status: OFF");
delay(1000);
}
else if (EEPROM.read(address) == 1)
{
lcd.setCursor(0, 0);
lcd.print("STATUS: ON");
lcd.setCursor(0, 1);
lcd.print("----------------");
}
}
void gsm_init()
{
lcd.print("System booting....");
lcd.setCursor(0, 1);
lcd.print("initiating......");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Checking Module");
lcd.setCursor(0, 1);
lcd.print("Connectivity....");
while (at_flag)
{
gsm.println("AT");
while (gsm.available() > 0)
{
if (gsm.find("OK"))
at_flag = 0;
}
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module");
lcd.setCursor(0, 1);
lcd.print("Connection: OK");
delay(1500);
eeprom_test();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System is Ready");
lcd.setCursor(0, 1);
lcd.print("----------------");
delay(1500);
}
void serialEvent()
{
while (gsm.available())
{
char read_char = gsm.read();
string += read_char;
i++;
if (string[i - 4] == 'R' && string[i - 3] == 'I' && string[i - 2] == 'N' && string[i - 1] == 'G' )
{
ring = 1;
}
}
}
void output_begin()
{
digitalWrite(output, HIGH);
if (EEPROM.read(wr_call_add) == 0)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sending SMS");
lcd.setCursor(0, 1);
lcd.print("Acknowledgement.");
delay(1000);
gsm.println("AT+CMGF=1");
delay(500);
gsm.print("AT+CMGS=");
gsm.print("\"");
gsm.print(str);
gsm.println("\"");
delay(1000);
gsm.println("Motor is ON.");
delay(100);
gsm.println((char)26);
}
if (EEPROM.read(wr_call_add) == 1)
{
wr_call_val = 0;
EEPROM.write(wr_call_add, wr_call_val);
}
lcd.clear();
}
void eeprom_test()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Testing EEPROM");
lcd.setCursor(0, 1);
lcd.print("Memory.");
delay(1500);
eeprom_tst = EEPROM.read(address);
eeprom_tst_ack = EEPROM.read(wr_call_add);
EEPROM.write(address, tst_var);
EEPROM.write(wr_call_add, wr_call_tst);
if (EEPROM.read(address) == tst_var && EEPROM.read(wr_call_add) == wr_call_tst)
{
EEPROM.write(address, eeprom_tst);
EEPROM.write(wr_call_add, eeprom_tst_ack);
if (EEPROM.read(address) != eeprom_tst || EEPROM.read(wr_call_add) != eeprom_tst_ack)
{
digitalWrite(output, LOW);
eeprom_dead_val = 1;
EEPROM.write(eeprom_dead, eeprom_dead_val);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EEPROM Test is");
lcd.setCursor(0, 1);
lcd.print("Unsuccessful.");
delay(1500);
eeprom_sms();
}
else if (EEPROM.read(address) == eeprom_tst && EEPROM.read(wr_call_add) == eeprom_tst_ack)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EEPROM Test is");
lcd.setCursor(0, 1);
lcd.print("Successful.");
delay(1500);
}
}
else if (EEPROM.read(address) != tst_var || EEPROM.read(wr_call_add) != wr_call_tst)
{
digitalWrite(output, LOW);
eeprom_dead_val = 1;
EEPROM.write(eeprom_dead, eeprom_dead_val);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EEPROM Test is");
lcd.setCursor(0, 1);
lcd.print("Unsuccessful.");
delay(1500);
eeprom_sms();
}
}
void eeprom_sms()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sending SMS");
lcd.setCursor(0, 1);
lcd.print("Acknowledgement");
delay(1000);
gsm.println("AT+CMGF=1");
delay(500);
gsm.print("AT+CMGS=");
gsm.print("\"");
gsm.print(str);
gsm.println("\"");
delay(1000);
gsm.println("EEPROM error. System disabled. Please reload the code with new address.");
delay(100);
gsm.println((char)26);
while (true)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EEPROM Error.");
lcd.setCursor(0, 1);
lcd.print("System Disabled.");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reload the code");
lcd.setCursor(0, 1);
lcd.print("with new address");
delay(1500);
}
}
// ------------- Program Developed by R.GIRISH ---------- //
That concludes the program code.
Things you need to change in the code:
char str[] = "91xxxxxxxxxx";
You should replace the “xxxxxxxxxxx” with your 10 digit phone number before you upload the code. If you are outside India replace your country code “91” with your own country’s phone code.
The circuit is heavily depending on EEPROM for its operation. The Arduino needs to restart multiple times for an operation to complete and the only memory can stay even after power is disconnected or after the Arduino resetsis the EEPROM.
But the EEPROM have limited write cycles so there might be a chance for EEPROM failure which might bring the system to halt.
Fortunately, the proposed system is programmed to detect EEPROM failure and notify the user via SMS and via the LCD display.
If such failure happens, the user can reprogram the Arduino with ease, just follow the steps below:
// ----------- ----------- //
int address = 0; // <<<<<<< Change address = 10 in case of EEPROM failure.
int wr_call_add = 1; // <<<<<<<< Change wr_call_add = 11 in case of EEPROM failure.
int f_address = 2; // <<<<<<<<< Chnage f_address = 12 in case of EEPROM failure.
int eeprom_dead = 3; // <<<<<<<<<< Change eeprom_dead = 13 inc case of EEPROM failure.
// ----------- ----------- //
Just replace the values 0, 1 ,2 and 3 with 10, 11, 12and 13 as mentioned above. In case of another failure after prolong usage of the system; replace the values with20, 21, 22 and 23.
When you change the above values with new value, we are using different set of EEPROM cells which might work for long time before its failure.
How likely EEPROM error can occur?
According to the ATmega328P data sheet, the claimed write cycles is 1,00,000 (one lakh) per cell, now assuming we turn on and off the system 10 times a day. 10 writes x 365 days = 3650 per year. 1,00,000 / 3650 = 27.39 years.
So we can say the EEPROM might not fail for at-least 10 years. However the mileage can varybut,you know how to fix in case of EEPROM failure.
How to Use
Let’s see how to use the system:
• Turn on the system; the Arduino will self-diagnose the circuit (which can be witnessed via LCD display) and sends an SMS saying “Motor OFF, System is ready”. Only then you can make call to the GSM module.
• Now, make a call to the GSM module from the mobile number which you entered in the program code.
• The relay turns ON and returns with an SMS acknowledgement saying “Motor is ON”.
• Now make another call it will de-energize the relay and returns with acknowledgement SMS saying “Motor is OFF / System is ready”.
• After making a call to the GSM module, Arduino automatically hang the call after a couple of rings.
• If you hear the voice info “The subscriber is switched OFF” after a call, there might be a power outage.
• If you hear anything per-recorded voice info related to network issue, the call might not reach the GSM module and will not trigger the relay.
• If you get “Motor is ON”acknowledgement SMSfor the second time after sometime you turned on the motor pump, you can assume the system and the motor just resumed after a power outage. Same applies,if you get “Motor is OFF / System ready” acknowledgement for the seconds time.
Author’s Prototype:
Part List:
• Arduino board (any model)
• GSM Module: SIM 900 / SIM 800
• BC548 Transistor
• 4.7 kilo ohm resistor
• 9V relay
• I2C LCD adapter module
• 16 x 2 LCD Module
• Diode 1N4007
• Valid SIM card with SMS functionality.
Do you like this project? Have any questions regarding this project? Drop your questions at comment section; you might receive a quick reply.