GSM based Water Level Monitoring and Control using Arduino, Sim900A, and Ultrasonic Sensor
Table of Contents
GSM Based Water Level Monitoring:
GSM based Water Level Monitoring and Control using Arduino, Sim900A, and Ultrasonic Sensor- In today’s article, you will learn how to make GSM based Water Level Monitoring and control system using Arduino Nano, GSM SIM900A module, and HC-SR04 Ultrasonic Sensor.
By the way, I have written many articles related to the water level monitoring and control system, in which I have used different technologies to monitor water levels and control water pumps. For example,
Wireless Water level monitoring using Long-range LoRa transceiver modules, with the help of this project water level inside a tank can be monitored within a range of 5 Kilometers.
IoT based water level monitoring and control system using ESP32 WiFi + Bluetooth module, Waterproof ultrasonic Sensor, and the new Blynk V2.0. With the help of this water level monitoring system, you can monitor the water level inside a tank from anywhere in the world.
I also made a water level monitoring system using a Pressure Sensor and displayed the water level information on LEDs.
If you’re interested in exploring technologies beyond GSM, such as LoRa and IoT platforms, I highly recommend read my previous articles on the Water Level Monitoring and Control Systems.
Amazon Links:
Arduino Nano USB-C Type (Recommended)
*Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
Anyway, let’s get back to our project.
For the demonstration purposes, I am going to monitor the water level inside a bucket which you can think of as the water tank and you can think of this 110/220Vac Bulb as the water Pump.
The Ultrasonic sensor is right on top of the water tank. Everything is in place and it looks good; so let’s go ahead and power up the entire system.
As usual, I am using my designed Arduino and LoRa based development board, because I specially designed it for projects like these. I am not using a separate power supply for the GSM SIM900A module, because my board has a 5V and 3A power supply which is more than enough to power up the Arduino, GSM, and relays.
If you don’t want to make such a development board then you can make a dedicated 5V and 3A power supply.
When the 110/220Vac supply is connected never touch the relay contacts as it can be dangerous. So, as far as possible, wear protective gloves and perform such high voltage experiments in the presence of a companion or someone having basic knowledge of the electrical systems.
When the water level in the water tank drops below a certain level, the Arduino starts sending alert messages with the help of GSM module.
In the programming, I’ve utilized a timer to ensure that alert messages are generated every 2 minutes. Having an alert message every 2 minutes could indeed be quite annoying. However, it’s important to note that this time duration is adjustable, and I will explain how to modify it later in this article.
We have two options, we can turn ON the water pump automatically or we can do it manually. In my case, I don’t want the water pump to turn ON automatically. Anyway, let’s write a message to turn ON the water pump.
abc123 is a password to add a little bit of security so that nobody else can control the water pump, you can use any combination of letters, characters, and numbers. Then the word relay, and command on. The % signs are used to separate these parameters. I have already explained this in my GSM based Home automation project. Anyway, the message is ready and let’s send it to control the water pump.
You can see the bulb just turned ON which represents a water pump. Now, it will stay ON until the water tank is filled. I filled the Bucket and then the Light “Water Pump” automatically turned OFF.
I have also added another feature that is; you can check the water level inside a water tank at anytime, all you need is to write a message which consists of a password and the word level.
Anyway, before I send this message, first let’s remove some water. Now, let’s send the message and check the level.
This is pretty amazing; with this feature you will never run out of water because you can check the water level at anytime and you can turn ON the water pump whenever you want, you don’t need to wait for the water tank to get completely empty.
GSM based Water Level Monitoring, Circuit:
Connect the 5V TXD and RXD pins of the GSM SIM900A module to the Arduino digital pins D9 and D10. Connect the 5V and GND pins of the GSM module to the 5V and 3A power supply Vin and GND. The power supply 5V and GND are connected to the Arduino Vin and GND pins.
Connect the VCC and GND pins of the HC-SR04 Ultrasonic Sensor to the Arduino Vin and GND pins. Connect the Trigger and Echo pins of the Ultrasonic Sensor to the Arduino D2 and D3 pins respectively.
Connect the VCC and GND wires of the relay module to the 5V and GND. Connect the relay input pin to the Arduino digital pin D4. The Vin and Gnd wires should be connected to a 5V and 3A power supply.
You can follow this circuit diagram if you want to make your own 5V and 3A power supply. Now, let’s go ahead and take a look at the programming.
GSM based Water Level Monitoring, Programming:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
#include <SoftwareSerial.h> SoftwareSerial SIM900(9, 10); // TXpin=9 RXpin=10 #define trigPin 2 #define echoPin 3 #define relay 4 int distance; String passcode="abc123"; String incoming = ""; String textForSMS; // for the timer int minutes = 0; int seconds = 0; long int total_seconds = 0; int secflag = 0; int timer_started_flag = 0; // Tracks the time since last event fired unsigned long previousMillis=0; unsigned long int previoussecs = 0; unsigned long int currentsecs = 0; unsigned long currentMillis = 0; int interval= 1 ; // updated every 1 second int tsecs = 0; // flags boolean Zero_Level_Flag = false; void setup() { //initialize Serial Monitor Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(relay, OUTPUT); pinMode(echoPin, INPUT); SIM900.begin(9600); // original 19200 randomSeed(analogRead(0)); SIM900.print("AT+CMGF=1\r"); // set SMS mode to text delay(1000); SIM900.print("AT+CNMI=2,2,0,0,0\r"); // blurt out contents of new SMS upon receipt to the GSM shield's serial out delay(1000); SIM900.println("AT+CMGD=1,4"); // delete all SMS delay(5000); Serial.println("Ready..."); } void loop() { currentMillis = millis(); currentsecs = currentMillis / 1000; if ((unsigned long)(currentsecs - previoussecs) >= interval) { total_seconds = total_seconds + 1; previoussecs = currentsecs; if ( total_seconds >= 59 ) { minutes = minutes + 1; total_seconds = 0; } if ( minutes >= 2 ) { total_seconds = 0; minutes =0; Zero_Level_Flag = false; } // Serial.print("Minutes:"); // Serial.println(minutes); // Serial.println(); // Serial.print("Seconds:"); // Serial.println(total_seconds); } digitalWrite(trigPin, LOW); delayMicroseconds(5); // Trigger the sensor by setting the trigPin high for 10 microseconds: digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Read the echoPin. pulseIn() returns the duration (length of the pulse) in microseconds: int duration = pulseIn(echoPin, HIGH); // Calculate the distance: // distance = duration*0.034/2; distance = (duration/2) / 29.1; Serial.print("Distance: "); Serial.println(distance); // Print the distance on the Serial Monitor (Ctrl+Shift+M): /* * 44 is the distance of the water level from the ultrasonic sensor * when the tank is full. * 64 is the low limit of the water level from the ultrasonic sensor */ int waterLevelPer = map(distance,44,64, 100, 0); if(waterLevelPer <= 0) { waterLevelPer=0; } if (waterLevelPer >= 100) { waterLevelPer = 100; } if (waterLevelPer >= 90) { digitalWrite(relay,LOW); } Serial.print("Percentage: "); Serial.println(waterLevelPer); if ((waterLevelPer <= 20) && (Zero_Level_Flag == false)) { Zero_Level_Flag = true; textForSMS = "level: "; textForSMS = textForSMS + waterLevelPer; textForSMS = textForSMS + "%"; textForSMS = textForSMS + "\n"; sendSMS(textForSMS); //Serial.println(textForSMS); //Serial.println("message sent."); textForSMS = ""; delay(200); } if(SIM900.available() >0) { incoming=SIM900.readString(); //Serial.println(incoming); String fulldata = getValue(incoming, '%', 0); String password = getValue(incoming, '%', 1); //contains password String level= getValue(incoming, '%', 2); //contains motor type dc motor or servo motor String relaystate= getValue(incoming, '%', 3); //contains motor type dc motor or servo motor //Serial.print("value 1: "); //Serial.println(password); //Serial.print("value 2: "); //Serial.println(level); //Serial.print("value 3: "); //Serial.println(relaystate); if((password==passcode)&&(level=="level")) { textForSMS = "level: "; textForSMS = textForSMS + waterLevelPer; textForSMS = textForSMS + "%"; textForSMS = textForSMS + "\n"; sendSMS(textForSMS); //Serial.println(textForSMS); //Serial.println("message sent."); textForSMS = ""; delay(200); } else if((password==passcode)&&(level=="relay")&&(relaystate=="on")) { digitalWrite(relay,HIGH); delay(100); } else if((password==passcode)&&(level=="relay")&&(relaystate=="off")) { digitalWrite(relay,LOW); delay(100); } } } void sendSMS(String message) { SIM900.print("AT+CMGF=1\r"); // AT command to send SMS message delay(1000); SIM900.println("AT + CMGS = \"+923348912230\""); // recipient's mobile number, in international format delay(1000); SIM900.println(message); // message to send delay(1000); SIM900.println((char)26); // End AT command with a ^Z, ASCII code 26 delay(1000); SIM900.println(); delay(100); // give module time to send SMS } String getValue(String data, char separator, int index) { int found = 0; int strIndex[] = { 0, -1 }; int maxIndex = data.length() - 1; for (int i = 0; i <= maxIndex && found <= index; i++) { if (data.charAt(i) == separator || i == maxIndex) { found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; } |
About the code:
I started off by adding the SoftwareSerial.h header file. Using the SoftwareSerial we can define multiple serial ports. You know, in Arduino Uno and Arduino Nano we have only one serial port that is available on pins 0 and 1. As I want to use the Arduino’s default serial port for the debugging purposes; so that’s why I defined another serial port for the GSM SIM900A module.
1 |
SoftwareSerial SIM900(9, 10); |
Next, I defined pins for the Trigger, Echo, and Relay.
1 2 3 4 5 |
#define trigPin 2 #define echoPin 3 #define relay 4 |
I also defined some variables for storing the water level value, password, incoming message, and alert message.
1 2 3 4 5 6 7 |
int distance; String passcode="abc123"; String incoming = ""; String textForSMS; |
I also defined some variables for the timer.
1 2 3 4 5 6 7 |
int distance; String passcode="abc123"; String incoming = ""; String textForSMS; |
Code inside the setup() function is exactly the same as explained in my previous GSM based home automation project. So, let’s go to the loop() function.
Using the millis() function, we calculate the seconds and minutes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
currentMillis = millis(); currentsecs = currentMillis / 1000; if ((unsigned long)(currentsecs - previoussecs) >= interval) { total_seconds = total_seconds + 1; previoussecs = currentsecs; if ( total_seconds >= 59 ) { minutes = minutes + 1; total_seconds = 0; } if ( minutes >= 2 ) { total_seconds = 0; minutes =0; Zero_Level_Flag = false; } |
So, when the minutes are greater than or equal to 2, we set the Zero_Level_Flag to false which signals the Arduino to send an alert message. When the alert message is sent the Zero_Level_flag is again set to true, and this whole process starts again.
All the other instructions are from my GSM based home automation project, all these instructions are used to split the string message and store the corresponding values in variables. Then we use these different parameters for requesting the water level and for controlling the water pump. I highly recommend you guys should watch my video on the GSM based home automation project. Anyway, that’s all for now.