Automatische Balkonbewässerung - Tankinhalt berechnen
Contents
Nachdem der Füllstandsensor nun zuverlässig Distanzen an FHEM sendet, kann daraus der Tankinhalt berechnet werden.
Mathematik eines Eimers
Die dafür nötigen Formel unterscheiden sich je nachdem, welche Form der Tank hat, als ersten Protoypen habe ich einen Putzeimer genutzt.
Über dem Eimer habe ich den Ultraschallsensor angebracht und die Entfernung der Unterkante bis zum Boden mit 24cm gemessen. Der Radius in dieser Höhe beträgt 14cm, am Boden sind es 12cm.
Mithilfe dieser Angaben und der Formel zu Berechnung des Volumens eines Kegelstumpf kann der Inhalt des Eimers berechnet werden."
Die nötige Formel findet sich zum Beispiel auf Wikipedia1:
$$ V = \frac{h \cdot \pi}{3} \cdot (R^2 + R \cdot r + r^2) $$
Für unseren Eimer ergeben sich dann folgende Variablen:
Variable | Bedeutung | Wert |
---|---|---|
R_max | Maximaler Radius | 14cm |
r | Radius an tiefster Stelle | 12cm |
h | nutzbare Höhe des Eimers | 24cm |
R | Radius an Wasseroberfläche | s.u. |
d | Gemessene Distanz | ReadingsVal('Balkon_Distance', 'distance13', 0) |
w | Wasserstand | h - d |
V | aktuelles Volumen |
Um den Radius an einer gegebenen Höhe zu berechnen, kann folgende Formel genutzt werden:
$$ R = r + ((R_{max}-r) \cdot \frac{w}{h}) $$
Einbindung in FHEM
Damit die gesamte Berechnung und Konfiguration des Tanks an einer einzelnen Stelle in FHEM erfolgt, wird dazu ein ReadingsProxy2 definiert.
Dieser besitzt folgende Readings, wobei die ersten vier manuell gesetzt werden müssen (abhängig vom Eimer):
Reading | Bedeutung |
---|---|
tankhoehe | nutzbare Höhe des Eimers: h |
eimerradius_max | Maximaler Radius: R_max |
eimerradius_min | Minimaler Radius: r |
min_waterlevel | Mindestfüllung bevor Trockenlaufschutz greift (in ml) |
waterlevel | aktueller Wasserstand (wird berechnet): w |
tankfilling | aktueller Füllstand (wird berechnet) |
defmod Balkon_Tank readingsProxy Balkon_Distance:distance13
# Berechnung der einzelnen Variablen
attr Balkon_Tank valueFn {\
my $eimerhoehe = ReadingsVal('Balkon_Tank', 'tankhoehe', 0);;\
my $eimerradius_max = ReadingsVal('Balkon_Tank', 'eimerradius_max', 0);;\
my $eimerradius_min = ReadingsVal('Balkon_Tank', 'eimerradius_min', 0);;\
# Wasserstand = Tankhöhe - gemessene Distanz\
my $waterlevel = $eimerhoehe-ReadingsVal('Balkon_Distance','distance13',0);;\
# Radius an Oberfläche berechnen\
my $radius = $eimerradius_min + (($eimerradius_max-$eimerradius_min)*$waterlevel/$eimerhoehe);;\
# Volumen des Kegelstump berechnen\
my $tankfilling = int((($waterlevel * pi)/3)*(( $radius ** 2) + ($radius * $eimerradius_min) + ($eimerradius_min ** 2)));;\
# Readings setzen\
fhem("setreading Balkon_Tank waterlevel $waterlevel");;\
fhem("setreading Balkon_Tank tankfilling $tankfilling");; \
return $tankfilling;;\
}
# Konfiguration Eimerabmessungen
setstate Balkon_Tank 2017-07-28 17:59:51 tankhoehe 24
setstate Balkon_Tank 2017-07-28 17:59:11 eimerradius_max 14
setstate Balkon_Tank 2017-07-28 17:59:22 eimerradius_min 12
# Mindestinhalt bevor Trockenlaufschutz greift
setstate Balkon_Tank 2017-07-28 13:13:53 min_waterlevel 3000
Trockenlaufschutz
Der Trockenlaufschutz wird über ein notify3 umgesetzt welches bei Aktualisierung des Tankinhalts überprüft, ob noch genug Wasser vorhanden ist. Falls nicht wird die Pumpe deaktiviert und eine Benachrichtigung gesendet.
defmod Trockenlaufschutz notify Balkon_Tank:tankfilling:.* { \
\
my $tankfilling = Value("Balkon_Tank");;\
my $lastTankfilling = ReadingsVal('Trockenlaufschutz', 'last_tankfilling', 0);;\
my $minWaterlevel = ReadingsVal('Balkon_Tank', 'min_waterlevel', 0);;\
# Nur auslösen, wenn der letzte Waterstand über dem minimum war\
if ($lastTankfilling > $minWaterlevel && $tankfilling <= $minWaterlevel) {\
Log 2, ("Pumpe wird gestoppt, zu wenig Wasser: $tankfilling");;\
fhem("set Pumpe_Schalter off");;\
fhem("set pushmsg msg 'fhem' 'Pumpe wurde gestoppt, zu wenig Wasser: $tankfilling ml übrig' '' 0 ''");;\
}\
else {\
Log 3, ("Pumpe kann weiterlaufen: $tankfilling");;\
}\
# Wasserstand speichern\
fhem("setreading Trockenlaufschutz last_tankfilling $tankfilling");;\
}
Comments