Back to PortfolioRobotics

GSM Smart Irrigation & Automated Flood Control System

Friday, August 28, 2026

Share:
GSM Smart Irrigation & Automated Flood Control System

An automated agricultural irrigation and telemetry platform designed to optimize water usage and protect crops from inundation. Powered by an Arduino microcontroller and a SIM808 GSM/GPRS module, the system enables two-way remote SMS control, real-time ultrasonic water level profiling, automated pump cutoff, and instant flood mitigation with dedicated drainage actuation.

Key Technical Features

  • Bidirectional Cellular Control: Operates over cellular networks using AT commands via the SIM808 module, enabling farmers to trigger irrigation, stop pumps, or fetch real-time telemetry from any standard mobile phone via SMS.
  • Closed-Loop Ultrasonic Level Sensing: Uses an HC-SR04 ultrasonic transducer to continuously calculate water depth and volume percentages, automatically stopping the main pump when optimal saturation is reached to prevent water waste.
  • Autonomous Flood Detection & Drainage: Integrates a ground moisture/flood sensor that immediately activates a high-flow secondary drainage pump upon detecting field inundation while dispatching urgent SMS alerts to the operator.
  • Live Local Telemetry Display: A 16x2 liquid crystal display with an I2C backpack provides instant local feedback on pump operating state, active runtime, flood warnings, and reservoir capacity percentages.
  • Isolated High-Current Actuation: Employs an optocoupled multi-channel relay module to switch high-draw 12V DC diaphragm pumps safely without introducing voltage sags or inductive flyback spikes to the MCU.

Hardware Architecture

Core Components

  • Microcontroller: Arduino Uno (ATmega328P) running the master state and automation loop.
  • Cellular Transceiver: DFRobot SIM808 GSM/GPRS/GPS module with dedicated SIM card integration.
  • Level Sensor: HC-SR04 Ultrasonic Distance Sensor mounted over the water basin.
  • Flood Sensor: Resistive soil moisture / immersion detection probe placed at critical field elevation.
  • Actuation System: Dual 12V high-pressure DC diaphragm water pumps (Main Supply Pump & Emergency Drain Pump).
  • Driver Interface: Optocoupled 5V relay module with active-low switching logic.
  • Display Interface: 16x2 Character LCD with PCF8574 I2C expander (Address 0x27).
  • Power Supplies: Dual 12V DC power adapters with step-down regulation for logic and pump rails.

Pin Mapping

  • Digital Pin 10 / Digital Pin 11: SIM808 TX / RX (SoftwareSerial)
  • Digital Pin 7: Ultrasonic TRIG
  • Digital Pin 8: Ultrasonic ECHO
  • Digital Pin 13: Main Irrigation Pump Relay (IN1)
  • Digital Pin 12: Emergency Drainage Pump Relay (IN2)
  • Analog Pin A0: Soil / Flood Sensor Digital Input
  • Analog Pin A4 / Analog Pin A5: 16x2 LCD SDA / SCL (I2C Bus)

Control Logic & SMS Commands

Supported SMS Commands

  • pump on: Energizes the main irrigation pump, starts runtime tracking, and dispatches a confirmation SMS.
  • pump off: De-energizes the main irrigation pump and returns a shutdown acknowledgement SMS.
  • pump status: Reads current ultrasonic depth, evaluates active run duration (in minutes), and replies with a complete telemetry report.

Water Level Calculation

Distance measurements are mapped inversely to derive the container fill percentage:

$$\text{Level \%} = \left( \frac{\text{Max Level} - \text{Current Distance}}{\text{Max Level} - \text{Min Level}} \right) \times 100$$

Firmware Implementation

The firmware polls for incoming SMS messages via SoftwareSerial, handles non-blocking ping calculations for water levels, and executes immediate emergency overrides whenever flood conditions are sensed.

cpp
1#include <DFRobot_SIM808.h>
2#include <SoftwareSerial.h>
3#include <Wire.h>
4#include <LiquidCrystal_I2C.h>
5
6// Define pins for SIM808
7#define PIN_TX 10
8#define PIN_RX 11
9
10// Define pins for Ultrasonic Sensor
11#define TRIG_PIN 7
12#define ECHO_PIN 8
13
14// Define pins for Pumps and Soil Sensor
15#define MAIN_PUMP_PIN 13
16#define DRAIN_PUMP_PIN 12
17#define SOIL_SENSOR_PIN A0
18
19// Define constants
20#define WATER_LEVEL_THRESHOLD 5 // Desired water level in cm
21#define PHONE_NUMBER "01406645788"
22#define MESSAGE_MAIN_ON "Main Pump is ON"
23#define MESSAGE_MAIN_OFF "Main Pump is OFF"
24#define MESSAGE_LEVEL_REACHED "Water level reached"
25#define MESSAGE_FLOOD "Flood detected! Drain Pump is ON"
26
27// Initialize SIM808, LCD, and serial communication
28SoftwareSerial mySerial(PIN_TX, PIN_RX);
29DFRobot_SIM808 sim808(&mySerial);
30LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C LCD with address 0x27
31
32// Buffers and variables
33char message[160];
34char phone[16];
35char datetime[24];
36String rmsg;
37
38// Pump and flood status
39unsigned long mainPumpStartTime = 0;
40bool mainPumpIsOn = false;
41bool floodDetected = false;
42
43void setup() {
44 pinMode(MAIN_PUMP_PIN, OUTPUT);
45 pinMode(DRAIN_PUMP_PIN, OUTPUT);
46 pinMode(TRIG_PIN, OUTPUT);
47 pinMode(ECHO_PIN, INPUT);
48 pinMode(SOIL_SENSOR_PIN, INPUT);
49
50 // Initial state of pumps (relay logic for pulled-up relays)
51 digitalWrite(MAIN_PUMP_PIN, HIGH); // OFF
52 digitalWrite(DRAIN_PUMP_PIN, HIGH); // OFF
53
54 mySerial.begin(9600);
55 Serial.begin(9600);
56
57 // Initialize LCD
58 lcd.begin();
59 lcd.backlight();
60 lcd.print("System Starting...");
61 delay(2000);
62
63 // Initialize SIM808 module
64 lcd.clear();
65 lcd.print("Initializing GSM...");
66 while (!sim808.init()) {
67 lcd.setCursor(0, 1);
68 lcd.print("Retrying...");
69 delay(1000);
70 }
71 lcd.clear();
72 lcd.print("GSM Ready");
73 delay(1000);
74}
75
76void loop() {
77 Read_SMS();
78
79 if (mainPumpIsOn) {
80 float waterLevel = measureWaterLevel();
81 lcd.clear();
82 lcd.setCursor(0, 0);
83 lcd.print("Main Pump: ON ");
84 lcd.setCursor(0, 1);
85 lcd.print("Level: ");
86 lcd.print(11 - waterLevel);
87 lcd.print(" cm");
88
89 if (waterLevel <= WATER_LEVEL_THRESHOLD) {
90 sim808.sendSMS(PHONE_NUMBER, MESSAGE_LEVEL_REACHED);
91 turnOffMainPump();
92 }
93 } else if (floodDetected) {
94 lcd.clear();
95 lcd.setCursor(0, 0);
96 lcd.print("Flood Detected!");
97 lcd.setCursor(0, 1);
98 lcd.print("Drain Pump ON ");
99 } else {
100 float waterLevel = measureWaterLevel();
101 int waterLevelPercent = calculateWaterLevelPercent(waterLevel);
102 lcd.clear();
103
104 lcd.setCursor(0, 0);
105 lcd.print("Main Pump: OFF");
106 lcd.setCursor(0, 1);
107 lcd.print("Level: ");
108 lcd.print(waterLevelPercent);
109 lcd.print("% "); // Overwrite remaining characters
110 }
111
112 checkFlood();
113 delay(2000);
114}
115
116void Read_SMS() {
117 int messageIndex = sim808.isSMSunread();
118
119 if (messageIndex > 0) {
120 sim808.readSMS(messageIndex, message, 160, phone, datetime);
121 rmsg = String(message);
122 rmsg.trim();
123
124 if (rmsg == "pump on") {
125 turnOnMainPump();
126 } else if (rmsg == "pump off") {
127 turnOffMainPump();
128 } else if (rmsg == "pump status") {
129 sendPumpStatus();
130 }
131
132 sim808.deleteSMS(messageIndex);
133 }
134}
135
136void turnOnMainPump() {
137 digitalWrite(MAIN_PUMP_PIN, LOW); // Active-low relay trigger
138 mainPumpIsOn = true;
139 mainPumpStartTime = millis();
140 sim808.sendSMS(PHONE_NUMBER, MESSAGE_MAIN_ON);
141}
142
143void turnOffMainPump() {
144 digitalWrite(MAIN_PUMP_PIN, HIGH);
145 mainPumpIsOn = false;
146 sim808.sendSMS(PHONE_NUMBER, MESSAGE_MAIN_OFF);
147}
148
149void turnOnDrainPump() {
150 digitalWrite(DRAIN_PUMP_PIN, LOW);
151 sim808.sendSMS(PHONE_NUMBER, MESSAGE_FLOOD);
152}
153
154void turnOffDrainPump() {
155 digitalWrite(DRAIN_PUMP_PIN, HIGH);
156}
157
158void sendPumpStatus() {
159 float waterLevel = measureWaterLevel();
160 String mainStatus = mainPumpIsOn ? "ON" : "OFF";
161 int pumpDuration = mainPumpIsOn ? (millis() - mainPumpStartTime) / 60000 : 0;
162 String message = "Main Pump: " + mainStatus + ", Level: " + String(waterLevel) + " cm, ON Time: " + String(pumpDuration) + " min";
163
164 sim808.sendSMS(PHONE_NUMBER, message.c_str());
165}
166
167float measureWaterLevel() {
168 digitalWrite(TRIG_PIN, LOW);
169 delayMicroseconds(2);
170 digitalWrite(TRIG_PIN, HIGH);
171 delayMicroseconds(10);
172 digitalWrite(TRIG_PIN, LOW);
173
174 long duration = pulseIn(ECHO_PIN, HIGH);
175 float distance = duration * 0.034 / 2.0;
176 return distance;
177}
178
179void checkFlood() {
180 int soilValue = digitalRead(SOIL_SENSOR_PIN);
181 if (soilValue == 0 && !floodDetected) {
182 floodDetected = true;
183 turnOnDrainPump();
184 lcd.clear();
185 lcd.setCursor(0, 0);
186 lcd.print("Flood Detected!");
187 lcd.setCursor(0, 1);
188 lcd.print("Drain Pump ON ");
189 } else if (soilValue == 1 && floodDetected) {
190 floodDetected = false;
191 lcd.clear();
192 turnOffDrainPump();
193 lcd.setCursor(0, 0);
194 lcd.print("Flood Cleared ");
195 lcd.setCursor(0, 1);
196 lcd.print("Drain Pump OFF");
197 sim808.sendSMS(PHONE_NUMBER, "Flood cleared! Drain pump is OFF.");
198 }
199}
200
201int calculateWaterLevelPercent(float currentLevel) {
202 float maxLevel = 9.0; // Empty distance (0%)
203 float minLevel = 6.0; // Full distance (100%)
204
205 float percent = ((maxLevel - currentLevel) / (maxLevel - minLevel)) * 100.0;
206
207 if (percent < 0) percent = 0;
208 if (percent > 100) percent = 100;
209
210 return (int)percent;
211}