# Title:
Monitoring of level in water well and and water consumption in garden.
Boris Smeds (bs222vh)
Estimated time to prepare 2 - 3 weeks.
# Objective
I have a water well in the garden that is used for watering plants and vegetables. To monitor the water level I have earlier used a long wooden stick that is stuck into the well and then to see how long part of the stick is wet. To avoid this complicated manual procedure I wanted a simple IoT solution to present the water level in the well directly on my smart phone or computer. It could also show how fast the water level will recover after watering the garden. At the same time I also wanted to measure the volume of water taken out of the well.
# Material
Pressure sensor : DC 24V 4-20 mA Water level regulator from lyuouk via Amazon.se Cost 455 SEK
Water flow meter : YF S201 , Electrokit 109 SEK
2 wire cable 25 m : 2 pair telephone cable I had available
Raspberry Pi pico WH : Electrokit 109 SEK
OLED display : Mini OLED display 128x32 white pixels. I2C SSD1306 - , procured from Pchbutik.se 39 SEK
ESP32 : https://www.makershop.de/plattformen/nodemcu/esp32-board-stiftleisten/ cost 7 EUR
Power supply 24V DC. I had a 20 V DC power supply in the junkbox that could be used.
Jumper cables and breadboards.
USB chargers as 5 V power supply
# Computer setup
For the water level measurement I use a microcontroller Raspberry Pi pico WH. It is programmed in Micropython with Thonny IDE. The sensor is giving a current between 4 and 20 mA dependant on the water level in the well. A resistor 150 ohm in series with the supply cable to the sensor will give a voltage drop between 60 mV and 300 mV that is measured with the analog input of the RP pico WH
For the water consumption sensor I used a ESP32 also programmed in Micropython. The sensor is generating pulses proportional to the water flow. These pulses are counted with an interrupt routine.
# Putting everything together
# Water level

Circuit diagram for the water level measurement.
My first attempt to measure the water in the well was to use an utrasonic device (HY-SRF05) to measure the time delay for pulses reflected from the water surface. This showed to be unreliable since the concrete walls of the well also gave reflections of the ultasonic pulses. As a final solution I used a pressure sensor with a 4 - 20 mA current output. It is specified to have a 24 V DC supply, but showed to be working well with the 20 V DC supply I had available. The current through the 150 ohm resistor will give a voltage drop between 600 and 3000 mV which is below the maximum input voltage of 3.3 V to the RP pico WH. The circuit is connecting the my home W-lan for sending data to thingspeak.com.
I also have a local OLED display showing the water level.

Picture of the pressure transducer used to measure water level. It is placed at the bottom of the well.
The cabel is 5 m long and is extended by 25 m telephone type cable into the house.
# Water flow

Circuit diagram for the measurement of water flow to the garden.
The sensor is specified to have a voltage supply of 5 to 24 V, but I decided to use a 3.3 V supply so that the level of the output pulses would not exceed the maximum input level of 3.3 V to the ESP32. Initially I could no connect to my home W-LAN because the signal level was too low, but my nearbye neighbor had a stronger signal and he allowed me to use his W-LAN. The measured data is sent to thingspeak.com

Detail of flowsensor connected to water pipes.

Picture of ESP32 connected to water flow sensor

Overall picture showing water pump and water sensor installation at the garden water distribution pipe.
# The code
# Code for Water level:
import machine
import urequests
import network, time
from machine import Pin, ADC
from time import sleep
import framebuf
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
#configure oled LCD
i2c=I2C(0,sda=Pin(20), scl=Pin(21), freq=400000)
oled = SSD1306_I2C(128, 32, i2c)
oled.text("STARTING", 0, 0)
oled.show()
#Read voltage over 150 ohm resistor to measure current between 4 and 20 mA
#20 mA will generate 3 V that is below the maximum AD converter input of 3.3 V
pot = ADC(Pin(28))
HTTP_HEADERS = {"Content-Type": "application/json"}
THINGSPEAK_WRITE_API_KEY = "XXXXXXXXXXXXXX" # insert my WRITE API key
UPDATE_TIME_INTERVAL = 20000 # in ms
last_update = time.ticks_ms()
ssid = "Torhamn2" # my ssid
password = "xxxxxxxxx" #insert password here
#Configure Raspberry Pi Pico W as Station
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
if not sta_if.isconnected():
print("connecting to network...")
sta_if.connect(ssid, password)
while not sta_if.isconnected():
pass
print("network config:", sta_if.ifconfig())
ip=sta_if.ifconfig()[0]
print(ip)
cal = 2.413 #2.2247
#Restart program if not possible to connect to Thingspeak network
def reconnect():
print("failed to connect to thingspeak. Reconnecting....")
time.sleep(5)
machine.reset()
cnt=0 # counter incrementing after every sample taken
while True:
if time.ticks_ms() - last_update >= UPDATE_TIME_INTERVAL:
last_update = time.ticks_ms()
pot_value = pot.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
pot_value = pot_value/65535*3300-599.0 # mV
mm = pot_value *cal
vatten_mm = int(mm)
bme_readings = {"field1": vatten_mm ,"field2":cnt}
try:
response = urequests.post(
"http://api.thingspeak.com/update?api_key=" + THINGSPEAK_WRITE_API_KEY,
json=bme_readings,
headers=HTTP_HEADERS, )
except Exception as e:
print(e)
reconnect()
finally:
response.close()
# Skriv ut mätvärde på LCD display
oled.fill(0)
oled.text(str(cnt),0,0) #antal samples
oled.text("BRUNNSVATTEN mm",0,10) #TEXT
oled.text(str(vatten_mm), 0, 20) #vattendjup i mm
oled.show()
cnt=cnt+1
print(bme_readings)
# Code Water flow
#Water flow meter with YF-S201
from machine import Pin
from time import sleep
import network, time
import urequests
import machine
ssid = "Torrum"
password = "XXXXXXXX"
HTTP_HEADERS = {"Content-Type": "application/json"}
THINGSPEAK_WRITE_API_KEY = "XXXXXXXXXXXX" #insert WRITE API key
def reconnect():
print("failed to connect to thingspeak. Reconnecting....")
time.sleep(5)
machine.reset()
#Configure as Station
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
if not sta_if.isconnected():
print("connecting to network...")
sta_if.connect(ssid, password)
while not sta_if.isconnected():
pass
print("network config:", sta_if.ifconfig())
ip=sta_if.ifconfig()[0]
print(ip)
cnt = 0
def handle_interrupt(pin):
global cnt
cnt = cnt +1
water = Pin(14, Pin.IN)
water.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)
while True:
print("cnt :",cnt)
liter = cnt/480
print("liter: ",liter)
bme_readings = {"field1": cnt,"field2": liter}
try:
response = urequests.post("http://api.thingspeak.com/update?api_key=" + THINGSPEAK_WRITE_API_KEY,json=bme_readings,headers=HTTP_HEADERS, )
except Exception as e:
print(e)
reconnect()
finally:
response.close()
print(bme_readings)
sleep(20)
# Additional comments to the code!
The data from the sensors is updated every 20 seconds.
Data is sent to thingspeak network with the POST(HTTP)protocol.
All equipment could be powered by mains connected USB chargers so power consumption and battery operation was not an issue.
The code as shown here is missing some indentation, that disappeared when pasting the code to HACKMD.
# Presenting the data
For presenting the data I have chosen the thingspeak network. thingspeak.com A free account will allow to send data every 15 seconds and can show data in both numerical and graphic form. The pictures below show examples when water was pumped out of the well, and show the increase of water level afterwards. The free account can receive 3 000 000 messages per year.

- [ ] 
# Conclusion.
I managed to install a working system to monitor the water level in a well, and to measure the volume of the water taken to the garden.
I had initially a problem when the internet connection was interrrupted, which resulted in a program crash.
This was finally solved by the
try:
except
part in the code that will restart the program after a loss of internet connection.
Also the coverage of my local W-LAN was not strong enough for the water flow sensor, but could be solved by connection to another nearbye W-LAN.