Improving and calibrating the capacitive water sensor

In a previous article, I explained a type of water level sensor that works capactitively and therefore passes no direct current through the water. When I wrote that article, I had already made two of these sensors and installed one in each of the two sump pump wells in my basement. These sensors have been working quite well for a long time, but they have a few issues. In this article, I will describe the improvements I have made to the sensor design and how I calibrated the sensors to allow me to determine the water flow rate and the volume of water the sump pump pumps each time it comes on.

Introduction

The two water level sensors I installed in the sump pump wells were equipped with nRF24L01 wireless modules. They transmitted measurements every 30 seconds to a Raspberry Pi, which recorded them to a database. This allowed me to visualize the water level in the sump-pumps in real time and see roughly how often the sump pumps came on. However, the water level followed this interesting stair-step pattern:

For a long time I didn't know what caused this, and assumed it was an issue with the sensor. However, I recently determined that the stair-step is an artifact of the method I used to measure the capacitance of the tube. Previously, I measured the capacitance by charging the tube through a resistor, continuously sampling the voltage, and measuring how long it takes to reach a certain voltage. However, a single ADC measurement takes aroung 13 microseconds, so the useful resolution of the water level sensor was limited to around 13 microseconds. In fact, if you look at the above plot, you will see that the height difference between successive "steps" is around 13 microseconds.

Improving the measurement algorithm

In order to use the sensor at the highest resolution, I had to implement a new algorithm for measuring the capacitance. Instead of using the ADC to measure the voltage on the tube, I used the analog comparator to determine precisely when it reaches a certain voltage. The positive input of the analog comparator was connected to the internal 1.1 volt reference, and the negative input was connected to the tube. To make a measurement, the Arduino starts charging the sensor tube through a 1M resistor, as before. The Arduino then measures the time it takes for the state of the analog comparator to change. Finally, the Arduino discharges the sensor tube through the 1M resistor.

Furthermore, to increase the accuracy of the measurement, the TIMER1 module of the Arduino was used to measure the time, rather than the micros function. The timer was configured to run at a frequency of 2MHz, so each tick would correspond to half a microsecond. The timer is reset when the Arduino starts charging the sensor tube, and the value is recorded when the state of the analog comparator changes.

Improving the construction of the sensor

In addition to fixing the code, I also added a spacer to the center wire to help keep it centered in the outer tube. This spacer is made from a strip of plastic from a milk jug with two slots cut in it, as shown below

Calibrating the sensor

My next goal was to calibrate the sensor so I can map a measured value to a specific volume. This would allow me to determine the total volume of water pumped as well as the approximate flow rate.

The general idea was to fill up a bucket with water and let it drain into the sump pump pit over several hours. By comparing the time it takes to fill up the pit normally vs. when water is being added should allow me to compute the volume of water pumped in one cycle. However, in practice, several attempts were needed to account for all of the variables.

First attempt

For the first attempt, I had the sensor set to take a measurement roughly every 700 milliseconds and output it via a serial port to my computer. The water in the bucket was allowed to flow out through a tube. I then measured the flow rate by filling water into a measuring cup for a certain amout of time and dividing the volume of water collected by the time. I measured a flow rate of around 6.8 mL per second. When the water was flowing, the time between pumps was reduced from 742 seconds to 418 seconds. Let \(\dot{V}_{bucket}\) be the rate of water inflow from the bucket, \(\dot{V}_{ground}\) be the rate of water entering the sump pump from the ground, \(t\) be the time one pumping cycle takes with the bucket, and \(t_0\) be the time one pumping cycle takes without the bucket. Since the volume of the tank must be the same with and without the bucket:

$$ V_{tank}=t\left(\dot{V}_{ground}+\dot{V}_{bucket}\right) = t_0\dot{V}_{ground} $$ $$ V_{tank}=t\left(\frac{V_{tank}}{t_0}+\dot{V}_{bucket}\right) $$ $$ V_{tank}\left(1-\frac{t}{t_0}\right)=t\dot{V}_{bucket} $$ $$ V_{tank}=\frac{\dot{V}_{bucket}}{\frac{1}{t}-\frac{1}{t_0}} $$ Plugging in the numbers I measured, we get: $$ V_{tank} \approx \frac{6.8\text{mL/s}}{\frac{1}{418\text{s}} - \frac{1}{742\text{s}}} \approx 6.5\text{L} $$

The tube I used to siphon the water out of the bucket rose up as the bucket drained, so the bucket stopped draining about halfway through. When I restarted it, I measured the flow rate again at 4.6 mL per second. This time, the pumping time was reduced to 502 seconds, so the volume was computed to be around 7.1 mL.

The issue with this attempt was that I was seeing these "spikes" in the data:
These spikes would seem to indicate that water was flowing back into the tank very quickly right after the pump was done pumping. While I expected this to happen, I did not expect it to account for half of the water in the tank, as the graph above might suggest.

Second attempt

On my second attempt, I added an ultrasonic sensor to the sump pump pit to determine the height of the water in the tank. This would allow me to determine whether the spikes seen above were due to an issue with the sensor or were caused by changes in the water level. I programmed a second Arduino to read from the ultrasonic sensor every second and transmit the value to my computer. I also weighed down the end of the tube in the bucket to prevent it from floating up and stopping prematurely. The data collected during the run are shown below:

The data from the ultrasonic sensor agreed with the data from the capacitive sensor, and the speedup caused by the added water is clearly visible. The decrease in flow rate from the bucket is also evident, as the sump pump slows down as the test progresses.

To determine the volume of one pump from this data, I would have to know the rate at which water is flowing into the tank. I assumed that flow rate decreased exponentially over time, since the flow rate is proportional to the pressure, which is proportional to the amount of remaining water. In other words, the flow rate \(\dot{V}_{bucket}\) can be given by \(be^{-ct}\), where \(b\) is the initial flow rate and \(c\) defines the decay rate. Suppose we start filling when the tank is empty. Let \(t_i\) be the time it takes for the sump pump to run \(i\) times (or equivalently, pump a volume of \(iV_{tank}\) in water). As above, let \(t_0\) be the time it takes for the tank to fill when no additional water is flowing in.

$$ \begin{aligned} iV_{tank} & = \int_{0}^{t_i}\left(\dot{V}_{ground}+\dot{V}_{bucket}\right)dt \\ & = \int_{0}^{t_i}\left(\frac{V_{tank}}{t_0}+be^{-ct}\right)dt \\ & = t_i\frac{V_{tank}}{t_0} + \frac{b}{c}\left(1-e^{-ct_i}\right) \end{aligned} $$ $$ i = \frac{t_i}{t_0} + \frac{b}{cV_{tank}}\left(1-e^{-ct_i}\right) $$

I then used performed a regression analysis to determine the values of \(c\) and \(\frac{b}{cV_{tank}}\). Given the initial flow rate, I can then solve for \(V_{tank}\). With the data I collected, I determined that \(V_{tank}\) is around 5.6 liters.

Third attempt

On my third attempt, I placed the ultrasonic sensor in the bucket to track the rate at which the water was leaving the bucket. As the water drained from the bucket, I also took measurements of the height of the water level in the tank so I could later calibrate my measurements.

Using the data from the ultrasonic sensor, as well as measurements of the overall height, bottom circumference, and top circumference of the bucket, I created a plot of the volume of water in the tank, as shown below in blue. An exponential best-fit curve is also shown in orange, which seems to meet the measured data quite closely

However, the measurement of the tank size was less successful. The water in the bucket did not seem to last as long, probably because the rate of natural flow into the tank had slowed significantly. The data from the capacitive sensor also showed some strange effects:

According to the above plot, the water level increased and decreased randomly for a few minutes until settling into a linear increase. I was not able to come up with a reasonable physical explanation for this, and I was also not able to observe the water level increasing or decreasing suddenly. When I moved the ultrasonic sensor back to the sump pump tank to check if the capacitive sensor was correct, both sensors displayed the normal more-or-less linear increase. As it turns out, the strange readings were caused by water spraying out of the weep hole on the outflow pipe and onto the cable of the capacitive sensor. This water spray was affecting the capacitance and changing the readings. The linear increase then returned once all of the water had evaporated.

Nevertheless, the time between pumps could still be accurately determined. On its own, the sump pump would pump roughly every 1940 seconds. Using the ultrasonic data, I could accurately determine the amount of water that had flown out of the bucket in each pumping cycle. The volume of one tank must therefore equal the amount flowing in from the ground plus the amount flowing in from the bucket:

$$ V_{tank} = t\dot{V}_{ground}+\Delta V_{bucket} = \frac{t}{t_0}V_{tank} + \Delta V_{bucket} $$

I plotted the rightmost equation for varying values of \(V_{tank}\) and looked for the best fit. From this test, I estimate the volume of the tank to be around 6.8 liters.

Fourth attempt

On the fourth attempt, I placed the sump pump cover over the pit to prevent the water from spraying out and affecting the readings. Like in the third attempt, the ultrasonic sensor measured the height of the water in the bucket. However, this time, the readings from the capacitive sensor were much closer to the expected linear increase.

To analyze the data, I used the actual data from the sensor instead of just the time between pumping cycles. To do this I first assumed that the value reported by the capcitive sensor was proportional to the volume of water in the tank. Since we know the amout of water that entered from the bucket over any given time, we can subtract the water flowing in from the bucket from the sensor reading to get the rate at which water flows in from the ground. However, the sensor produces a value in microseconds, and the volume of water from the bucket is given in cubic meters. Thus, a scale factor is needed to perform this subtraction. Since the flow rate from the ground is relatively consistent over the duration of the test, a scale factor must be selected that makes the slope of the subtracted result close to the slope one would get without the water flowing in from the bucket.

In the above plot, the blue curve is the data from the sensor, and the orange curve is the subtracted result. Note that the slope of the orange curve while the tank is filling is fairly consistent, even when water is flowing in from the bucket. The orange curve represents what the sensor reading would be if the bucket was not adding any water but the sump pump still ran at the same times.

The scale factor was determined to be around 1400 microseconds per cubic meter. Since the difference in the sensor readings from when the tank is full and when the tank is empty is around 7.6 microseconds, the volume of the tank can be determined to be 7.6/1400 cubic meters, or around 5.4 liters.

Conclusion

I conducted four different test and got five different values, ranging from 5.4 to 7.1 liters. Obviously this large range of values is not helpful in determining the actual volume of water pumped by the sump pump in one cycle. However, I tended to get larger values when the water from the ground was flowing in faster, suggesting that the actual volume is closer to 5.4 liters than to 7.1. Further testing will be needed to determine the volume more precisely.

Comments

Popular posts from this blog

Controlling a ceiling fan and light with an Arduino

Pole and zero calculator