In this post I will show how to construct a SMS based water pump controller with automatic shutdown of pump when no water flow through the pump is detected. We will also construct another much simpler automatic dry run preventer circuit without GSM in the next half of the article.
What is Dry Run in Motors
We have already discussed on GSM based pump controller on this website check it out if haven’t yet. Here we are adding an additional feature on existing design, which will prevent the motor from dry running.
Dry running means running the water pump without liquid flow. The consequence can be serviceable damage to unserviceable damage depending on how long the motor was running without pumping the water and the quality of the water pump.
Yes, the water pumps are not cheap and if you are an agriculturist who irrigate the field every day, then a small issue with your water pump can land you in economic loss.
Servicing the pump may take some time and money, so it is better to follow the famous slogan “prevention is better than cure”.
Motor dry run is a very common problem, when there is not enough water to flow through the pump, over heating of mechanical components as well as electrical components will occur.
At a point the mechanical components will start to melt and also may cause short circuit.
Such disaster may be prevented using the circuit, proposed in this project.
To detect the flow of water, we are utilizing YF-S201 water flow sensor. When no water flow is detected by the sensor, it cuts off the power supply to water pump and send an SMS acknowledgement to the recipient about the dry run shut off.
With this GSM based control you can turn on and off the pump and also the circuit acknowledges about the pump dry run issue.
Circuit for SMS based pump control:

The circuit consists of AC to DC converter using 9V transformer, bridge rectifier a smoothing capacitor of 1000 uF and a LM7809 9V regulator. Two DC jacks are provided for powering Arduino board and SIM 800 / SIM 900 GSM module.
Never power the GSM module with 5V pin of Arduino to 5V pin of GSM module as the Arduino board cannot provide enough current.
The connection between Arduino and GSM module as follows:
Arduino TX ---------------------- RX SIM 800 / 900
Arduino RX --------------------- TX SIM 800 / 900
Arduino GND ------------------- GND SIM 800 / 900
The main supply is provided by the LM 7809 regulator.
The LED indicator will glow if the relay is activated and turns off when the relay is deactivated.
The diode IN4007 will absorbed high voltage spike which occurs while switching the relay on and off.
The water flow sensor is connected to A0 pin of Arduino, 5V and GND provided from Arduino board.
Program for GSM based design:
//-------------Program Developed By R.Girish (Optimized)-------------//
#include <SoftwareSerial.h>
// PIN CONFIGURATION
const int MOTOR_PIN = 8;
const int LED_PIN = 9;
const int INPUT_PIN = A0; // Water pulse/flow frequency feedback channel
// SoftwareSerial isolates the GSM modem from the main USB Serial port
// Connect RX Pin 10 to TX Pin of GSM Module
// Connect TX Pin 11 to RX Pin of GSM Module (via 5V to 3.3V voltage divider if needed)
SoftwareSerial gsmSerial(10, 11);
// Configurations
const String TARGET_PHONE = "+91xxxxxxxxxx"; // <--- Put your actual phone number here
// Memory Protection Caps
const int BUFFER_MAX = 20;
char cmdBuffer[BUFFER_MAX];
int bufferIndex = 0;
// Runtime State Tracker Flags
bool hasNewCommand = false;
bool isMotorActive = false;
unsigned long initializationTimer = 0;
bool isGsmReady = false;
void setup() {
Serial.begin(9600); // Native Hardware Serial dedicated to PC Debug Monitoring
gsmSerial.begin(9600); // Dedicated Isolated Software Serial for GSM Commands
pinMode(MOTOR_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(INPUT_PIN, INPUT);
digitalWrite(MOTOR_PIN, LOW);
digitalWrite(LED_PIN, LOW);
Serial.println(F("[SYSTEM]: Powering up... Initializing 60s GSM warm-up window."));
initializationTimer = millis();
}
void loop() {
// Non-blocking asynchronous delay logic handling GSM module startup
if (!isGsmReady) {
if (millis() - initializationTimer >= 60000UL) {
configureGsmModem();
isGsmReady = true;
}
return; // Postpone parsing routines until modem is warm
}
// 1. Process asynchronous serial reads
readGsmSerial();
// 2. Process incoming commands
if (hasNewCommand) {
evaluateCommand();
hasNewCommand = false; // Reset command trigger
}
// 3. Monitor active pump current for dry-run protection
if (isMotorActive) {
// Read pulse width intervals
unsigned long highPulseTime = pulseIn(INPUT_PIN, HIGH, 500000UL); // 500ms timeout
unsigned long lowPulseTime = pulseIn(INPUT_PIN, LOW, 500000UL);
unsigned long totalCyclePeriod = highPulseTime + lowPulseTime;
// An interval sum of 0 signifies complete loss of sensor signal
if (totalCyclePeriod == 0) {
executeDryRunTrip();
}
}
}
void readGsmSerial() {
while (gsmSerial.available()) {
char incomingChar = gsmSerial.read();
if (incomingChar == '/') {
// Start parsing or end parsing on the framing delimiter '/'
if (bufferIndex > 0) {
cmdBuffer[bufferIndex] = '\0'; // Properly terminate the string array
hasNewCommand = true;
break;
} else {
bufferIndex = 0; // Fresh command start detected, clear index pointers
}
}
else {
// Safely append characters while enforcing memory boundary limits
if (bufferIndex < (BUFFER_MAX - 1)) {
cmdBuffer[bufferIndex++] = incomingChar;
} else {
bufferIndex = 0; // Prevent overflow by dumping messy lines
}
}
}
}
void evaluateCommand() {
Serial.print(F("[RECEIVED CMD]: "));
Serial.println(cmdBuffer);
if (strncmp(cmdBuffer, "motor on", 8) == 0) {
digitalWrite(MOTOR_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
isMotorActive = true;
Serial.println(F("[STATE]: Motor Engaged."));
sendSmsNotification("Motor Activated Successfully.");
}
else if (strncmp(cmdBuffer, "motor off", 9) == 0) {
stopMotor();
Serial.println(F("[STATE]: Motor Manually Disengaged."));
sendSmsNotification("Motor Deactivated Manually.");
}
else if (strncmp(cmdBuffer, "test", 4) == 0) {
sendSmsNotification("System Status: Operational and Online.");
}
bufferIndex = 0; // Clear index for the next command cycle
}
void executeDryRunTrip() {
stopMotor();
Serial.println(F("[WARNING]: Critical Fault - Dry Run Detected! Shutting down system."));
sendSmsNotification("ALERT: Motor deactivated automatically due to dry run conditions!");
}
void stopMotor() {
digitalWrite(MOTOR_PIN, LOW);
digitalWrite(LED_PIN, LOW);
isMotorActive = false;
}
void configureGsmModem() {
Serial.println(F("[GSM]: Configuring hardware flags..."));
gsmSerial.println("AT+CNMI=2,2,0,0,0");
delay(1000);
gsmSerial.println("AT+CMGF=1");
delay(500);
sendSmsNotification("System is ready to receive commands.");
Serial.println(F("[GSM]: Setup complete. System online."));
}
void sendSmsNotification(String messageText) {
gsmSerial.print("AT+CMGS=\"");
gsmSerial.print(TARGET_PHONE);
gsmSerial.println("\"\r");
delay(1000);
gsmSerial.println(messageText);
delay(100);
gsmSerial.println((char)26); // ASCII control line terminator character: CTRL+Z
delay(1000);
}Here is the tested SMS while prototyping:

The following things we can observe from the screen shot:
· First the motor is turned on and the circuit acknowledged with a reply.
· The motor is deactivated and the circuit is acknowledged with a reply.
· Again the motor is activated and unplugged the sensor to simulate dry run situation, the circuit turns the pump off and replied with pump dry run acknowledgement.
· Finally a test SMS has sent and the circuit replied with “System is Working Fine”.
I would suggest installing the water flow sensor after couple of meters after the water pump.
That concludes the GSM based pump dry run preventer.
Now let’s take a look at simple water pump dry run preventer without GSM, this could be the easier of the two.
Circuit Diagram:

Nothing much about to explain here, just wire up as per the schematic. The power supply can be a 9V wall adapter with at-least 500 mA or the supply which illustrated in the GSM based controller schematic.
The push button is provided to turn the pump on and off.
Once you press the button to turn on the pump, the circuit waits till 20 seconds initially to detect the flow of water, during that time the push button is disabled for 20 seconds.
After the initial 20 seconds the push button is enabled and you may turn OFF the pump manually by pressing the push button again.
If water flow is detected the circuit keeps the pump ON after 20 seconds, otherwise the circuit cuts the power supply to the motor. Also the circuit can cut off the supply at any instant, if no water flow detected.
If the circuit shut off due to dry run, the LED blinks rapidly.
Program for simple pump dry run preventer:
//--------------------------Program Developed by R.GIRISH (Optimized)------------------------//
// Pin Configuration Constants
const int INPUT_PIN = A0; // Flow meter / pulse signal line
const int TEST_PIN = 6; // Mock pulse generator line
const int BUTTON_PIN = A1; // Pushbutton control toggle pin
const int LED_PIN = 8; // Status and fault indicator LED
const int MOTOR_PIN = 9; // Pump drive line output (Relay/MOSFET gate)
// System Runtime Tracking Flags
bool isMotorActive = false;
bool isSystemFaulted = false;
// Debounce & State Tracking Variables
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long DEBOUNCE_DELAY = 50; // 50ms button filtering
// Asynchronous Timing Trackers
unsigned long motorStartTime = 0;
const unsigned long PRIMING_BYPASS_TIME = 20000UL; // 20-second startup bypass
unsigned long lastBlinkTime = 0;
bool alertLedState = LOW;
void setup() {
Serial.begin(9600);
pinMode(INPUT_PIN, INPUT);
pinMode(TEST_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(MOTOR_PIN, OUTPUT);
// Set up pin A1 using internal pullup resistor for noise immunity
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Initialize safe dead-stop defaults
digitalWrite(MOTOR_PIN, LOW);
digitalWrite(LED_PIN, LOW);
analogWrite(TEST_PIN, 100); // Maintained from original setup spec
Serial.println(F("[SYSTEM]: System Initialized and Ready."));
}
void loop() {
// 1. Safe Non-Blocking Toggle Button State Scanner
checkButtonToggle();
// 2. Handle System Behavior Based on Fault State
if (isSystemFaulted) {
handleFaultBlink();
}
else if (isMotorActive) {
monitorDryRunSafety();
}
}
void checkButtonToggle() {
bool currentRead = digitalRead(BUTTON_PIN);
// Reset debounce timer if physical electrical state changes
if (currentRead != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
// If the button has been reliably pressed down (transitioned from HIGH to LOW)
if (currentRead == LOW && !isMotorActive) {
if (isSystemFaulted) {
// If system is locked up on a fault, pressing the button acts as a manual clearance reset
clearSystemFault();
} else {
startMotor();
}
delay(300); // Short preventative delay block to prevent immediate cycle double-triggers
}
else if (currentRead == LOW && isMotorActive) {
stopMotor();
Serial.println(F("[MANUAL]: User Request - Turning Motor OFF."));
delay(300);
}
}
lastButtonState = currentRead;
}
void startMotor() {
Serial.println(F("[SYSTEM]: Motor Activated. Initializing 20s Priming Window."));
digitalWrite(LED_PIN, HIGH);
digitalWrite(MOTOR_PIN, HIGH);
isMotorActive = true;
motorStartTime = millis(); // Save timestamp marks
}
void stopMotor() {
digitalWrite(MOTOR_PIN, LOW);
digitalWrite(LED_PIN, LOW);
isMotorActive = false;
}
void monitorDryRunSafety() {
// Only evaluate real-world fluid presence AFTER the 20-second priming window expires
if (millis() - motorStartTime >= PRIMING_BYPASS_TIME) {
// Read high and low pulse width durations (with a safety 500ms timeout window)
unsigned long pulseHigh = pulseIn(INPUT_PIN, HIGH, 500000UL);
unsigned long pulseLow = pulseIn(INPUT_PIN, LOW, 500000UL);
unsigned long totalPeriod = pulseHigh + pulseLow;
// Defensive check: split 0 parameters before calculating arithmetic divisions
if (totalPeriod == 0) {
triggerDryRunFault();
return;
}
float frequency = 1000000.0 / totalPeriod;
// Safety check for absolute zero fluid movement anomalies
if (isinf(frequency) || frequency <= 0.1) {
triggerDryRunFault();
}
}
}
void triggerDryRunFault() {
Serial.println(F("[CRITICAL ALERT]: Dry Run Condition Detected! Trip Triggered."));
stopMotor();
isSystemFaulted = true;
}
void clearSystemFault() {
Serial.println(F("[RESET]: Fault Reset Flag Processed. System back online."));
isSystemFaulted = false;
digitalWrite(LED_PIN, LOW);
}
void handleFaultBlink() {
// Asynchronous LED indicator alert routine (Zero processor delay freeze blocks)
if (millis() - lastBlinkTime >= 500) {
lastBlinkTime = millis();
alertLedState = !alertLedState;
digitalWrite(LED_PIN, alertLedState);
}
}
//--------------------------Program Developed by R.GIRISH------------------------//That concludes the both the designs.
If you have any specific questions regarding this SMS based pump controller with automatic dry run shut down circuit, please express in the comment section, you may receive a quick reply.



Comments
Hello Sir. I have a project: “INTELLIGENT GLASS SYSTEM FOR THE BLIND” I need a Camera to capture images, send them to a server and Optical Character Recognition (OCR) work to convert the text into audio feedback. The audio is then relayed back to the user, allowing them to ‘read’ text through sound via a speaker. All this should be done offline. I have found that at least no arduino is capable of such.
what should I do Sir?
Thank you.
Hello Jedidiah,
The idea looks very good and innovative, but it seems to be beyond the level of my expertise, I have no idea how to handle the server transmission and the related parameters.
i had connected all the connections but motor starts as soon as give the supply to ckt i (is the relay connections right i think it should to n/o)
please check it by swapping the relay contact, check it with a bulb first, if everything works then you can connect the actual load.
Hello Sir,
is there any other ways to check the pump is running in dry state or not. I heard that few industrial dry run sensor are actually calculating voltage difference or amp difference when pump is in normal vs in dry state.
Hi Madhav, Checking the amp difference is the best and the most reliable way according to me…another way is by monitoring motor temperature
Thanks for the replay Sir,
How can monitor the same, I mean is there any we can input the current amp feed to arduino and analysing it take action.
Thanks in advance .
Madhav, monitoring it through wireless method can be a lot complicated, however an arrangement can be made where the motor will be automatically switched OFF and an SMS sent to your mobile regarding the same..
i want to learn to code the arduino UNO board i recently purchased. this is some thing i want to do before i die. i am 80 years old. so if you can help u better hurry. many thanks in advance.
I wish I could teach you, however I am myself in the learning stages of Arduino so cannot provide much help, nevertheless If possible i’ll try to publish a related post which will help understanding Arduino easier for all the interested readers like you
much obliged. God Bless, Fali
Help me sir I want both sms and call control 3 phase water pump with automatic dry shut off I’m farmer I’m try to this project my own farm plzz sir help me
Hi Rushikesh, you can use the same circuit and code and build it for your 3 phase motor.
The only change you need to implement is:
Replace BC548 with a TIP122, and replace the single relay with three 30 amp relays in parallel (coils in parallel)…the 1N4007 can be a common diode for all the 3 coils in parallel.
After this you can wire the 3 separate contacts of the relay with the 3 wires of the 3 phase motor.
Alternatively you can replace the relay with a single TTTP relay or a triple throw triple contact relay (30 amp)
thank u for ur reply sir, but pls wot is d value of c1, c2, c3 d1, d2 in d above 555 voltage doubler if i want to use it to power 35v from 12v or 15v transformer.
you can use C1 = 0.1uF, C2, C3 = 100uF/25V, D1, D2 = 1N4007
pls sir can i power 35v dc from 15v or 12v transformer by using voltage doubler. and pls can u give me d circuit diagram of d voltage doubler i am suppose to use in dat situation. tnx
wireless, yes you can do that by using the circuit explained in the following links:
https://www.homemade-circuits.com/?s=voltage+doubler