All About Water Systems (Ultrasonic + WaterFlow + Rain Sensors)


About This Project

Sometimes when I take a bath, the water stops. I checked that the water tank is empty and I have to call the water engineer to fix the water. I wish I could know the water problem earlier so when I know Cayenne I have an idea to make My Water System connected to my Mobile Device.

My current water system has 2 water tanks. The water from the underground flows into Blue Tanks using Grundfos pump, it’s filtered with sands and then go thru the Orange Tanks. Orange Tanks distribute the water using a small pump to home.

Sometimes the water from the ground is not flowing into the Blue Tank so I need the water flow sensor so we know when the Grundfos Pump starts flowing the water or not. If the water flows sensor slower than usually it means either I need to tweak the ‘pipe button’ or fix the underground pipe.

For the Orange Tank, sometimes I have to know if water flowing into Orange Tanks or not. If the water flows slower (or even stops) than usually, it means it’s time to clean up the water filter.

What’s Connected

  • Arduino Uno WIFI Developer Editions
  • Arduino Ethernet Shield W5500 (I know it’s ridiculous to have an ethernet over Uno WIFI, but because until now I cannot connect UNO Wifi to Cayenne, so I decided to buy W5500 Maybe someday I will remove the ethernet shield if Uno WIFI can connect to cayenne). You can check the thread here Please make support for Arudino Uno WiFi
  • 2 Pcs Ultrasonic HC-SR04
  • 2 Pcs Water Flow Sensors
  • 2 Pcs Arduino Relay
  • 1 Contactor Schneider LC1D09M7 220V for Grundfos Pump
  • 1 MY2 AC 220V/240V - 5A DPDT Electromagnetic Power Control Relay OMRON
  • 1 Rain Sensors (This is Bonus because in the Future I want to develop the system if Rain comes I want to all windows closed automatically)

Arduino Pin

D2 water flow sensor blue tank *
D3 water flow sensor orange tank *
D4 ultrasonic blue tank - echo
D5 ultrasonic blue tank - trigger
D6 ultrasonic orange tank - echo
D7 ultrasonic orange tank - trigger
D8 relay blue tank
D9 relay orange tank
A0 rain sensor

*. Note: WARNING! You have to put the water flow sensor to pin D1 and D2 ONLY because the water flow sensor need to use interrupts and for Arduino UNO it’s only available on pin D1 and D2 (

Triggers & Alerts

  • If Orange Tank bellow 75% Turn on Blue Switch (Grundfos Pump)
  • If Orange Tanks above 95% Tun off Blue Switch
  • If Blue Tanks above 95% Turn off Blue Switch
  • If Orange Tanks bellow 50% Email Alert (Something problem in the water systems)


  • Turn on Blue Switch (Grundfos Pum) at 5 am - 6 am (the lowest electrical use in My Home)

Dashboard Screenshots

Web Dashboard:

Mobile Dashboard:



Water Flow for Blue Tanks in L/minute:

Rain Sensor in %:
0% means not raining at all
100% means full flood, please prepare your boat, because the flood is already reach the top of the roof T_T

Photos of the Project

(Take some pictures of your project living in the wild!)


Ultrasonic Placement:

Whole System with Tanks:


//Remove This Someday when UnoWifiDev can connect to Cayenne (Can't Wait That Time Comes ^^)
//#include <UnoWiFiDevEd.h>

//#define CAYENNE_DEBUG         // Uncomment to show debug messages
//#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneEthernetW5500.h>

// Cayenne authentication token. This should be obtained from the Cayenne Dashboard.
char token[] = "XXXXXXXX";

// Water Flow --> Only Works ON Pin 2 and Pin 3 for Uno, check

int flowPin = 2;    //This is the input pin on the Arduino, Only Can be setup in Port 2 and 3
int flowPin2 = 3;
double flowRate;    //This is the value we intend to calculate. 
double flowRate2;
volatile int count;    //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.  
volatile int count2;
unsigned int getcount; //Getcount from count for flowRate
unsigned int getcount2;     

// Rain Sensor
float rain_level;
int rain_percentage;
int rain_bottom = 1022; 
int rain_top = 2;
int rain_distance =  rain_bottom - rain_top;
const int rainPin=A0; 
#define VIRTUAL_RAIN V10

// Ultrasonic
const int echoPin = 4; // Echo Pin 
const int trigPin = 5; // Trigger Pin 
float water_level;
float water_percentage;
int water_bottom = 42; 
int water_top = 32;
int water_distance = water_bottom - water_top;

const int echoPin2 = 6; // Echo Pin 
const int trigPin2 = 7; // Trigger Pin
float water_level2;
float water_percentage2;
int water_bottom2 = 75; 
int water_top2 = 19;
int water_distance2 = water_bottom2- water_top2;

void setup()

  // Water Flow
  pinMode(flowPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(flowPin), Flow, RISING);  

  pinMode(flowPin2, INPUT);
  attachInterrupt(digitalPinToInterrupt(flowPin2), Flow2, RISING);  

  // Ultrasonic 
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);  

  pinMode(trigPin2, OUTPUT);
  pinMode(echoPin2, INPUT);   

  // Rain
  pinMode(rainPin, INPUT);

void loop()

  // Water Flow
  // Ultrasonic

  // Rain
  rain_level = analogRead(rainPin);
  rain_percentage = 100 * ((rain_distance - rain_level)/rain_distance);

// Water Flow
void Flow()
   count++; //Every time this function is called, increment "count" by 1

void Flow2()
   count2++; //Every time this function is called, increment "count" by 1

static unsigned long lastSecond;
void getWaterFlow()
  if (micros() - lastSecond >= 1000000L)
	lastSecond += 1000000;

	noInterrupts(); //Disable the interrupts on the Arduino
	  getcount = count;
	  getcount2 = count2;
	  count = 0;      // Reset the counter so we start counting from 0 again
	  count2 = 0;       
	interrupts();   //Enables interrupts on the Arduino

	//Start the math for Blue Tank
	flowRate = (getcount * 2.25);        //Take counted pulses in the last second and multiply by 2.25mL 
	flowRate = flowRate * 60;         //Convert seconds to minutes, giving you mL / Minute
	flowRate = flowRate / 1000;       //Convert mL to Liters, giving you Liters / Minute
	//Start the math for Orange Tank
	flowRate2 = (getcount2 * 2.25);        //Take counted pulses in the last second and multiply by 2.25mL 
	flowRate2 = flowRate2 * 60;         //Convert seconds to minutes, giving you mL / Minute
	flowRate2 = flowRate2 / 1000;       //Convert mL to Liters, giving you Liters / Minute
	//Serial.println(flowRate);         //Print the variable flowRate to Serial  
	Cayenne.virtualWrite(VIRTUAL_PIN_WATERFLOW_1, flowRate);
	//Serial.println(flowRate);         //Print the variable flowRate to Serial  
	Cayenne.virtualWrite(VIRTUAL_PIN_WATERFLOW_2, flowRate2);  

// Ultrasonic 
float duration;
long HR_dist = 0; // Calculated Distance
unsigned long previousMillisUltraSonic = 0;

void getDistance(){ 
  unsigned long currentMillisUltraSonic = millis();
  // Check sensor data every 250 milliseconds
  if (currentMillisUltraSonic - previousMillisUltraSonic >= 5000) {  
	digitalWrite(trigPin, LOW); 
	digitalWrite(trigPin, HIGH);
	digitalWrite(trigPin, LOW);
	duration = pulseIn(echoPin, HIGH);
	duration = duration/58.2;
	Cayenne.virtualWrite(VIRTUAL_PIN_ULTRASONIC_1, duration);
	water_percentage = (100 * (water_top + water_distance - duration)) / water_distance;
	Cayenne.virtualWrite(VIRTUAL_PIN_ULTRASONIC_PERCENT_1, water_percentage);

	digitalWrite(trigPin2, LOW); 
	digitalWrite(trigPin2, HIGH);
	digitalWrite(trigPin2, LOW);
	duration = pulseIn(echoPin2, HIGH);
	duration = duration/58.2;
	Cayenne.virtualWrite(VIRTUAL_PIN_ULTRASONIC_2, duration);

	water_percentage2 = (100 * (water_top2 + water_distance2 - duration)) / water_distance2;
	Cayenne.virtualWrite(VIRTUAL_PIN_ULTRASONIC_PERCENT_2, water_percentage2);
	previousMillisUltraSonic = currentMillisUltraSonic;

// Rain
  Cayenne.virtualWrite(VIRTUAL_RAIN, rain_percentage);


The Judges Have Spoken! ~CONTEST RESULTS~

Great project! But I couldn’t understand what are the HC-SR04 for. They measure the current tank water level?


Yes. absolutely. You can see in the dashboard there is measure distance from ultrasonic. Each tank has 1 ultrasonic, because I put ultrasonic on the top of the tank, I need to convert it so it can be easily read with percentage instead of distance. I attached the widget percentage on the bottom of the dashboard so my wife can easily understand. :grinning: