While energy prices are increasing every day, the prices of water are (still) moderate compared to gas and electricity. Nevertheless, there are good reasons to save on water usage, e.g. when you realise that while taking a shower a lot of hot water is used and it is costing energy to heat up the water. In other words: a lot of energy is washed away every day.
Although you can see the water usage on the meter itself, it does not tell you how much water is being used for taking a shower or flushing the toilet, or watering your plants in the garden.
On the internet you find several types of water meters for sale (at significant prices sometimes) and there are also some publications of DIY water meters. Those DIY designs give a good guidance for making one, but are always based on the particular knowledge, skills and available means of the designer.
This is why I started this project to make my own design and build a smart water meter myself, of course considering the solutions and information that have been published by others. Thanks to the open-source community.
The design described here is naturally also driven by my own available means and skills, but I hope it helps you to build your own version or that at least it inspires you to make your own design.
1.1 The designThe design of the Smart Water Meter is based on the following requirements:
- It should provide on-line data of the water usage in liter on a per minute basis and also the daily and total use
- The data should be made visible in graphs with a selectable timeline scaling and should be accessible with a PC/laptop, tablet or smart phone
- It should be able to measure the momentary water flow rate in Lit/min
- It should provide a water flow alarm while being away from home
- It should be packaged as a simple clip-on to the existing water meter not requiring any physical modification of the meter.
These requirements have been the basis for the development of the complete Smart Water Meter, resulting in the following hardware product:
The embedded software has been programmed with the ARDUINO IDE and flashed to the ESP32 microcontroller, built-in the above housing which is simply made as a clip-on to the existing water meter.
An essential element in this project is the use of BLYNK as IOT server.
With Blynk, the device is connected to the Internet and a web dashboard as well as a dashboard for use on a mobile phone is created. Thanks to that the Smart Water Meter can be monitored and from anywhere in the world.
An example of the resulting Blynk Dashboard on a PC/Laptop or tablet is shown below:
For use on a mobile phone the following dashboard was created:
On both types of dashboards, the instantaneous Waterflow can be observed in Liter/minute as well as the amount of water in liter as used sofar today:
An alarm can be generated, as a push notification on your tablet or mobile phone, in case you are not home and if there is a waterflow:
It is also possible to make automations in Blynk such as a warning when today’s water use exceeds the daily average (calculated by dividing the total yearly consumption by 365 minus holidays):
The existing Water meter used in my project is the SENSUS 620 model, as shown below:
The most significant characteristics of this model are:
- Smallest unit of measure is 1 liter (see little red circle)
- There is a metal plate on the liter indicator (1 revolution is 1 liter)
- There are 2 “stubs” on the transparent cover (blue arrows)
- Maximum flow 2.5m³ per hour (2500/60= 41, 6 Lit/min or 0, 6944 lit/sec)
The metal plate on the rotating dial is the most important item for this project, because it opens the possibility to use the following sensor in the design:
This is a sensor that is able to sense metal at proximities of max 8 mm from the top.
Its most important characteristics are:
- 3 wire connection (+ Power, - power or GND, data)
- Power supply: 5V DC (this is what I ordered, but received a 6V-36V model, which thankfully turned out to be working on 5V as well, so I could keep the electronics design simple and use a 5V phone charger as power supply)
- The data pin gives a signal, which is “High” when there is metal detected near the sensor and “Low” when not
- Diameter: 18 mm
- Thread (M18) length 45 mm
I build the sensor in a self-designed and 3D printed holder. The holder can be put on top of the “2 stubs” of the existing water meter. For initial experiments the sensor is connected to a breadboard set-up with a Mini ESP32 TTGO T7 V1.3.
One important aspect is the proper alignment of the sensor with the rotating metal plate. For this purpose, the holder was designed with a slot that enables positioning of the sensor within the holder. The sensor should not be precisely above the rotating plate for proper detection behaviour.
The hart of the sensor should be somewhat off-centred from the rotation axis of the liter-count dial:
This drawing in made in Fusion360 and forms the basis sketch for the sensor holder.
The 3D printed result of the design can be seen below:
To test the proper positioning, it is possible to connect the sensor to 5V DC and monitor if the red LED on top of the sensor blinks when the metal part of the liter dial is passing underneath.
2. ThingsThe picture below shows the items used for the Smart Water Meter:
Not visible is a 5V USB adapter with cable. The soldering board should be cut to fit inside the 3D printed housing.
3. Step 1: System DesignThe water meter device will be connected to the internet continuously via the on-board Wi-Fi functions of the Mini ESP32 microcontroller (MCU). For this reason, the use of batteries for this application is not a very practical solution. The power requirements of the sensor and the MCU are low and therefore the use of a 5V DC USB charger with 1A (maximum current) is more than sufficient. Using a simple USB power meter connected to the USB charger during testing showed currents below 10 mA in normal circumstances. During measurements and transmission of data streams via WiFi, there are short fluctuations between 20mA and max 50mA.
The main elements of the system are the ESP32 microcontroller (MCU), the proximity sensor and the 5V power supply.
A blue LED is used for indicating the Wi-Fi connection status with the nearest Access Point (AP). A red LED serves as power-on indicator and a yellow LED will indicate when the sensor is triggered.
All electronics except the 5V charger, will be build inside a 3D printed housing. The housing has an opening for connecting a micro-USB plug to the MCU for modifying the software if needed.
4. Step 2: Making the Smart Water Meter4.1 Things usedThe following materials are used for the smart water meter:
The electronic design is shown in the following circuit diagram:
The above diagram has been made using EasyEDA.
Note that the pin layout of the ESP32, as shown in above diagram is different from the reality. It has been modified to make the diagram more easy to comprehend. The real pin allocation is shown in below diagram:
Note that pin 27 is actually GPIO27 (and not GPIO17 as printed)
The breadboard set up used for testing and building the software with the ARDUINO IDE, is shown in the following picture:
A closer look at the mini ESP32:
Let’s have a closer look at the inductive proximity sensor LJ18A3-8ZBX (detecting metal or no) metal sensor in combination with the Optocoupler (PC817).
The relevant part of the circuit diagram is shown below.
If there is no metal detection, the data output of the sensor will be LOW , that means that inside the PCF817 optocoupler housing the IR diode will not be radiating and consequently the IR receiving “transistor” will not be conducting. Because GPIO 04 is programmed with a “pullup” resistor, GPIO 04 will be seen as HIGH by the firmware running on the ESP32 MCU.
When there is metal detection, the opposite process takes place. In other words when the dial in the water meter is rotating clockwise, GPIO 04 changes state from HIGH to LOW and after a short while back to HIGH.
The time duration between the two transitions can be measured with a specific Arduino code in microseconds. This time duration is dependent on the speed of rotation of the dial and is thus a measure for the momentary waterflow (flow rate).
This property can be used to determine the instantaneous waterflow in Liter/Second or Liter/Minute!
Of course, at the same time the used amount of water can be measured (in Liter) by counting the number of times that GPIO 04 goes from HIGH to LOW.
There is one problem with this method and that is when the dial stops rotating with the metal plate underneath the sensor, then GPIO04 remains LOW.
Luckily, this can be solved in the software.
Also, the optocoupler helps to solve the problem of the 5V high level at the data output of the sensor. When connected directly to a ESP32 GPIO pin 5V would fry that GPIO immediately. The optocoupler brings down the 5V level to 3.3 V which can be handled by a GPIO pin (programmed with an internal PULLUP).
Another aspect to note is the 10uF capacitor between the RST pin and GND. This enables the boot process when flashing new code from the Arduino IDE on your PC to the ESP32 (without the need to press its on-board boot-button).
4.3 Mechanical and electrical assemblyThe solderable prototype board (5 * 7 cm) is made to fit inside the housing:
The components from the breadboard are transferred onto a small (5 * 7 cm) single sided prototype board, which is then mounted inside the 3D printed housing.
The housing and the sensor holder are then fixed together with 2 screws and positioned on the 2 stubs of the existing water meter.
Key element for this project is the use of BLYNK as IOT server.
With Blynk you can connect your devices to the Internet and create mobile and web dashboards to control your devices from anywhere in the world.
A device is usually a microcontroller (MCU) like ESP32, Arduino, etc. They can connect to the Internet using Wi-Fi. You can attach sensors and actuators to this MCU and monitor or control them remotely with Blynk.
If you are new to Blynk you will need to create a Blynk account to use it for this project. The free Blynk account enables you to use its basic features and a maximum of 2 devices on-line (which is good enough for the application in this project).
In fact, you can do amazing things with Blynk, it is well documented and there is even an example code generator that helps you to make a quick start.
In order to get a free account, go to: https://blynk.io/ and follow the steps for a free account. After becoming an experienced user, it is possible to get a lot of extra capabilities for a reasonable fee.
Then go to: https://docs.blynk.io/en/getting-started/what-do-i-need-to-blynk to make a quick start. Follow the steps as directed.
Hereafter, you should have a bit more understanding of the relationship between templates, devices, data streams, and widgets on the dashboard.
Copy the Template ID, Device Name en Auth Token and store the data in a temporary TXT file, save this file for later use.
Now open the Arduino sketch as provided for this project and fill in the first 3 lines of code, with the date obtained from Blynk, when creating your own template:
#define BLYNK_TEMPLATE_ID "Own TMPL-code" // put here your own template code as obtained from BLYNK
#define BLYNK_DEVICE_NAME "My Smart Watermeter" // put here the name of your own device
#define BLYNK_AUTH_TOKEN "My template token code" // put here your TOKEN code
Hereafter the following Libraries are included in Arduino:
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
Next you will have to fill in the following lines in the Arduino sketch:
char auth[] = BLYNK_AUTH_TOKEN; // variable using the above defined TOKEN code specific to your device
char ssid[] = "my WIFI"; // your own WiFi credentials
char pass[] = "my password"; // Set the password of your own WiFi, set as "" for an open netwerk
In Blynk you will have to create a set of Data streams, as per the instructions provided by Blynk: https://docs.blynk.io/en/getting-started/template-quick-setup/set-up-datastreams
The following table gives the data for the data streams to be made for your Smart Water Meter which match with the code used in the Arduino Sketch.
These Data streams will have to be defined before you can start working on your own version of a Web Dashboard.
Hereunder is an example of a Dash Board that I created for my own Smart Water Meter. I did not find a way to make a copy of the dashboard and make it available as a file, so this is a work that you will have to do yourself. It will take some time to get used to the UI, but after a while of playing with it you will see how easy it actually is to make a nice dashboard (which you will be able to see on your laptop or tablet anywhere in the world). Here you find all the information needed to make your own dashboard: https://docs.blynk.io/en/getting-started/template-quick-setup
Example Web Dashboard.
Example Mobile Dashboard
For use on mobile phones there is another tool in Blynk, “Mobile Dashboard”, that enables you to create a nice dashboard that fits on the small display of a mobile phone. This tool is a bit more difficult to work with, but after a while of playing you will be able to get a good result. To use it, you have to download the Mobile APP: https://docs.blynk.io/en/downloads/blynk-apps-for-ios-and-android
In Blynk it also possible to make “automations” which e.g., can be used to send Push Notifications to your mobile phone and/or send an email to your email address as set in your Blynk profile. For instance, if there is waterflow detected while you have set a switch button in the Web Dashboard for being away from Home. Here is how to do that: https://docs.blynk.io/en/getting-started/notification-management
Example Push Notification
Or this one:
Example email
Now it is time to have a closer look at the Arduino Sketch.
The following constants are used:
const int Liter_count_Pin = 4;
const int B_LEDPin = 27;
const int Or_LEDPin = 25;
float Flowrate_factor = 288330.00;
The first 3 serve to assign the required GPIO pins to named parameters. The Flowrate_factor is a number that will be used to calculate the correct waterflow in Liter/Sec or Liter/Min. This number will need to be adjusted, after proper calibration. How this is done, will be explained further on.
Next the following global variables are defined:
int LitCount = 0;
int PastMinuteUse = 0;
int PrevLitCount = 0;
int Stopcount = 0;
float FlowLitPerSec = 0.00;
float FlowLitPerMin = 0.00;
int UpTimeMin = 0;
double UpTimeHr = 0.00;
double UpTimeDay = 0.00;
int DayCount = 1;
int TodayUse = 0;
int PastDayUse = 0;
int PrevDayLitCount = 0;
int PastYearCub = 0;
boolean WaterFlow_state = false;
boolean Home = true;
unsigned long Count_Duration = 0.00;
BlynkTimer timer;
The comments listed in the Arduino Sketch provide further clarification about the purpose and meaning of these variables in more detail.
The most important variable is the last one: “Count_Duration” which will hold the time in microseconds measured between the moment that the “Liter_count_Pin” goes “LOW” and back to “HIGH” again.
This measured time is used in the sketch to calculate the momentary waterflow in Liters/second. This is a unique approach because it creates the capability to measure the waterflowrate instantaneously and thus calculate the values for “FlowLitPerSec” and “FlowLitPerMin”.
At the same time when a detection from HIGH to LOW takes place, a Liter of water will be counted by incrementing the variable “LitCount” with +1.
Next, a Blynk Timer object will be created:
BlynkTimer timer;
This may seem a simple statement, but actually it is key to what is a great advantage of BLYNK and that is the capability to create individual timers for a number of different functions.
In this Sketch the following timers are used for the following functions:
timer.setInterval(10000L, MEASUREWATER); // Set the function MEASUREWATER to excute every 10 seconds
timer.setInterval(60000L, SendPeriodicWaterUse); // Set the function SendPeriodicWaterUse to excute every 60s
timer.setInterval(86400000L, SendDailyUseData); // Set the function SendDailyUseData to excute every 24 hours
The function “MEASUREWATER” will be called every 10 seconds, likewise the function “SendPeriodicWaterUse” will be called every 60 seconds and the function “SendDailyUseData” every 24 Hrs (or 86400000 milliseconds).
In every function a number of global variables will receive a new value. Those variables are allocated to so-called “Virtual Pins” numbered, e.g., as “V5” for “LitCount” and then send to the BLYNK cloud for periodic updating.
4.4.2 The Function MEASUREWATERThis function is the most important one in the sketch. It detects if there is a Waterflow, calculates the Flow in Liter/sec and Liter/min and triggers the “WaterAlarm” when the “not home” indicator has been set in the cloud.
The first part of the function, takes care of the Liter counting and Flow calculation:
An essential part of this function is the line:
Count_Duration = pulseInLong(Liter_count_Pin, LOW, 9000000);
The pulseInLong function is well defined in the ARDUINO reference: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulseinlong/
In this case the function will read a pulse (going LOW) on the Liter_count_Pin. The function measures the time in microseconds between the moment the pin transitions to LOW and the moment it goes HIGH again. When the pin does not go HIGH within the timeout limit of 9 seconds (9000000 microseconds) the function will give up and return the value 0. :
else if (Count_Duration == 0) {
This situation may happen in case of very low waterflows of less 33 milliliter/second (2 L/min) orin case the rotating liter dial stops under the sensor,
if (digitalRead(Liter_count_Pin) == LOW) {
This can easily happen. In both cases this effect will result in 1 liter to be counted once:
if (Stopcount == 0) {
To indicate that a liter is counted the orange LED (yellow LED with 330 Ohm connected to GPIO25) is switched “on” with:
digitalWrite(Or_LEDPin,HIGH);
And switched to “off” at the end of the function:
digitalWrite(Or_LEDPin,LOW);
The blue LED will be switched “on” before every data transmission to Blynk, with:
digitalWrite(B_LEDPin,HIGH);
and switched “off” at the end of such transmission.
The second part of the “MEASUREWATER” function takes care of setting a Waterflow alarm.:
if (!Home && WaterFlow_state ) {
Blynk.virtualWrite(V4, true);
Blynk.logEvent("WaterAlarm", "There is waterflow and nobody is home");}
else
{Blynk.virtualWrite(V4, false); }
In case a waterflow is detected, (“WaterFlow_state” == “true”), while the Boolean “Home” is “0”, in other words when the condition “!Home” (not Home) == “true”, the Virtual Pin V4 will be set to “true” in Blynk cloud.
A logEvent will be created to enable Blynk to send a push notification or email to the owner of the smart water meter.
In case “Home” is “true” or “WaterFlow_state” is “false”, V4 will be set to “false”
The “Home” status is made as follows:
When building the Blynk Dashboard with the Blynk Console, there is a possibility to add a “Switch” widget to the Dashboard.
When this is done go to the “settings” of the widget and set the following properties:
Don’t forget to “save and Apply” the changes.
Now the value of “V0” that has been connected with the DataStream name “Home” and can be controlled to “Home” or “Not Home” and given the value “1” or “0”.
In the Arduino Sketch you will see the following lines of code:
BLYNK_WRITE(V0) {
int value = param.asInt(); // assign incomming value of pin V0 to variable "value"
if(value == 1) // excute this code in case value is "1" (meaning Home is on)
{ Home = true; } // make boolean Home true
else // excute this code in case value is "0" (meaning Home is off)
{ Home = false; } // make boolean Home false
Blynk.virtualWrite(V1, value); // Update Home state on the Blynk dashboard
}
The effect of this code is that whenever through the Blynk dashboard on your PC/Laptop or Tablet the Switch status is changed, the changed value of V0 will be send to the Smart Water Meter device and the value of its boolean variable “Home” will be modified accordingly.
If done the change will be reported back to the Blynk cloud via Virtual pin ”V1”. On the Dashboard the “LED” widget assigned to V1 will then change its status (in this example from “green” to “white” or vice versa.
At the end of the “MEASUREWATER” function both the Orange LED and Blue LED will be switched off
digitalWrite(Or_LEDPin,LOW);
digitalWrite(B_LEDPin,LOW);
4.4.3 The Function SendPeriodicWaterUseThis function takes care of sending the most important data to Blynk every minute:
The “UpTimeMin”, which is the time lapsed after the device came on-line (or after a reset) and calculated with millis () / 60000, thus resulting in minutes uptime.
The subsequent calculation of UpTimeHr and UpTimeDay should be obvious.
The amount of liter used in the past minute is calculated with:
PastMinuteUse = LitCount - PrevLitCount;
Where LitCount is the total amount of liter counted since the start of the device and PrevLitCount is the total amount 1 minute ago.
The amount used today sofar is calculated with:
TodayUse = TodayUse + PastMinuteUse;
Hereafter all the data are send to Blynk one after another.
4.4.4 The Function SendDailyUseDataFinally, the function SendDailyUseData takes care of sending a daily report to Blynk about the total amount of liter (PastDayUse) used in the past 24 hrs.
The variable “DayCount” plays an important role in this function.
After 365 days have lapsed the total water usage over the past year is calculated and send to Blynk as V13. This will only happen if the device has not been reset during the whole year (so no power cuts). The current version of the Sketch has no remedy built-in (yet) for this kind of cases, but this can be done by adding additional code that reads the latest values from Blynk after a power cut. Depending on the time that the power dip lasted, more or less data (liter) will not be accounted for.
Another possibility is the use of the built-in EEPROM memory or SPIFFS of the ESP32.
4.5 Calibrating the WaterFlow functionIn the code for the “MEASUREWATER” function, you find the following line:
FlowLitPerSec = Flowrate_factor/Count_Duration ;
The value of the Flowrate_factor has been initially set to:
float Flowrate_factor = 300000.00;
This means that in case of a Count_Duration measurement of 300 milliseconds (=300000 µSec) the value for “FlowLitPerSec” will be 1 l/S (equivalent to 60 Liter/Minute) which is a pretty high flow rate that is normally not even achieved when flushing a toilet.
The “Flowrate_factor” of 300000 is however an estimated value, that needs to be verified by calibration. The estimate is based on the assumption that the metal plate on the Liter dial of the water meter will be approx. 1/3 of the time of a complete revolution (for 1 liter) be under the sensor head.
If the estimate would be correct then 1 liter in 1 sec (for 1 revolution), would result in a “Count_Duration” of 333333 µSec.
The “Flowrate_factor” is depending on the precise position of the sensor with respect to the rotating dial with the metal plate. Even the dimensions and shape of the metal plate have an influence.
The best way to get the correct “Flowrate_factor” value is by calibration.
To do this, take a bucket of 10 liter, put it under a water tap and using a stopwatch record the time needed to fill it with 10 liter (at constant maximum flow of the water).
On the Blynk dashboard you should see the Flow in lit/min that is currently measured (after a response time of 10 sec). Note this value as “measuredFlow”
Also check, after filling the bucket, on the Dashboard if the counted number in liter has indeed been increased with 10. (If not verify your sensor positioning and adjust it if needed).
The time in seconds for 10 liter is used to compute the real water flow, as follows:
RealFlow (X) = 10 / time in seconds (in L/sec)
The “adjustedFlowrate_factor” can now be computed as follows:
“adjustedFlowrate_factor” = (measuredFlow * 300000) / RealFlow (X)
The resulting computations in an excel sheet, after a calibration, look as follows:
This leads to an adjusted Flowrate_factor, which is then put in the Arduino code as 288330.00. Now you have your system calibrated!
After flashing the modified code to your Smart Water Meter is should now produce the instantaneous WaterFlow on the Blynk Dashboard as accurate as possible. In case of doubt, just run the calibration process again.
4.6 The complete ARDUINO sketchThe complete ARDUINO sketch for the Smart Water Meter comprises 188 lines of code. The complete listing is included as part of this tutorial, the ARDUINO code is provided with an ample number of comments, which should help in understanding the programme. The sketch is provided with English comments or at choice with Dutch comments.
Throughout the Sketch a lot of print commands are included in order to help during the development and to be able to monitor the process on the Serial Monitor of the Arduino IDE (running on the PC). Uncomment these lines in case you want to monitor the process on your serial monitor of the Arduino IDE.
5. Step 3: Instructions for useWhen properly mounted on top of the existing water meter and connected to the 5V charger and having established the connection with your Wi-Fi access point, the device should be up and running. It is up to you own creativity to build a good-looking dashboard in Blynk or a dashboard for use on a mobile phone.
The system can be reset by disconnecting the 5V charger for a short while and plugging it back in.
6. Final RemarksThis was a very interesting project to work on, it was fun developing and building it, especially when you see the results on the nice-looking Blynk Dashboard.
The Wi-Fi connection made through the ESP32 TTGO T7 works excellent, though I must admit that my water meter device is close to the access point.
Of course, there is always room for improvements. Some of the improvements, I have in mind are:
- to introduce the possibility to set the actual reading of the existing water meter after a reset so that also the actual meter ready can be made available on the Blynk Dashboard.
- Add the possibility to do Over-the-air updates of the firmware on the ESP32
- Create the possibility to avoid hardcoding the Wi-Fi credentials
Also writing this tutorial for you was a pleasant thing to do.
Have fun reading and/or making your own Smart Water Meter!
Comments