EBUS

Aus FHEMWiki
Version vom 18. Januar 2016, 23:03 Uhr von Snoop (Diskussion | Beiträge) (Link ebusd und default service Aufruf angepasst)
X mark.svgDie Verwendung des EBUS zur Ansteuerung eines Heizungssystems kann dieses bei unsachgemäßer Anwendung beschädigen. Für unmittelbare oder mittelbare Folgen, die sich aus dem Nachbau des Interfaces oder der Verwendung der hier zur Verfügung gestellten Information ergeben, übernimmt der Autor keine Haftung.

Dieser Artikel beschreibt die Ankopplung von Heizungssysteme mit EBUS-Interface an FHEM.

Der EBUS ist eine bei vielen Heizungssystemen vorhandene serielle Schnittstelle mit zwei Leitungen. Verwendet werden dabei 2400 Baud als Geschwindigkeit und die beiden Signalpegel

  • logisch 1: 15–24 V
  • logisch 0: 9–12 V

Eine direkte Ankopplung des EBUS an FHEM via Pegelwandlung und serielle Schnittstelle ist nicht empfehlenswert, weil der EBUS mehrere (bis zu 25) Master-Devices erlaubt, die wiederum mehreren Slave-Devices (bis zu 228) Befehle geben. Erforderlich ist also eine Bus-Arbitration, d.h., jedes Master-Device muss sich mit den anderen über die Benutzung des Bus verständigen. Dieses relativ aufwändige Protokoll würde FHEM eine erhebliche Last aufbürden.

Stattdessen wurde der Weg beschritten, einen separaten Raspberry Pi (Modell B) an den EBUS zu koppeln und darauf die Software ebusd laufen zu lassen. Diese wird dann in einer beliebigen FHEM-Instanz als ECMD-Device definiert und somit per telnet abgefragt.

Achtung: es hat sich als nicht praktikabel erwiesen, den EBUS mit einem Pegelwandler direkt an den seriellen GPIO-Port des Raspberry Pi anzuschließen. Die ständig einlaufenden Synchronisationssignale auf dem EBUS, sowie die interne Verarbeitung der GPIO-Signale im Raspberry führen zu einer intolerablen Latenz, d.h., die EBUS-Signale kommen verspätet bei der Software ebusd an (bis zu 90 Minuten wurden beobachtet). Stattdessen sollte grundsätzlich ein Seriell-USB-Konverter verwendet werden und der Raspberry Pi über einen USB-Port mit dem EBUS verbunden werden.

Interface

Eigenbau

Hierbei wird ein kommerziell für ca. 6,00 € erhältliches USB-Modul mit ein paar Zusatzbauteilen im Wert von ca. 5,00 € versehen. Das Interface hat die folgenden Eigenschaften:

  • Verpolungssicherer EBUS-Anschluss
  • Galvanische Trennung zwischen EBUS und USB

Die Bauteile sind unkritisch und können durch äquivalente Teile ersetzt werden. Allerdings sollte bei der Zenerdiode auf eine Belastbarkeit mit 1,3 W geachtet werden, und beim USB-Modul darauf, dass dieses einen FTDI-Chip enthält.

Achtung': Der Autor übernimmt keine Haftung für die Anwendung dieser Schaltung. Zur Vermeidung von Schäden durch unsachgemäße Bedienung des Heizungssystems wird ausdrücklich empfohlen, nur die lesende Hälfte des Interfaces nachzubauen und sich auf ein passives Lauschen auf dem EBUS zu beschränken. Dazu einfach den Zweig mit Darlington-Transistor aus der Schaltung nicht einbauen.

Kommerzielles Interface

Ein kommerziell erhältliches Interface EBUS/USB findet man hier

Software

Als Software kommt auf dem Raspberry Pi der ebusd = EBUS-Dämon zum Einsatz (aktuell im Dezember 2014 die Version 0.5). Achtung, diese Software befindet sich aktuell in der Weiterentwicklung, unerwünschte Effekte können nicht ausgeschlossen werden.

Der ebusd wird auf dem Raspberry Pi nach der beiliegenden Anleitung übersetzt und installiert. Wichtigste Bestandteile der Installation sind

  • ebusd - das eigentliche Programm zur Kommunikation mit dem EBUS
  • ebusctl - ein Programm zur lokalen Ansteuerung des ebusd
  • Das Verzeichnis /etc/ebusd => Alle hier liegenden Dateien im CSV(Comma Separated Value)-Format werden beim Start des ebusd eingelesen und als Kommandos für das Heizungsystem verwendet.
  • Die Datei /etc/default/ebusd mit Startoptionen für den ebusd.
# Default settings for ebusd. This file is sourced by /bin/sh from
# /etc/init.d/ebusd.
# Options to pass to ebusd
EBUSD_OPTS="--scanconfig"

Konfiguration ebusd

Der ebusd wird entweder über ebusctl oder über telnet durch Klartextkommandos abgefragt, die lauten z.B. cyc broad OutTemp.

  • In einer CSV-Datei in /etc/ebusd muss festgelegt werden, in welche bzw. aus welcher binären Folge dieses Kommando übersetzt wird. Konkret handelt es sich z.B. bei cyc broad OutTemp um die Außentemperatur, die im Heizungssystem zyklisch als Broadcast gesendet wird und vom ebusd einfach mitgelesen wird.
  • Für unterschiedliche Heizungssysteme werden unterschiedliche CSV-Dateien benötigt. Einige dieser Dateien liegen hier vor, allerdings bisher nur für wenige Geräte.

Vorgehensweise bei einem neuen Heizungssystem

  • Zunächst das Interface mit dem EBUS verbinden. Ein funktionierendes Interface eines der beiden obigen Typen lässt sich daran erkennen, dass die EBUS-LED ständig schwach flackert - das sind die auf dem Bus einlaufenden Synchronisationssignale (Hexadezimal AA).
  • Desweiteren den ebusd starten, und zwar mit den Optionen -f (Läuft im Vordergrund) und -l All (Alle Daten werden geloggt). Diese Optionen produzieren Unmengen an Daten, und zwar immer in Form von Telegrammen der Art
10feb5160301f00d44

Hierin bedeutet

Byte Bedeutung hier
0x10 Adresse des Senders Zentrale
0xfe Adresse des Empfängers Alle Geräte
0xb5 Herstellercode Vaillant
0x16 Klasse des Kommandos Broadcast
0x03 Anzahl Datenbytes 3
0x01 Bedeutung des Wertes OutTemp = Außentemperatur
0xf0 LSB des Wertes 240
0x0d MSB des Wertes 12
0x44 CRC

Damit ergibt sich in diesem Falle eine Außentemperatur von (12*256 + 240)/256 = 12,9375 Grad Celsius. In der zugehörigen CSV-Datei wird dem ebusd diese Übersetzung mitgeteilt durch eine Zeile der Form

c;broad;OutTemp;Aussentemperatur;;FE;B516;3;01;1;temp;md;2,3;d2b;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;;

Diese CSV-Dateien können z.B. mit OpenOffice aus einem Spreadsheet generiert werden, indem dieses als CSV-Datei mit Separator ";" gespeichert wird.

  • Bei einem vollkommen unbekannten Heizungssystem sollte man den Hersteller fragen, welche Codes er verwendet
  • Für Vaillant- und Wolf- Heizungssysteme liegen in dem oben genannten Verzeichnis ein paar Beispiele vor, die man als Ausgangspunkt nehmen kann.

Konfiguration FHEM

Im nachfolgenden Beispiel wird der EBUS über das Modul ECMD angebunden und mit drei Klassen von Kommandos versehen:

define EBUS ECMD telnet 192.168.0.192:8888
attr EBUS classdefs HK.SOL.class=/opt/fhem/FHEM/ebus_solar.cfg:HK.WW.class=/opt/fhem/FHEM/ebus_ww.cfg:HK.Hz.class=/opt/fhem/FHEM/ebus_hz.cfg
attr EBUS room System
#--
define HK.Hz ECMDDevice HK.Hz.class
attr HK.Hz IODev EBUS
attr HK.Hz group heating
attr HK.Hz room Verbrauch
#--
define HK.WW ECMDDevice HK.WW.class
attr HK.WW IODev EBUS
attr HK.WW group heating
attr HK.WW room Verbrauch
#--
define HK.SOL ECMDDevice HK.SOL.class
attr HK.SOL IODev EBUS
attr HK.SOL group solarGenerator
attr HK.SOL room Solaranlage

Diese drei Klassen werden als separate Files mit den in der EBUS-Definition stehenden Dateinamen ebus_hz.cfg, ebus_ww.cfg sowie ebus_solar.cfg angelegt. Alle drei ECMD-Devices werden nun zyklisch (z.B. jede Minute) abgefragt mit

define EBUS.Timer at +*00:01:00 get HK.Hz A.Temp;;get HK.Hz state;;get HK.WW state;;get HK.SOL state
attr EBUS.Timer group heatingControl
attr EBUS.Timer room Verbrauch
attr EBUS.Timer verbose 0

Heizkreis

Die erste Datei definiert die FHEM-Readings für die Abfrage von Außentemperatur und Heizkreis:

# Außentemperatur
get A.Temp cmd {"cyc broad temp\n"}
get A.Temp expect ".*"
get A.Temp postproc { my $rval;\
  if(($_ eq "")||($_ eq "no data stored") ){\
    $rval = "err";\
  }else{\
    $rval=sprintf("%5.2f °C",$_);\
  }\
 $rval; }
# Heizkeis HK1
get state cmd {"cyc mv HK1_temp\n"}
get state expect ".*"
get state postproc { my ($bval,$rval,$tval,$pval,$qval,$sval,$xval,$zval);\
 my $hash  = $defs{"%NAME"};\
 if( ($_ eq "")||($_ eq "no data stored") ){\
    $bval = "err";\
    $rval = "err";\
    $tval = "err";\
    $pval = "err";\
    $qval = "err";\
    $sval = "err";\
    $xval = "err";\
    $zval = "err";\
 }else{\
    my @values=split(' ',$_);\
    if( $values[0] < 15 ){\
       $bval = "err";\
       $rval = "err";\
       $tval = "err";\
       $pval = "err";\
       $qval = "err";\
       $sval = "err";\
       $xval = "err";\
       $zval = "err";\
    } else { \
       $bval = HzBedarf();\
       $rval = sprintf("%5.2f °C",$values[0]);\
       $tval = sprintf("%5.2f °C",$values[1]);\
       if( $values[2] == 0 ){\
          $pval = "OFF";\
          $qval = "0 0";\
       }elsif( $values[2] == 1 ){\
          $pval = "ON (HK)";\
          $qval = "80 0";\
       }elsif( $values[2] == 2 ){\
          $pval = "ON (WW)";\
          $qval = "0 80";\
       }else{\
          $pval = "unknown";\
          $qval = "err";\
       }\
       $sval = sprintf("%d",$values[2]);\
       $xval = sprintf("%5.2f %5.2f %s %5.2f",\
         $values[0],$values[1],$qval,$bval);\
       $zval = sprintf("VL.T %5.2f °C, RL.T %5.2f °C, %s",\
         $values[0],$values[1],$pval);\
    }\
 }\
 readingsSingleUpdate($hash, "VL.T", $rval, 1);\
 readingsSingleUpdate($hash, "RL.T", $tval, 1);\
 readingsSingleUpdate($hash, "Pumpe", $pval, 1); \
 readingsSingleUpdate($hash, "Pumpe.P", $qval, 1); \
 readingsSingleUpdate($hash, "Bedarf", $bval, 1); \
 readingsSingleUpdate($hash, "Status", $sval, 1);\
 readingsSingleUpdate($hash, "reading", $xval, 1);\
 $zval; }

Warmwasserkreis

Die zweite Datei definiert die FHEM-Readings für den Warmwasserkreis:

# Warmwasserkreis
get state cmd {"cyc broad getstatus_WW\n"}
get state expect ".*"
get state postproc { my ($rval,$tval,$bval,$pval,$xval,$zval);\
 my $hash  = $defs{"%NAME"};\
 if( ($_ eq "")||($_ eq "no data stored") ){\
    $rval = "err";\
    $tval = "err";\
    $bval = "err";\
    $pval = "err";\
    $xval = "err";\
    $zval = "err";\
 }else{\
    my @values=split(' ',$_);\
    if( $values[1] < 15 ){\
       $rval = "err";\
       $tval = "err";\
       $bval = "err";\
       $pval = "err";\
       $xval = "err";\
       $zval = "err";\
    }else {\
       $rval = sprintf("%5.2f °C",$values[0]);\
       $tval = sprintf("%5.2f °C",$values[1]);\
       $bval = ($values[2] == 80) ? "ON (WW)" : "OFF";\
       $pval = ($values[3] == 1) ? "ON" : "OFF";\
       $xval = sprintf("%5.2f %5.2f %5.2f %d %d",\
        $values[0],0.0,$values[1],$values[2],$values[3]);\
       $zval = sprintf("SF1.T %5.2f °C, %s",\
        $values[0],$pval);\
    }\

Solarkreis

Die dritte Datei definiert die FHEM-Readings für den Solarkreis:

# Solarkreis
get state cmd {"cyc broad getstatus_SOL\n"}
get state expect ".*"
get state postproc { my ($rval,$pval,$qval,$lval,$yval,$xval,$zval);\
 my $hash  = $defs{"%NAME"};\
 if( ($_ eq "")||($_ eq "no data stored") ){\
    $rval = "err";\
    $pval = "err";\
    $qval = "err";\
    $lval = "err";\
    $yval = "err";\
    $xval = "err";\
    $zval = "err";\
 }else{\
    my @values=split(' ',$_);\
    $rval = sprintf("%5.2f °C",$values[0]);\
    $pval = ($values[1] == 1)?"ON":"OFF";\
    $qval = ($values[1] == 1)?65:0;\
    $lval = sprintf("%5.2f %%",$values[2]);\
    $yval = sprintf("%d",$values[3]);\
    $xval = sprintf("%5.2f %d %5.2f %d",\
      $values[0],$qval,$values[2],$values[3]);\
    $zval = sprintf("Coll.T %5.2f °C, %s",\
      $values[0],$pval);\
 }\
 readingsSingleUpdate($hash, "Coll.T", $rval, 1);\
 readingsSingleUpdate($hash, "Pumpe", $pval, 1);\
 readingsSingleUpdate($hash, "Pumpe.P", $qval." W", 1);\
 readingsSingleUpdate($hash, "Load",  $lval, 1);\
 readingsSingleUpdate($hash, "Yield", $yval, 1);\
 readingsSingleUpdate($hash, "reading", $xval, 1);\
 $zval; }

Watchdog

Überwachung in FHEM

In FHEM kann man ein Notify einrichten, um bei einem Verbindungsabbruch mehrere Versuch zum Reconnect durchzuführen

define EBUS.N notify (EBUS.*DISCONNECTED.*)|(HK.Hz:A.Temp.*err) { EBUSrecover("notify EBUS.N",0)}
attr EBUS.N group deviceDetector
attr EBUS.N room Alarm

Das dabei aufgerufene Perl-Programm besteht nur aus wenigen Zeilen:

sub EBUSrecover($$)
{   
  my ($evt,$num) = @_;
  Log 1,"[EBUS] Recover triggered from $evt, attempt No. $num";
  if(Value("EBUS") ne "opened"){
    if( $num < 7){
      $num++;
      fhem("set EBUS reopen");
      fhem("define EBUSrecoverdly at +00:00:05   
            {EBUSrecover('EBUSrecover',$num)}");
    }else{
      fhem("set Device.warn EBUS") 
    }
  }
}

Überwachung auf dem Raspberry Pi

Es empfiehlt sich auch, den ebusd kontinuierlich zu überwachen und ggf. neu zu starten. Mit der nachfolgenden Beschreibung wird alle 5 Sekunden die Existenz des Programms abgefragt und dieses bei einem versagenden Test neu gestartet.

Dazu wird auf dem Raspberry nach überall erhältlichen Anleitungen der Watchdog Timer installiert und die Datei /etc/watchdog.conf mit den beiden Parametern

test-timeout = 10
interval     = 5

besetzt. Ferner wird die Datei /etc/watchdog.d/ebusd angelegt mit dem Inhalt

#!/bin/sh
# description: watchdog helper file for ebusd  
case "$1" in
'test')
       #--- Test for ebusd
       if [ -s /var/run/ebusd.pid ] ; then
           RUN=`ps -ef | grep ebusd.*USB0 | grep -v grep`
           if [ "$RUN" != "" ] ; then            
              #echo "ebusd is already running"
              exit 0
           else
              echo "ebusd defunct at "`date`
              exit 1    
           fi
       else
           echo "ebusd not running, return 1 at "`date`
           exit 1    
       fi
       ;;
'repair')
       #-- Restarting ebusd
       echo "ebusd restarting at "`date`
       /etc/init.d/ebusd start
       RETVAL=$?
       exit 0
       ;;
*)
       exit 0
       ;;
esac