Dachs MSR1 auslesen
Die Dachs MSR1 ist ein Klein-Blockheizkraftwerk (BHKW) der Firma SenerTec, die sowohl Wärme, als auch Strom erzeugt, und vor allem eine serielle Schnittstelle zur Verfügung stellt *Händereib*. Über diese kann man einiges an Betriebs- und Wartungsdaten auslesen. Eine genauere Beschreibung des Protokolls gibts hier.
│ │ Load a Default Configuration ---> │ │ ... │ │ IO Support ---> | | ... │ │ [*] Senertec Dachs MSR1 Support │ │ (0) MSR1 usart select
Inhaltsverzeichnis
Anschluss
Obwohl sowohl das Ethersex, als auch die MSR1 einen Slave (Weiblich) RS232 Anschluss hat braucht man ein 1:1 Kabel. Außerdem muss das RTS Signal des MSR1 auf eine logische Null gelegt werden, da sich die MSR1 sonst nicht für irgendwelche Befehle interessiert. Dazu verwendet man am besten den zweiten Kanal des verbauten MAX232, legt den Eingang auf GND und greift die +10V am Ausgang ab. Ansonsten ist der RS232 Anschluss ein 9600 8N1.
Alternative Kabelbelegung
Im BHKW-Forum gibt es noch eine alternative Kabelbelegung. Zu beachten ist nur, das man die Leitungen nicht kreuzen darf. (getestet mit dem AVR-Net-IO)
Media:Kabelbelegung_Dachs_MRS1.pdf
Die dort beschriebene Belegung ist also für PC->Dachs gedacht. Diese Variante funktioniert mit einem ethersex nur dann, wenn an der RS232 Buchse auch der RTS Kanal durch den MAX232 geschleift wird. (Und die Ethersexfirmware um RTS Handshaking erweitert wurde *huestel*)
Auslesen
Der MSR1 kann man zwei verschiedene Datensätze entlocken, den "0xe8"-Datensatz und den "0xc0"-Datensatz. Beide enthalten teilweise redundante Daten, wobei jedoch letzterer weitaus mehr Informationen bietet. Den 0xe8 Datensatz bekommt man mit dem ecmd `msr1 get' bzw. `msr1 get 0'. Das erste Byte gibt an, wieviele Anfragen seit dem letzten erfolgreichen Versuch fehlgeschlagen sind. Den 0xc0-Datensatz bekommt man über `msr1 get 1'.
Einbindung in den HTTPD
│ │ Load a Default Configuration ---> │ │ ... │ │ General Setup ---> │ │ ... │ │ [*] VFS (Virtual File System) ---> │ │ [*] VFS File Inling │ │ [*] Inline MSR1
Unter $ethersexip/msr.ht kann nun der aktuelle Status des Dachs ausgelesen werden.
Programm Beispiele
Abfrage in Perl
e8
Ein Beispiel wie die Werte e8 abgefragt und aufbereitet werden.
#!/usr/bin/perl -w
# Abfrage der Dachs e8-Werte per esex
#
# kleines Beispielscript, das die e8 Wert abholt ud anschliesend aufbereitet
# in Variabeln schreibt.
# Das Script kann als Vorlage für eigene Entwicklungen benutzt werden.
#
# Autor: Lothar Schweikle-Droll
# Lizenz: GPL
use strict;
use Net::Telnet ();
my $debug=1;
my $esex;
my $esexip="192.168.255.90";
my $esexport="2701";
my $e8hex;
my @e8hex;
my $BETRIEBSSTUNDEN;
my $WARTUNG;
my $RL;
my $VL;
my $ABGAS;
my $EINSCH_TEMP_SOL;
my $BETRIEBSZUSTAND;
my $BETRIEBSZUSTAND_SOL;
my $GEN_LEISTUNG_SOL;
my @SERVICE_CODE_MODUL; #Modul 0 = Leitregler
my %BETRIEBSZUSTAND = (
10=>'Störabschaltung',
11=>'Abschaltung MV1',
11=>'Abschaltung MV2',
13=>'Drehzahl<200 n. 25 sek.',
14=>'Drehzahl>200 n. 25 sek.',
15=>'Abschaltung>1 Minute',
16=>'Abschaltung>4 Minuten',
20=>'Startvorbereitung',
21=>'Starteinleitung',
22=>'Start',
23=>'1,5 sek. nach Start',
24=>'Startende',
30=>'450<Drehz<800',
32=>'Zuschaltung Generator',
33=>'Leistungsregelung runter',
34=>'Leistungsregelung hoch',
35=>'Betrieb');
my $non;
&e8_esex;
&wertezuweisung;
### Ab hier kann eigener Code stehen
if ( $debug == 1){
&debug;
}
##### Subrotinen
sub e8_esex {
#Dachs e8 abfrge per Telnet über den ethersex
$esex = Net::Telnet->new || die "kann Ethersex nicht finden";
$esex->open(Host => $esexip, Port => $esexport, Timeout => 1);
$esex->print("msr1 get 0");
($non, $e8hex) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
#den String in ein Array wandeln
@e8hex = $e8hex =~ /(..)/g;
}
sub wertezuweisung {
$BETRIEBSSTUNDEN=hex($e8hex[1].$e8hex[2]);
$WARTUNG=hex($e8hex[3]);
#RL auf negative Temp prüfen
if (hex($e8hex[4]) >128 ) {
$RL=hex($e8hex[4])-255;
}else{
$RL=hex($e8hex[4]);
}
#VL auf negative Temp prüfen
if (hex($e8hex[5]) >128 ) {
$VL=hex($e8hex[5])-255;
}else{
$VL=hex($e8hex[5]);
}
$ABGAS=hex($e8hex[6])+15;
$EINSCH_TEMP_SOL=hex($e8hex[7]);
$BETRIEBSZUSTAND=$BETRIEBSZUSTAND{hex($e8hex[8])};
$GEN_LEISTUNG_SOL= sprintf("%.3f" , hex($e8hex[9])/34); #Sollwert Der Generatorleistung gerundet auf 3 Stellen nach dem Komma
my $i=0;
while ($i <=5 ) {
$SERVICE_CODE_MODUL[$i]=hex($e8hex[$i+10]);
$i++
}
$BETRIEBSZUSTAND_SOL=hex($e8hex[16]);
}
sub debug {
print "\n*********** DEBUG Start *************\n\n";
print "e8-Hexwert:","@e8hex","\n\n";
print "Betriebstundenb:\t",$BETRIEBSSTUNDEN,"\n";
print "Wartung:\t\t",$WARTUNG,"\n";
print "VL:\t\t\t",$VL,"\n";
print "RL:\t\t\t",$RL,"\n";
print "Abgas:\t\t\t",$ABGAS,"\n";
print "EINSCH_TEMP_SOL:\t",$EINSCH_TEMP_SOL,"\n";
print "Betriebszustand:\t",$BETRIEBSZUSTAND,"\n";
print "Generator Leitsung Sol:\t",$GEN_LEISTUNG_SOL,"\n";
print "BETRIEBSZUSTAND_SOL:\t",$BETRIEBSZUSTAND_SOL,"\n";
my $i=0;
while ($i <=5 ) {
#$SERVICE_CODE_MODUL[$i]=hex($e8sex[$i+10]);
print "SERVICE_CODE_MODUL[".$i."]\t".$SERVICE_CODE_MODUL[$i],"\n";
$i++
}
print "\n";
print "*********** DEBUG Ende **************\n\n";
}
c0
Ein Beispiel für die c0 Werte
#!/usr/bin/perl -w
# Abfrage der Dachs c0-Werte per esex
#
# kleines Beispielscript, das die c0 Wert abholt ud anschliesend aufbereitet
# in Variabeln schreibt.
# Das Script kann als Vorlage für eigene Entwicklungen benutzt werden.
#
# Autor: Lothar Schweikle-Droll
# Lizenz: GPL
use strict;
use Net::Telnet ();
my $debug=1;
my $esex;
my $esexip="192.168.255.90";
my $esexport="2701";
my $c0hex1;
my $c0hex2;
my $c0hex3;
my $c0hex4;
my $c0hex;
my @c0hex;
my $WARTUNG;
my $RL;
my $VL;
my $SRL;
my $SVL;
my $BETRIEBSSTUNDEN;
my $ABGAS;
my $AUSENTEMP;
my $F1TEMP;
my $F2TEMP;
my $GENERTEMP;
my $MOTORTEMP;
my $SERVICECODE;
my $BETRIEBSART;
my $BHKW_FREIGABE;
my $BRENNER_FREIGABE;
my $DREHZAHL;
my $ERZEUGTE_E_ENERGIE;
my $ERZEUGT_WAERME;
my $GEN_LEISTUNG;
my $STARTS;
my $non;
&e8_esex;
&wertezuweisung;
### Ab hier kann eigener Code stehen
if ( $debug == 1){
&debug;
}
##### Subrotinen
sub e8_esex {
#Dachs C0 abfrge per Telnet über den ethersex
$esex = Net::Telnet->new || die "kann Ethersex nicht finden";
$esex->open(Host => $esexip, Port => $esexport, Timeout => 1);
# $c0hex1=$esex->cmd('msr1 get 1');
$esex->print("msr1 get 1");
($non, $c0hex1) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $c0hex2) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $c0hex3) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $c0hex4) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
$c0hex = ($c0hex1).($c0hex2).($c0hex3).($c0hex4); #die vier Einzelwerte zu einem gesamt String zusammensetzen
@c0hex = $c0hex =~ /(..)/g; #Den String in eine Array schreiben (nur die HEX-Werte ohne Leerstellen
}
sub wertezuweisung {
$BETRIEBSSTUNDEN=hex($c0hex[19].$c0hex[20]);
$WARTUNG=$c0hex[3];
#RL auf negative Temp prüfen
if (hex($c0hex[22]) >128 ) {
$RL=hex($c0hex[22])-255;
}else{
$RL=hex($c0hex[22]);
}
$SRL=hex($c0hex[21]);
#VL auf negative Temp prüfen
if (hex($c0hex[24]) >128 ) {
$VL=hex($c0hex[24])-255;
}else{
$VL=hex($c0hex[24]);
}
$SVL=hex($c0hex[23]);
#Ausentemp auf negative Temp prüfen
if (hex($c0hex[25]) >128 ) {
$AUSENTEMP=hex($c0hex[25])-255;
}else{
$AUSENTEMP=hex($c0hex[25]);
}
#F1 und F2 auf negative Temp prüfen
if (hex($c0hex[26]) >128 ) {
$F1TEMP=hex($c0hex[26])-255;
}else{
$F1TEMP=hex($c0hex[26]);
}
if (hex($c0hex[27]) >128 ) {
$F2TEMP=hex($c0hex[27])-255;
}else{
$F2TEMP=hex($c0hex[27]);
}
$GENERTEMP=hex($c0hex[28]);
$SERVICECODE=hex($c0hex[30]);
$BETRIEBSART=$c0hex[31];
$BHKW_FREIGABE=hex($c0hex[32]);
$BRENNER_FREIGABE=hex($c0hex[33]);
$MOTORTEMP=hex($c0hex[34]);
$ABGAS=hex($c0hex[35])+15;
$DREHZAHL=hex($c0hex[36].$c0hex[37]);
$ERZEUGTE_E_ENERGIE=hex($c0hex[38].$c0hex[39].$c0hex[40].$c0hex[41]);
$ERZEUGT_WAERME=hex($c0hex[42].$c0hex[43].$c0hex[44].$c0hex[45]);
$GEN_LEISTUNG=sprintf("%.3f" , hex($c0hex[46])/34); #Sollwert Der Generatorleistung gerundet auf 3 Stellen nach dem Komma
$STARTS=hex($c0hex[47].$c0hex[48]);
}
sub debug {
print "\n*********** DEBUG Start *************\n\n";
print "c0-Hexwert:","@c0hex","\n\n";
print "Betriebstunden:\t\t",$BETRIEBSSTUNDEN,"\n";
print "Wartung:\t\t",$WARTUNG,"\n";
print "VL:\t\t\t",$VL,"\n";
print "RL:\t\t\t",$RL,"\n";
print "F1:\t\t\t",$F1TEMP,"\n";
print "F2:\t\t\t",$F2TEMP,"\n";
print "VL Soll:\t\t",$SVL,"\n";
print "RL Soll:\t\t",$SRL,"\n";
print "Ausen:\t\t\t",$AUSENTEMP,"\n";
print "Generator Temp:\t\t",$GENERTEMP,"\n";
print "Servicecode:\t\t",$SERVICECODE,"\n";
print "Betreibsart:\t\t",$BETRIEBSART,"\n";
print "BHKW Freigabe:\t\t",$BHKW_FREIGABE,"\n";
print "Brenner Freigabe:\t",$BRENNER_FREIGABE,"\n";
print "Motor Temp:\t\t",$MOTORTEMP,"\n";
print "Abgas:\t\t\t",$ABGAS,"\n";
print "Drehzahl:\t\t",$DREHZAHL,"\n";
print "erzeugte E-Energie:\t",$ERZEUGTE_E_ENERGIE,"\n";
print "erzeugte Wärme:\t\t",$ERZEUGT_WAERME,"\n";
print "Generator ist:\t\t",$GEN_LEISTUNG,"\n";
print "Startvorgang:\t\t",$STARTS,"\n";
print "\n";
print "*********** DEBUG Ende **************\n\n";
}
48
Ein Beispiel für die 48 Werte
#!/usr/bin/perl -w
# Abfrage der Dachs 48-Werte per esex
#
# kleines Beispielscript, das die 48 Wert abholt ud anschliesend aufbereitet
# in Variabeln schreibt.
# Das Script kann als Vorlage für eigene Entwicklungen benutzt werden.
#
# Autor: Lothar Schweikle-Droll
# Lizenz: GPL
use strict;
use Net::Telnet ();
my $debug=1;
my $esex;
my $esexip="192.168.255.90";
my $esexport="2701";
my $x48hex1;
my $x48hex2;
my $x48hex3;
my $x48hex4;
my $x48hex;
my @x48hex;
my $WARTUNG;
my $BETRIEBSSTUNDEN;
my $MAXABGAS;
my $VL;
my $STOERUNGEN;
my $F1TEMP;
my $F2TEMP;
my $MAXGENERTEMP;
my $MAXMOTORTEMP;
my $STARTS;
my $MITTELGENLEISTUNG;
my $FLUESSIGKEITSCHALTER;
my $LETZTEWARTUNG;
my $NAECHSTEWARTUNGOEL;
my $NAECHSTEWARTUNGGAS;
my @FEHLERCODE; #000-127
my @FEHLERAUTO; #1=Autoentstörung
my @FEHLERCODELANG;
my @FEHLERMIN;
my @FEHLERSTUNDEN;
my @FEHLERTAG;
my @FEHLERMON;
my @FEHLERJAHR;
my @FEHLERDATUM;
my $non;
my %Servicecode = (
0=>'Allgemeine Hilfe',
1=>'Abgasfühler U/K',
2=>'Kühlw.Motor U/K',
3=>'Kühlw.Gener. U/K',
4=>'04',
5=>'Vorlauftemp. U/K',
6=>'Rücklauftemp U/K',
7=>'Fühler 1 U/K',
8=>'Fühler 2 U/K',
9=>'Aussentemp. U/K',
10=>'Flüssigkeit. U/K',
11=>'11',
11=>'12',
13=>'13',
14=>'14',
15=>'15',
16=>'16',
17=>'17',
18=>'18',
19=>'19',
20=>'Abgas Motor zu hoch',
21=>'21',
22=>'Kuehlw. Motor > 95 C',
23=>'Abgastemp. zu hoch',
24=>'Kuehlw. Generator > 77 C',
25=>'25',
26=>'2h Vorlauft<Soll',
27=>'27',
28=>'28',
29=>'UP:Rueckleistung',
30=>'30',
31=>'HKA-Anl. < 100 U/min',
32=>'32',
33=>'HKA-Lauf < 2300 U/m',
34=>'34',
35=>'35',
36=>'36',
37=>'37',
38=>'38',
39=>'Generatorzuschalt',
40=>'Generatorabschalt');
&x48_esex;
&wertezuweisung;
### Ab hier kann eigener Code stehen
if ( $debug == 1){
&debug;
}
##### Subrotinen
sub x48_esex {
#Dachs 48 abfrge per Telnet über den ethersex
$esex = Net::Telnet->new || die "kann Ethersex nicht finden";
$esex->open(Host => $esexip, Port => $esexport, Timeout => 1);
# $x48hex1=$esex->cmd('msr1 get 1');
$esex->print("msr1 get 2");
($non, $x48hex1) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $x48hex2) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $x48hex3) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
($non, $x48hex4) = $esex->waitfor(Timeout => 1, Match =>'/[0-9A-Fa-f]+/');
$x48hex = ($x48hex1).($x48hex2).($x48hex3).($x48hex4); #die vier Einzelwerte zu einem gesamt String zusammensetzen
@x48hex = $x48hex =~ /(..)/g; #Den String in eine Array schreiben (nur die HEX-Werte ohne Leerstellen
}
sub wertezuweisung {
$BETRIEBSSTUNDEN=hex($x48hex[1].$x48hex[2]);
$STARTS=hex($x48hex[3].$x48hex[4]);
$MAXABGAS=hex($x48hex[5])+15;
$MAXGENERTEMP=hex($x48hex[7]);
$MAXMOTORTEMP=hex($x48hex[6]);
#MAXVL auf negative Temp prüfen
if (hex($x48hex[8]) >128 ) {
$VL=hex($x48hex[8])-255;
}else{
$VL=hex($x48hex[8]);
}
#Max F1 und F2 auf negative Temp prüfen
if (hex($x48hex[9]) >128 ) {
$F1TEMP=hex($x48hex[9])-255;
}else{
$F1TEMP=hex($x48hex[9]);
}
if (hex($x48hex[10]) >128 ) {
$F2TEMP=hex($x48hex[10])-255;
}else{
$F2TEMP=hex($x48hex[10]);
}
$MITTELGENLEISTUNG=(7.5 / 255 * hex($x48hex[11]));
$STOERUNGEN=hex($x48hex[12]);
$FLUESSIGKEITSCHALTER=hex($x48hex[55]);
$LETZTEWARTUNG=hex($x48hex[59].$x48hex[60]);
$NAECHSTEWARTUNGOEL=hex($x48hex[59].$x48hex[60])+2700;
$NAECHSTEWARTUNGGAS=hex($x48hex[59].$x48hex[60])+3500;
#Fehler Code zuweisen
for ($non=1;$non<=7;$non++) {
$FEHLERCODE[$non]=hex($x48hex[7+(6*$non)]);
$FEHLERAUTO[$non]="0";
if ( $FEHLERCODE[$non] > 127 ) {
$FEHLERCODE[$non]=$FEHLERCODE[$non]-128;
$FEHLERAUTO[$non]="1";
}
$FEHLERCODELANG[$non]=$Servicecode{$FEHLERCODE[$non]};
$FEHLERSTUNDEN[$non]=hex($x48hex[9+(6*$non)]);
if ( $FEHLERSTUNDEN[$non]=~ /^[0-9]$/ ) {
$FEHLERSTUNDEN[$non]='0'.$FEHLERSTUNDEN[$non];
}
$FEHLERMIN[$non]=hex($x48hex[8+(6*$non)]);
if ( $FEHLERMIN[$non]=~ /^[0-9]$/ ) {
$FEHLERMIN[$non]='0'.$FEHLERMIN[$non];
}
$FEHLERTAG[$non]=hex($x48hex[10+(6*$non)]);
if ( $FEHLERTAG[$non]=~ /^[0-9]$/ ) {
$FEHLERTAG[$non]='0'.$FEHLERTAG[$non];
}
$FEHLERMON[$non]=hex($x48hex[11+(6*$non)]);
if ( $FEHLERMON[$non]=~ /^[0-9]$/ ) {
$FEHLERMON[$non]='0'.$FEHLERMON[$non];
}
$FEHLERJAHR[$non]=hex($x48hex[12+(6*$non)]);
if ( $FEHLERJAHR[$non]=~ /^[0-9]$/ ) {
$FEHLERJAHR[$non]='0'.$FEHLERJAHR[$non];
}
$FEHLERDATUM[$non]=$FEHLERSTUNDEN[$non].":".$FEHLERMIN[$non]." ".$FEHLERTAG[$non].".".$FEHLERMON[$non].".".$FEHLERJAHR[$non]; #Deutsch ohne Sekunden
$FEHLERDATUM[$non]=$FEHLERJAHR[$non]."-".$FEHLERMON[$non]."-".$FEHLERTAG[$non]." ".$FEHLERSTUNDEN[$non].":".$FEHLERMIN[$non].":30"; #International mit gemittelte Sekunden
#print "HEXzahl: ".(7 + (6 * $non))."\n";
}
}
sub debug {
print "\n*********** DEBUG Start *************\n\n";
print "48-Hexwert:","@x48hex","\n\n";
print "Betriebstunden:\t\t",$BETRIEBSSTUNDEN,"\n";
print "Letzte Wartung:\t\t",$LETZTEWARTUNG,"\n";
print "Wartung bei Öl (alle 2700h):\t",$NAECHSTEWARTUNGOEL,"\n";
print "Wartung bei Gas (alle 3500h):\t",$NAECHSTEWARTUNGGAS,"\n";
print "Starts:\t\t\t",$STARTS,"\n";
print "MAX Abgas:\t\t",$MAXABGAS,"\n";
print "MAX Gen Temp:\t\t",$MAXGENERTEMP,"\n";
print "MAX Mot Temp:\t\t",$MAXMOTORTEMP,"\n";
print "Max VL:\t\t\t",$VL,"\n";
print "Max F1:\t\t\t",$F1TEMP,"\n";
print "Max F2:\t\t\t",$F2TEMP,"\n";
print "Mittlere Gen Leistung:\t",$MITTELGENLEISTUNG,"\n";
print "Anzahl Störungen:\t",$STOERUNGEN,"\n";
print "Fluessigkeitsschalter:\t",$FLUESSIGKEITSCHALTER,"\n\n";
print "Fehlerpeicher\n";
print "=============\n";
for ($non=1;$non<=7;$non++) {
print "Fehler: ".$non."\n";
print "Fehlercode: ".$FEHLERCODE[$non]."\n";
print "Autoentstörung: ".$FEHLERAUTO[$non]."\n";
print "Zeit: ".$FEHLERSTUNDEN[$non].":".$FEHLERMIN[$non]." ".$FEHLERTAG[$non].".".$FEHLERMON[$non].".".$FEHLERJAHR[$non]."\n";
print "Datum: ".$FEHLERDATUM[$non]."\n";
print "Langtext: ".$FEHLERCODELANG[$non]."\n\n";
}
print "\n";
print "*********** DEBUG Ende **************\n\n";
}