Bewässerungsanlage - Steuerung mit FHEM

Sie befinden sich hier:
» 
» 
» 

Automatische Ansteuerung über FHEM

Nachdem ich in den vorherigen Abschnitten step-by-step den Aufbau der Bewässerungsanlage und deren Steuerung beschrieben habe und die Steuerung grundsätzlich schon funktioniert, fehlt eigentlich nur noch die automatische Steuerung über FHEM.

Meine Lösung in FHEM möchte ich in diesem Abschnitt vorstellen.

Steuern und Überwachen der Bewässerungsanlage von überall

Die notwendige Funktionalität in FHEM kann in zwei Abschnitte eingeteilt werden. Das ist einerseits die Ansteuerung der Hardware (Ventile, Ultraschallsensor) und andererseits die Ermittlung des Gießindex. Der Aufbau der Bewässerungsanlage etc. wurde in den vorherigen Abschnitten schon ausführlich beschrieben, so dass ich mich hier rein auf den FHEM-Teil beschränke. Für die anderen Informationen, die evtl. notwendig sind, um das Gesamte zu verstehen, habe ich hier vermehrt mit Querverweisen gearbeitet.


Ansteuerung der Ventile über FHEM

Die Auslösung der Befehle erfolgt über http-Requests, die an den Microcontroller (Pretzelboard) gesendet werden. Die Parametrisierung der Requests wurde im Abschnitt Programmierung Pretzelboard ausführlich beschrieben. Das Senden der Requests erfolgt über das HTTP-Modul von FHEM. Für den Empfang des Response wird ebenfalls das HTTP-Modul verwendet. Letztendlich landet der Text (Response), der auf der Webseite ausgegeben wird, im state des Devices. Beispielhaft finden Sie hier die FHEM-Konfiguration für ein Relais (Ventil):

define EG_au_VT_1 HTTPMOD none 0
attr EG_au_VT_1 userattr reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex readingsRegex01 readingsRegex02 set01Name set01NoArg:0,1 set01URL set02Name set02NoArg:0,1 set02ParseResponse:0,1 set02URL set03Name set03NoArg:0,1 set03URL setParseResponse:0,1
attr EG_au_VT_1 alias Ventil 1
attr EG_au_VT_1 cmdIcon ON:rc_GREEN OFF:rc_RED STS:rc_INFO@yellow
attr EG_au_VT_1 devStateIcon an:general_an@green aus:general_aus@red
attr EG_au_VT_1 icon sani_irrigation
attr EG_au_VT_1 reading01Name state
attr EG_au_VT_1 reading01Regex ^(.\w*)
attr EG_au_VT_1 reading02Name state
attr EG_au_VT_1 reading02Regex ^(.\w*)
attr EG_au_VT_1 reading03Name state
attr EG_au_VT_1 reading03Regex ^(.\w*)
attr EG_au_VT_1 set01Name ON
attr EG_au_VT_1 set01NoArg 1
attr EG_au_VT_1 set01URL http://192.168.1.145/device/?R2=ON
attr EG_au_VT_1 set02Name OFF
attr EG_au_VT_1 set02NoArg 1
attr EG_au_VT_1 set02URL http://192.168.1.145/device/?R2=OFF
attr EG_au_VT_1 set03Name STS
attr EG_au_VT_1 set03NoArg 1
attr EG_au_VT_1 set03URL http://192.168.1.145/device/?R2
attr EG_au_VT_1 setParseResponse 1
attr EG_au_VT_1 sortby 2
attr EG_au_VT_1 stateFormat stateDE
attr EG_au_VT_1 timeout 10
attr EG_au_VT_1 userReadings stateDE {(ReadingsVal($name,"state","") eq "ON")?"an":"aus"}
attr EG_au_VT_1 webCmd ON:OFF:STS

Reading:
setreading EG_au_VT_1 stateDE "";

Ultraschallmessung (Füllstand Zisterne) über FHEM

Eine Ultraschallmessung wird ebenfalls über das HTTP-Modul von FHEM ausgelöst. Es wird ein Request zum Pretzelboard gesendet. Dort erfolgen drei Einzelmessungen im Abstand von jeweils einer Sekunde. Als Response werden die drei Ergebnisse der Einzelmessung zurückgeliefert (z.B. 623|624|624). Die Werte entsprechen dem Abstand des Ultraschallsensors zur Wasseroberfläche in Millimetern. Aus diesen Angaben wird in FHEM das aktuelle Volumen der Zisterne ermittelt und in Readings gespeichert.

Es werden immer drei Einzelmessungen durchgeführt, um die Genauigkeit der Messung zu erhöhen. Wenn alle drei Werte identisch sind, ist es einfach und es wird dieser Wert übernommen. Sind zwei Werte identisch und es weicht nur ein Wert ab, so wird der dritte Wert verworfen. Sind alle drei Werte unterschiedlich, so wird der gerundete Mittelwert gebildet. Den entsprechenden Auszug aus FHEM finden Sie hier:

define EG_au_US_1 HTTPMOD none 0
attr EG_au_US_1 userattr reading01Name reading01Regex readingsRegex01 set01Name set01NoArg:0,1 set01URL setParseResponse:0,1
attr EG_au_US_1 alias Ultraschallsensor
attr EG_au_US_1 cmdIcon STS:rc_INFO@yellow
attr EG_au_US_1 icon light_dinner_table
attr EG_au_US_1 reading01Name state
attr EG_au_US_1 reading01Regex ^([0-9|]*)
attr EG_au_US_1 set01Name STS
attr EG_au_US_1 set01NoArg 1
attr EG_au_US_1 set01URL http://192.168.1.145/device/?US1
attr EG_au_US_1 setParseResponse 1
attr EG_au_US_1 sortby 6
attr EG_au_US_1 timeout 20
attr EG_au_US_1 userReadings value1 { my @values = split /\Q|/, ReadingsVal("$name","state",0);; $values[0]},\
value2 { my @values = split /\Q|/, ReadingsVal("$name","state",0);; $values[1]},\
value3 { my @values = split /\Q|/, ReadingsVal("$name","state",0);; $values[2]},\
value_avg {\
  my @values = split /\Q|/, ReadingsVal("$name","state",0);;\
  my $value_avg = 0;;\
  if ($values[0] == $values[1] || $values[0] == $values[2]) {\
    $value_avg = $values[0];;\
  } elsif ($values[1] == $values[2]) {\
    $value_avg = $values[1];;\
  } else {\
    $value_avg = round(($values[0] + $values[1] + $values[2]) / 3, 0);;\
  };;\
  $value_avg;;\
},\
level_cur {\
  my $level_cur = ReadingsVal("$name","level_max",0) \
    + ReadingsVal("$name","value_min",0) \
    - ReadingsVal("$name","value_avg",0);; $level_cur;;},\
volume_cur {\
  my $volume_max = ReadingsVal("$name","volume_max",5000);;\
  my $volume_cur = round(ReadingsVal("$name","level_cur",0) / ReadingsVal("$name","level_max",1260) * $volume_max,0);;\
  if ($volume_cur > $volume_max){\
    $volume_cur = $volume_max;;\
  }\
  $volume_cur;;\
}
attr EG_au_US_1 webCmd STS

Readings:
setreading EG_au_US_1 level_cur 0;  # aktueller Füllstand
setreading EG_au_US_1 level_max 1260;  # max. mögl. Füllstand
setreading EG_au_US_1 value1 0;  # Messwert 1
setreading EG_au_US_1 value2 0;  # Messwert 2
setreading EG_au_US_1 value3 0;  # Messwert 3
setreading EG_au_US_1 value_avg 0;  # Messwert Mittelwert
setreading EG_au_US_1 value_min 575;  # min. Abstand Sensor Wasseroberfläche
setreading EG_au_US_1 volume_cur 0;  # aktuelles Zisternenvolumen
setreading EG_au_US_1 volume_max 5000;  # max. Zisternenvolumen
setreading EG_au_US_1 volume_prev 0;  # Zisternenvolumen gestern

Ermittlung des Gießindex

Auf die Bedeutung des Gießindex bin ich bereits im Abschnitt Entwurf der Steuerungslogik ausführlich eingegangen. Die konkrete Ermittlung des Gießindex erfolgt über den AT-Befehl, der eine Procedure mit der Gießlogik aufruft, Alle Schwellwerte wurden in Readings einer Dummy-Variable hinterlegt, damit sie bei Bedarf angepasst werden können, ohne direkt am Sourcecode Änderungen vornehmen zu müssen.

Der AT-Befehl triggert zwischen 09:00 und 18:00Uhr die Abfrage der Parameter, auf denen der Gießindex basiert (Außentemperatur und Ertrag der PV-Anlage). Um 20:00Uhr erfolgt der Vorschlag des Gießprogrammes (Viel, Wenig, Töpfe, Pause) unter Einbeziehung weiterer Parameter (Füllstandänderung Zisterne, Regendauer). Das ermittelte Gießprogramm wird per Pushbullet auf mein Handy gesendet und kann bei Bedarf auch noch bis 21:00Uhr angepasst werden.

Hier die wesentlichen Parameter für die Gießlogik:

define at_Giessen_Logik at +*01:00:00 {myGiessenUtils_at_Giessen_Logik($hour)}
define du_Giessen_Logik dummy

Readings:
setreading du_Giessen_Logik energy_cum 0;  # kumulierte Energie
setreading du_Giessen_Logik energy_limit 30;  # Schwellwert Energie
setreading du_Giessen_Logik temp_cum 0;  # kumulierte Temperatur
setreading du_Giessen_Logik temp_limit 20;  # Schwellwert Temperatur
setreading du_Giessen_Logik pause 0;  # Anzahl Tage Giesspause
setreading du_Giessen_Logik index 0;  # aktuell ermittelter Gießindex
setreading du_Giessen_Logik index_prev 0;  # gemerkter Gießindex vom Vortag
setreading du_Giessen_Logik toepfe_limit 25;  # Schwellwert Gießprogramm Töpfe
setreading du_Giessen_Logik wenig_limit 50;  # Schwellwert Gießprogramm Wenig
setreading du_Giessen_Logik viel_limit 100;  # Schwellwert Gießprogramm Viel

Um 21:00Uhr wird das Gießen ausgelöst. Dies geschieht über den AT-Befehl, der eine Dummy-Variable setzt und dadurch ein Notify triggert. Nach dem Gießen wird wiederum eine Pushbullet-Message auf mein Handy gesendet, welches das ausgeführte Gießprogramm und die vergossenen Wassermenge mitteilt.

Das Reading energy_limit kann direkt gesetzt werden. Wie bereits erwähnt, ermittle ich den Wert aus dem monatlichen Durchschnittsertrag der letzten Jahre x 0,75 / 30 Tage. Das Reading wird somit an jedem Ersten eines Monats dynamisch gesetzt.

define at_EnergyLimit at *00:00:01 {if ($mday == 1) {myGiessenUtils_setEnergyLimit($month)}}
sub myGiessenUtils_setEnergyLimit($){
  my($curmonth) = @_;
  my $value = ReadingsVal("du_Energy_Stat","M_Mittel_".sprintf("%02d",$curmonth),"0" );
  my @fld="";
  my $energy_limit = 30;
  if ($value ne "0"){
    @fld = split(" ", $value);
    $energy_limit = round($fld[0]/30*0.75,0);
  }
  fhem("setreading du_Giessen_Logik energy_limit $energy_limit");
}

Gießlogik und das eigentliche Gießen ist strikt getrennt, d.h. der Gießindex wird über die Readings von du_Giessen_Logik ermittelt. Das eigentliche Giessen erfolgt über du_Giessen. Somit kann auch völlig losgelöst von der Gießlogik ein Gießvorgang ausgelöst werden.

define at_Giessen at *21:00:00 {myGiessenUtils_at_Giessen()}
define du_Giessen dummy
attr du_Giessen setList Viel Wenig Töpfe Pause
attr du_Giessen webCmd Viel:Wenig:Töpfe:Pause
define ny_Giessen notify du_Giessen:.* {myGiessenUtils_ny_Giessen($EVENT)}

Zum Abschluss hier noch das komplette Perl-Modul, welches die Gießlogik enthält:


Darstellung in FHEM

Die Darstellung über die herkömmliche FHEM-Oberfläche ist bei mir eher sekundär. Die primäre Darstellung erfolgt über FHEM Tablet-UI, worüber ich im nächsten Kapitel schreiben werde.


Kontakt

Senden Sie mir Ihre Fragen oder Anregungen über die Kontaktbox oder direkt per Email. Sie können mich natürlich auch über die gängigen sozialen Netze erreichen.

kontakt@kaempf-nk.de

Fragen / Anregungen?

Sicherheitsabfrage:
Datenschutzhinweis: Die eingegebenen Daten werden nicht an Dritte weitergegeben.