UPDATE: neuere Version des Beitrags unter: Regenwassertank Füllstand messen mit Raspberry Pi; Version 2020
Hardware:
Raspberry Pi
DYP-ME007Y
Software:
Am Ende wurde es: python und mysql
Vorwort zum DYP-ME007Y: hier gibt es wohl verschiedene Versionen, die beste Erklärung dazu habe ich hier gefunden: JSN-SR04T-2.0.pdf
Ich verwende die Variante ohne Widerstand, also die simple Variante.
Dazu habe ich mal ein Script zum antesten gesucht und auch gleich was gefunden.
http://town-und-country.taunustörtchen.de/ueberwachung-der-zisterne-mit-dem-raspberry-pi/
ABER: die Berechnung gilt für einen Tank der über die gesamte Tiefe einen konstanten Querschnitt hat. Mein Tank ist aber ein liegender Zylinder, was bedeutet, dass 10 cm Unterschied im Wasserstand viel mehr Volumen hat als der selbe Unterschied ganz oben oder ganz unten.
Also mal auf die Suche gemacht nach einer verwendbar einfachen Formel.
Der zweite Treffer in der Online-Suche war
</pre> #!/usr/bin/python # coding=utf8 import time import math import sys import RPi.GPIO as GPIO #################### select mode ###################### # mode 1 = analog (R27 empty) # mode 2 = serial, running continuous (R27 = 47kOhm) # mode 3 = serial with trigger from script (R27 = 120kOhm) mode=3 #################### Tank settings #################### voll=70 # 70 cm von Sensor bis Wasseroberfläche = voll leer=230 # 230 cm von Sensor bis Wasseroberfläche= leer laenge=230 #230 cm Länge des Tanks radius=90 #90 Radius Tank korr= 0 # 20 wird zur Entfernung addiert echo_time = 2 # delay between measurements in seconds ### make sure no echo is left allowed_dev = 0.1 # filter out wrong measurements #################### serial settings #################### if (mode == 3) or (mode == 2): import serial #seriellen Port einstellen ser = serial.Serial("/dev/ttyAMA0", baudrate=9600) #, timeout=3.0 ser = serial.Serial( port='/dev/ttyAMA0', baudrate = 9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1 ) #################### analog settings #################### elif (mode == 1): GPIO.setmode(GPIO.BOARD) trig=13 echo=15 GPIO.setup(echo,GPIO.IN) GPIO.setup(trig,GPIO.OUT) else: print "Mode falsch." print >> sys.stderr, "Mode falsch." GPIO.cleanup() sys.exit(1) ###### main ############### entfernung=0 gesamt=0 entf_array = {} for i in range(0,10): if (mode == 1): ### analog GPIO.output(trig,True) time.sleep(0.00001) GPIO.output(trig,False) j = 0 while GPIO.input(echo) == 0: pass start=time.time(); while GPIO.input(echo) == 1: pass ende = time.time(); entfernung=(((ende - start) * 34300) / 2)+korr elif (mode == 2): ### serial cont. ser.flushInput() #import pdb #pdb.set_trace() #ser.write(bytes([0x55])) #startbyte = ord(ser.read(1)) startbyte = 1 while startbyte != 255: read = ser.read(1) print read if len(read) == 0: continue else: startbyte = ord(read) hbyte = ord(ser.read(1)) lbyte = ord(ser.read(1)) sbyte = ord(ser.read(1)) entfernung = (hbyte * 256 + lbyte)/10 + korr summe = startbyte + hbyte + lbyte summe = summe - (int(summe/256) * 256) if summe != sbyte: entfernung = 0 print(startbyte, hbyte, lbyte, sbyte, entfernung) elif (mode == 3): ### serial standby ser.flushInput() ser.write(chr(0X55)) #startbyte = ord(ser.read(1)) #import pdb #pdb.set_trace() startbyte = None while startbyte != 255: read = ser.read(1) if len(read) == 0: ser.flushInput() continue else: startbyte = ord(read) hbyte = ord(ser.read(1)) lbyte = ord(ser.read(1)) sbyte = ord(ser.read(1)) ser.flushInput() ser.write(chr(0X55)) ser.write(chr(0X55)) entfernung = (hbyte * 256 + lbyte)/10 + korr summe = startbyte + hbyte + lbyte summe = summe - (int(summe/256) * 256) if summe != sbyte: entfernung = 0 #print (i) #print(startbyte, hbyte, lbyte, sbyte, entfernung) print entfernung entf_array[i] = entfernung gesamt=gesamt+entfernung time.sleep(echo_time) mittelwert=gesamt/(i+1) ##### filter mismatching measurements i = 0 gesamt = 0 for entf in entf_array: if entf_array[entf] < mittelwert*(1+allowed_dev) and entf_array[entf] > mittelwert*(1-allowed_dev): gesamt=gesamt+entf_array[entf] i=i+1 mittelwert=gesamt/(i) ##### discard if median is outside full or empty if (mittelwert < voll or mittelwert > leer): print "Messung ausserhalb Bereich: " + str(mittelwert) print >> sys.stderr, "Messung ausserhalb Bereich: " + str(mittelwert) mittelwert = None volumen = None #if (mode == 1): # GPIO.cleanup() #sys.exit(1) else: ##### convert distance to round tank volume print "Entfernung: ", mittelwert, " cm" hoehe = (leer - mittelwert) acosval = (radius - hoehe)/float(radius) # float needed else python rounds to int alpha = 2*math.acos(acosval) volumen = int(round(laenge * radius*radius/2*(alpha -math.sin(alpha)))) check = False if check: print "leer: ", leer, " cm" print "radius: ", radius, " cm" print "laenge: ", laenge, " cm" print "hoehe: ", hoehe, " cm" print "acosval: ", acosval, "" print "alpha: ", alpha, " rad" print "Volumen: ", volumen, " cm³" print "Volumen: ", volumen/1000, " Liter" print "- - - - - - - - - - - - - - - - - - - - - " #f1=open('/var/scripts/regentank_check/entfernung.txt','w') #print >> f1, '%d' % (mittelwert) #f1.close() #f2=open('/var/scripts/regentank_check/volumen.txt','w') #print >> f2, '%d' %(volumen) #f2.close() #f1l=open('/var/scripts/regentank_check/entfernung.txt','r') #f2l=open('/var/scripts/regentank_check/volumen.txt','r') #serverftp = ftplib.FTP('ftp.server.de', 'user', 'pass') #serverftp.storbinary('Stor entfernung.txt', f1l) #serverftp.storbinary('Stor volumen.txt', f2l) #serverftp.quit() import MySQLdb db = MySQLdb.connect(host="localhost", # your host, usually localhost user="regenwasseruser", # your username passwd="password", # your password db="regenwasser") # name of the data base # you must create a Cursor object. It will let # you execute all the queries you need cur = db.cursor() # Use all the SQL you like if volumen: vol_string = str(int(round(volumen/1000,0))) else: vol_string = "Null" cur.execute("INSERT INTO volumen (`datetime`,`volume`) VALUES (now()," + vol_string + ")") db.commit() db.close() #### clean up after using GPIO mode if (mode == 1): GPIO.cleanup() <pre>
Und zu guter letzt, noch meine Skizzen von der Verkabelung, für Modus 1, 2 und 3:
Modus 1, analog, kein Widerstand:
Modus 2, seriell Dauer, 47kOhm Widerstand:
Modus 3, seriell Standby, 120kOhm Widerstand:
Und noch eine Warnung: ich hatte einen Schlauch quer durch den Tank liegen von der Wasserpumpe. Der Sensor hat, als der Wassertand viel, den Schlauch erfasst. Unbedingt darauf achten, dass die Richtung in die der Sensor misst auch wirklich frei ist.
Ich lasse das script jetzt einmal pro Tag per crontab laufen.
Hier gehts zum Setup des Systems: http://bitsnbites.astrids.bplaced.net/?p=145
Oder weiterlesen beim erstellen der Anzeige des Füllstands mit html und php: