Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Python Script for Raspberry Pi + HC-SR04 sensor to measure water level in a sump pit
#!/usr/bin/python
# Measure distance to water level in sump pit using
# HC-SR04 ultrasonic ranging module
# Sensor info:
# 2cm - 4m. range with ~3mm. accuracy, 15 degree measuring angle
# 5VDC, 15mA working current
# Suggestion in spec to connect ground before 5VDC line when hot plugging
# Measure surface area no less than 0.5 m^2 (really?)
# range_sensor.py
# Prints the current date/time and measurement in cm. as CSV
# Calls another process if reading falls below threshold
import RPi.GPIO as GPIO
import time
import datetime
import os
import subprocess
# Minimum distance to water level (cm) / threshold
MIN_DISTANCE = 24.5
# Calculate median of a list
def median(lst):
lst = sorted(lst)
if len(lst) < 1:
return None
if len(lst) %2 == 1:
return lst[((len(lst)+1)/2)-1]
else:
return float(sum(lst[(len(lst)/2)-1:(len(lst)/2)+1]))/2.0
# Sensor Pinout
TRIG = 23
ECHO = 24
# Set mode and data direction
GPIO.setmode(GPIO.BCM)
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
# Speed of sound constant
# 343 m / sec. is rougly the speed of sound in dry air at 20C
# The speed decreases with temperature and increases a bit with more humidity
# This is a cool, damp basement, so we'll assume 341 m / sec. (15C / 59F with 60%RH)
# Sensor measures round-trip time, so we divide by 2 to get half of that distance
SPEED = 17050
distances = []
sampleCount = 0
while sampleCount < 30:
# Distance Measurement In Progress
# Limit sample rate to every 10ms (even though spec recommends 60ms)
time.sleep(0.01)
# Send 10uS pulse
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
# Waiting for ECHO to go high...
# Max. wait 1 second using pulse_end as temp variable
pulse_start = time.time()
pulse_end = time.time()
while GPIO.input(ECHO)==0 and pulse_start - pulse_end < 1:
pulse_start = time.time()
# Waiting for ECHO to go low... (max. wait 1 second)
pulse_end = time.time()
while GPIO.input(ECHO)==1 and pulse_end - pulse_start < 1:
pulse_end = time.time()
# Append distance measurement to samples array
distances.append((pulse_end - pulse_start) * SPEED)
sampleCount = sampleCount + 1
# Cleanup (set GPIOs to input, etc.)
GPIO.cleanup()
# Print date/time and median measurment in cm.
median = round(median(distances), 1)
print datetime.datetime.now().strftime("%Y-%m-%d %H:%M") + "," + str(median)
# Notify of problem if water level is high
if median < MIN_DISTANCE:
subprocess.call(["node", os.path.dirname(os.path.realpath(__file__)) + "/email_warning.js", str(median)])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment