This winter my area has been hit by a terrible drought: we had no rainfalls for more than 100 days. Even if -till now- there has not been outages of running water, I realized how precious water is and, for this reason, I would like to create something that can build awareness about water use and abuse. I was thinking of a small device based on Nicla Sense ME to install on the top of the tap lever. By measuring the tilt of the tap lever, the device will make a rough estimation of water flow (in liters per minute). Additionally, thanks to the 3-axis magnetometer, it will also be possible to determine the horizontal orientation of the tap lever and make an estimation of the amount of fossil fuels required to heat the water and, consequently, the amount of CO2 released. With proper calibration, the same device could be installed in a shower, where the tap is installed vertically on the wall
This was a sketch to show the original idea
Element14 was so nice to send me a Nicla Sense ME board, but I was so clumsy that I damages the board during the build. For this reason, I felt back to Arduino Nano 33 IoT. The main issue, however, is that the IMU of the Arduino 33 Nano IoT does not have a magnetometer, so I have not the absolute heading of the tap lever
To build the hardware, you need
- An Arduino Nano 33 IoT
- A 0.91 inches I2C OLED display
- a push button
- a DC-DC converter
- a 3.7V Lipo battery
Here is the wiring diagram
Arduino sketch performs three basic tasks
- Reads accelerometer to determine how open the tap is. If the tap is open, then water flow is calculated
- Reads gyroscope to extrapolate, from angular velocity, an approximation of the orientation of the tap lever. When tap is open, heading is needed to compute the amount of energy (and thus the amount of natural gas) to heat the water
- Reads the status of the button. When long-pressed, the sketch enters a calibration mode. User will have to
- Switch fully on the tap, then press the button. The sketch will store the accelerometer readings for this position
- Close the tap, then press the button. The sketch will store the accelerometer readings for this position
To calculate the amount of water provided, we make an interpolation based on a maximum flow rate when tap is fully open. The code to calculate the current flow rate is
double perc = (accelZFull + (accelZ - accelZClose)) / (accelZClose - accelZFull); double flow = FLOW_MAX_MILLILITRE_SEC * perc; double deltaMs = millis() - prevMs; double milliLitres = flow * deltaMs / 1000.0; partialMilliLitres += milliLitres; totalMilliLitres += milliLitres;
where
- accelZ is the current accelerometer reading
- accelZFull is the accelerometer reading when the tap is fully open (stored during the calibration procedure)
- accelZClose is the accelerometer reading when the tap is closed (stored during the calibration procedure)
-
FLOW_MAX_MILLILITRE_SEC is the flow rate when the tap is fully open expressed in millilitres per second. This constant is defined as
#define FLOW_MAX_MILLILITRE_SEC ((FLOW_MAX_LITRE_MIN * 1000.0) / 60.0)
and
#define FLOW_MAX_LITRE_MIN 24.0
To estimate the "heading" of the tap, I will use the gyroscope. Currently the algorithm is in it initial stages, and needs to be improved
// make a moving average of the readings avgGX = (avgGX * 0.9) + (gX * 0.1); float delta = millis() - prevFastMs; if (delta > 0) { // update heading only when velocity is greater than a threshold (IMU has an offset) if ((appStatus == APP_NORMAL) && (abs(avgGX) > 5.0)) { heading = heading + (avgGX * delta / 1000.0); } prevFastMs = millis(); }
The value of the heading is later used to calculated the amount of energy
double percHot = (heading - ORIENT_MIN) / (ORIENT_MAX - ORIENT_MIN); double co2 = CO2_GRAMS_PER_LITER * percHot * milliLitres / 1000.0;
where CO2_GRAMS_PER_LITER has been calculated from the amount of natural gas required to raise the temperature of a liter of water from 10 °C (the average temperature of cold water) to 40 °C.
#define CO2_GRAMS_PER_LITER 60.0
One liter of water weights about 1 kg
The specific heat capacity of water is approximately 4.2 J / g.K
The increase in temperature is 25 Kelvin (40-15)
So the energy needed is 1000 [g] x 25 [K] x 4.2 [J / g.K] = 1.05 MJ
I assumed the calorific value of gas to be 35 MJ / standard cubic meter, so to heat 1 liter I need 1.05 [MJ] / 35 [MJ / smc] = 0,03 [smc]
A standard cubic meter of methane weights 550 g, so to heat the water I will burn 0,03 [smc] * 550 [g / smc] = 16,5 g
For a chemistry
Burning 16.5 g of methane will produce 16.5 [g] * 2.75 = 45 [g] and I rounded to 60 [g] to take into account boiler efficiency etcetera
Here are some pictures of the device
Full code for this project is available on my github repository