In previous posts, I have detailed how I keep track of the status of my stand by generator. One of the main tasks of the stand by generator is to ensure that there is a steady supply of power for the sump pump. So, wouldn’t it be nice if we could monitor the level of the sump, preferably remotely, so we can take action if it is too high?
Raspberry Pi to the rescue. In the course of investigating distance sensors, I came across http://www.raspberrypi-spy.co.uk/2012/12/ultrasonic-distance-measurement-using-python-part-1/. It explains the use of the ultrasonic distance sensor HY-SRF05, which can read distances between 5cm and 2m. Perfect for my purpose. Besides, they only cost around $3.00 each!
I took the very simple voltage divider circuit mentioned on that webpage and created a little circuit board for it. Here’s it is, fresh out of the etcher, with the ink of hand drawn traces still covering the only copper left on the board. To the top you can see the 4 points of the board to which the HY-SRF05 will be attached by solder points.
Once I sanded the ink off, drilled the holes and mounted the resistors, connecting wires and sensor, I did a test. It worked! Woohoo! Next, accuracy testing was conducted, proving that most of the time the reading is within 5%. Good enough for my purpose.
To attach the sensor in a convenient spot, I used a hose clamp and short piece of wire strapping. Through experimenting I found out that in order to get a fairly accurate reading, you need to get as much clearance on the sides of the sensor as possible. The wire strapping allows for this, as it is bendable and strong enough to support the lightweight sensor. The sensor and circuit board are kept in place with a colourful binder clip, for easy removal in case the pump needs to be serviced.
The Raspberry Pi itself is mounted some distance away (+/- 50 cm) on the sump pump closet wall, using a case I obtained from Allied Electronics. A couple of screws inserted in the drywall keep the Pi high and dry.
So much for the hardware. Now, I should point out that this Pi is the second one I own, the first one being used to monitor generator temperature. The Pi uses a concept called ‘bit-banging’ to get the readings from the sensor. If the CPU is busy servicing a lot of processes, that could read to erroneous readings, since the CPU ‘time slices’ and is too busy to pay attention to our sensor when needed. So, for now, this is all the Pi does. I adapted the Python program from Raspberry Pi Spy to every five minutes take 10 readings and store these, along with the current time) in a simple text file. I also installed an FTP service on this Pi (‘vsfptd’) which will be used by my primary Pi to obtain the data as needed.
Here’s the amended program:
1: #!/usr/bin/python
2: #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3: #|R|a|s|p|b|e|r|r|y|P|i|-|S|p|y|.|c|o|.|u|k|
4: #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5: #
6: # ultrasonic_1.py
7: # Measure distance using an ultrasonic module
8: #
9: # Author : Matt Hawkins
10: # Date : 09/01/2013
11: # Modified: Keith Hekker
12: # Date : 2013/03/11
13: # Import required Python libraries
14: import time
15: import RPi.GPIO as GPIO
16: import os
17: import datetime
18:
19:
20: # Use BCM GPIO references
21: # instead of physical pin numbers
22: GPIO.setmode(GPIO.BCM)
23:
24: # Define GPIO to use on Pi
25: GPIO_TRIGGER = 23
26: GPIO_ECHO = 24
27:
28: print "Ultrasonic Measurement"
29:
30: # Set pins as output and input
31: GPIO.setup(GPIO_TRIGGER,GPIO.OUT) # Trigger
32: GPIO.setup(GPIO_ECHO,GPIO.IN) # Echo
33:
34: # Set trigger to False (Low)
35: GPIO.output(GPIO_TRIGGER, False)
36:
37: while 1:
38: # Allow module to settle
39: dTimeRecorded = datetime.datetime.now()
40: print dTimeRecorded
41:
42: tdistance = 0
43: #Create a list to store distances
44: lDistances = []
45: for x in range(0,10):
46: time.sleep(1.0)
47: # Send 10us pulse to trigger
48: GPIO.output(GPIO_TRIGGER, True)
49: time.sleep(0.00001)
50: GPIO.output(GPIO_TRIGGER, False)
51: start = time.time()
52:
53: while GPIO.input(GPIO_ECHO)==0:
54: start = time.time()
55:
56: while GPIO.input(GPIO_ECHO)==1:
57: stop = time.time()
58:
59: # Calculate pulse length
60: elapsed = stop-start
61:
62: # Distance pulse travelled in that time is time
63: # multiplied by the speed of sound (cm/s)
64: distance = elapsed * 34300
65:
66: # That was the distance there and back so halve the value
67: distance = distance / 2
68: print "Distance : %.1f" % distance
69: if x > 0 and distance > 0:
70: tdistance = tdistance + distance
71: lDistances.append(distance)
72:
73: fdistance = tdistance/9
74: print "Final Distance : %.1f" % fdistance
75:
76: lDistances.append(dTimeRecorded)
77: with open('distances','w') as file:
78: for item in lDistances:
79: file.write("{}\n".format(item))
80:
81: time.sleep(300)
82:
83: # Reset GPIO settings
84: GPIO.cleanup()
It does need to use supervisory permission to run, so once you switched to the directory where your Pi program is stored, you need to type in on the command line sudo python ultrasonic_1.py.
So much for the data generating Pi. Now we switch our attention to the data consuming Pi. It already runs as a webserver using bottle.py straight from within Python. All I did was add a function that generates an FTP call(using the Python library FTPlib), opens the file downloaded, reads the 9 values, adds them up and divides the total by nine to get the average value. It also retrieves the time when these values were recorded. Lastly, it generates a line of text along the lines of ‘Sump pump water level: 8.08 cm. Recorded at: 2013-03-12 19:18:47’, which can be plugged into the HTML template being used. Speaking of this template, in the appropriate place on the front page, I added a variable that bottle.py would populate at run time. That’s it!
Here’s the function I added into my bottle web server program
1: def getSumpPumpDepth():
2: sftp = ftplib.FTP('192.168.0.151','fred','fredspassword')
3: sftp.cwd("pythonprogs")
4: gFile = open("distancemeasurement","wb")
5: sftp.retrbinary("RETR distances",gFile.write)
6: sftp.quit()
7: gFile.close()
8: listdata = [line.strip() for line in open("distancemeasurement","r")]
9: nTotalDistance = 0
10: nListLength = len(listdata)
11: for x in range(0,nListLength):
12: if x < nListLength -1:
13: nTotalDistance = nTotalDistance + float(listdata[x])
14: else:
15: cTimeRecorded = listdata[x]
16:
17: #print nTotalDistance
18: nAvgDistance = nTotalDistance/(nListLength -1)
19: #print nAvgDistance
20: #print cTimeRecorded
21: return "Sump pump water level: " + str(nAvgDistance)[:4] + " cm. Recorded at: " + cTimeRecorded[:19]
And here is the line it produces on the web page:
Awesome post! This is exactly what I was looking to do... Thank you for sharing!
ReplyDeleteVery cool. Did you add any code to send an email or email to text alert when certain thresholds are met?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi!
ReplyDeleteThis post is pretty old, but is nice if you want to start with the ultrasound device.
I've polished the code to make it pretty reliable (14 cm = 13,9 <> 14,1 cm).
wget https://raw.githubusercontent.com/mirdesign/general/master/water/ultrasound.py
Enjoy the code!
Greetings,
Maarten
www.mirdesign.nl
Maarten,
ReplyDeleteThanks a lot, you certainly know a lot more about Python than I do.
I have incorporated this in my code and will post an update to this blog shortly to notify anyone else.
Bedankt!
Keith
There can be any number of problems that could have resulted in this.
ReplyDeleteHeres a list:
1) Check your discharge line outside and see if its clogged up or encountering any kinks/twists/etc.
2) Check your pump and see if there is anything blocking water suction such as leaves, etc.
3) Check to see if your pill/float switch is working. There may even be a short in it.
4) Check to see if there is a power problem (ie breaker blown, etc)
5) How old is the pump? If its 7-8 years old or is in use often, the pump may be shot.
The battery backup system should either be an AC pump with an inverter, or a DC pump with a charger. AGM batteries are recommended because they require no maintenance. A good Sump Pump uses low energy to run at full capacity. Having an efficient pump that reduces the number of pumping cycles by discharging the maximum amount of water will extend the life of the pump.You can know more here.
ReplyDeleteAmazing post! I keep track of the status of my stand by generator. One of the main tasks of the stand by generator is to ensure that there is a steady supply of power for the sump pump. I achieved that from this review!!!!!!!!!!
ReplyDeleteKieth,
ReplyDeleteSorry for asking you to return to a ~5year old project....
I bought a SRF05 to do almost the same thing, but have been struggling to understand how to wire the thing into my PI#3 (there is surprising few "How Tos" for this sensor) - accepting I'm new to all this, could you post a breadboard diagram so I can try to figure out where I keep failing.
Many Thanks,
Carl
*update*
ReplyDeleteI'm pleased to say that almost gave up too early - further reading suggests it's the same as the 04 - so if anybody else is following in my poor footsteps - Look here: https://tutorials-raspberrypi.com/raspberry-pi-ultrasonic-sensor-hc-sr04/ - which worked for me.... the scripts from your site still work too, but I needed to change GPIO_TRIGGER to be "18"...
Thanks again Keith (and great post by the way..)
Some truly wonderful work on behalf of the owner of this internet site , perfectly great articles . battery backup sump pump
ReplyDelete