Automatische Balkonbewässerung - Tankinhalt berechnen

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:

Für unseren Eimer ergeben sich dann folgende Variablen:

VariableBedeutungWert
R_maxMaximaler Radius14cm
rRadius an tiefster Stelle12cm
hnutzbare Höhe des Eimers24cm
RRadius an Wasseroberfläches.u.
dGemessene DistanzReadingsVal('Balkon_Distance', 'distance13', 0)
wWasserstandh - d
Vaktuelles Volumen 

Um den Radius an einer gegebenen Höhe zu berechnen, kann folgende Formel genutzt werden:

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):

ReadingBedeutung
tankhoehenutzbare Höhe des Eimers: h
eimerradius_maxMaximaler Radius: R_max
eimerradius_minMinimaler Radius: r
min_waterlevelMindestfüllung bevor Trockenlaufschutz greift (in ml)
waterlevelaktueller Wasserstand (wird berechnet): w
tankfillingaktueller 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");;\
}

Footnotes

Gallery

Related Posts