Wago /SPS über Modbus(TCP/IP) in FHEM steuern

Begonnen von lechez, 05 Mai 2013, 10:50:13

Vorheriges Thema - Nächstes Thema

ChrisD

Hallo,

Du kannst versuchen den Fehlercode im Log mit auszugeben um so vielleicht herauszufinden was passiert. Dazu kannst du in der Funktion write_modbus_coil die ZeileLog 1, "write error\n $_[0] Wert $_[1]";durchLog 1, "write error $_[0] Wert $_[1], er ".$m->last_error()." ex ".$m->last_except();ersetzen. Bei Schreibfehlern sollte im FHEM-Log Zeilen wie diese auftreten:
Zitat2013.12.14 19:16:17.169 1: write error 1 Wert 1, er 7 ex 1

Ein Liste der Fehler (Wert hinter 'er') und Exceptions (Wert hinter 'ex') findest du im Quellcode von MBclient.pm.

Grüße,

ChrisD


leibi

Hallo,

was bedeutet das:
                                  2013.12.14 19:55:31 1: write error 0 Wert 0, er 7 ex 3

Bin mir da in der MBclient nicht ganz schlüssig.

Markus

ChrisD

Beim Schreiben des Wertes 0 auf das Coil 0 tratt eine Exception auf, laut der Modbus-Spezifikation bedeutet Exception 3:
ZitatA value contained in the query data field is not an allowable value for the slave.  This indicates a fault in the structure of remainder of a complex request, such as that the implied length is incorrect. It specifically does NOT mean that a data item submitted for storage in a register has a value outside the expectation of the application program, since the MODBUS protocol is unaware of the significance of any particular value of any particular register.
Entweder hat MBclient ein ungültiges Paket zusammengebaut oder dein Server hat es nicht korrekt verstanden. Du kannst die Pakete auf der Console ausgeben lassen, dazu muss du am Anfang von write_modbus_coil (nach dem ersten {)$m->{debug}=1;und am Ende (vor dem letzten })$m->{debug}=0; hinzufügen. Auf der Console sollte dann beim Schreiben u.a. dies stehen:
ZitatTx
[xx xx 00 00 00 05] 01 05 00 00 00
Rx
...
Von Interesse ist hier was nach Rx als Antwort erscheint.

Grüße,

ChrisD


leibi

Hallo,

wenn ich das einfüge geht gar nichts mehr, leider.

Ist der MBClient eigentlich ein Modbus-Slave oder Master, da ja meine SPS sowie die Wago als Slave laufen.
Die Wago kann aber mit dem Baustein Modbus-Master von Codesys auch als solcher betrieben werden.
Falls beide als Slave laufen, kann ich mir vorstellen das das lesen(bei mir z.b. Temperaturwerte) gut klappt, aber das gegenseitige Schreiben wird Probleme machen. Funktioniert bei mir hin und wieder, aber nicht stabil, leider.

Gruß
Markus

ChrisD

Hallo,

Der Baustein sollte so aussehen:
sub
write_modbus_coil($$)
{
  $m->{debug}=1;
  if ($m->write_single_coil($_[0], $_[1])) {
    $m->close();
  } else {
    Log 1, "write error $_[0] Wert $_[1], er ".$m->last_error()." ex ".$m->last_except();
    $m = MBclient->new();
    # define server target
    $m->host("x.x.x.x");  # hier die IP-Adresse des Servers eintragen
    $m->unit_id(1);
  }
  $m->{debug}=0;
}

Die Begriffe Master und Slave gibt es bei Modbus TCP eigentlich nicht, sie sind für Modbus RTU. Bei Modbus TCP spricht man von Client und Server, dabei entspricht der Client dem Master (!) und der Server dem Slave. Server/Slave sind diejenigen die abgefragt werden, Client/Master sind diejenigen die die Anfragen stellen. Wenn FHEM mit der SPS kommuniziert ist FHEM Client (Master) und die SPS ist Server (Slave).

Ich habe mir nochmal die Modbus-Spzifikation durchgesehen und glaube dass MBclient das Paket falsch zusammengebaut hat. In meinem Beispielpaket (Schreiben von 0 auf Adresse 0) sind nur 5 Bytes Nutzdaten enthalten, es müssten aber 6 sein. Das Feld für den Datenwert muss laut Spezifikation 2 Bytes lang sein, MBclient sendet aber nur 1 Byte. Es ist möglich dass der Server-Baustein in der Wago die Länge nicht auswertet und nur das Datenfeld (muss 0x000 oder 0xff00 sein) überprüft. Dadurch funktioniert das Schreiben abhängig davon was im vorherigen Paket enthalten war.

Versuch mal die Zeile 373 in MBclient von
my $tx_buffer = $self->_mbus_frame(WRITE_SINGLE_COIL, pack("nC", $bit_addr, $bit_value));
in
my $tx_buffer = $self->_mbus_frame(WRITE_SINGLE_COIL, pack("nn", $bit_addr, $bit_value));
zu ändern.

Grüße,

ChrisD

leibi

Hallo ChrisD,

danke für deine Hilfe, machst du sowas eigentlich beruflich?

Es kommt leider immer noch:
2013.12.15 20:00:38 3: act_Garten_temp return value: 1
2013.12.15 20:00:39 3: act_Garten_Steckdose41 return value: 1
2013.12.15 20:00:39 1: write error 0 Wert 1, er 7 ex 3

MFG

ChrisD

#81
Hallo,

Die Byte-Order beim Schreiben der 1 ist noch falsch, dazu muss die Zeile 372 in MBclient von
$bit_value = ($bit_value) ? 0xFF : 0;in$bit_value = ($bit_value) ? 0xFF00 : 0;geändert werden. Nach einem reload MBclient sollte es funktionieren.

Grüße,

ChrisD

leibi

Hi,

jetzt habe ich das :
2013.12.15 20:33:08 3: act_EG_Ausgang1 return value: Undefined subroutine &main::write_single_coil called at (eval 34) line 1.

Wie kann das sein das mir fhem immer selber die Zeile mit webCmd ON:OFF meines Schalters selber löscht?

ChrisD

Ich habe meinen letzten Post editiert da ich übersehen hatte dass der Byte-Order falsch war. Die Meldung
Zitat2013.12.15 20:33:08 3: act_EG_Ausgang1 return value: Undefined subroutine &main::write_single_coil called at (eval 34) line 1.
kommt wahrscheinlich daher dass beim reload von 99_modbus (oder FHEM Neustart) ein Fehler aufgetreten ist und dadurch alle Funktionen aus der Datei nicht mehr verfügbar sind. In der Logdatei müsste eine entsprechende Meldung zu finden sein (Error:Modul 99_modbus deactivated). In der folgenden Zeile müsste der Fehler stehen.

Wann verschwindet die Zeile mit webCmd ?

Grüße,

ChrisD

leibi

Hallo,

die WebCmd wird immer wieder mal gelöscht, beim ausprobieren.

Jetzt geht wieder gar nichts mehr:
2013.12.15 21:35:12 3: at_read_EGTemperatur1: Undefined subroutine &main::read_holding_zaehler called at (eval 53) line 1.

2013.12.15 21:35:15 3: act_EG_Ausgang1 return value: Undefined subroutine &main::write_single_coil called at (eval 54) line 1.

Ich weiss nicht mehr was das sein kann, das Fhem hat bei mir irgendwie ein Eigenleben, es funktioniert erst alles, dann gar nichts mehr.

ChrisD

Hallo,

Hast du die Meldung 'Error:Modul 99_modbus deactivated' nicht in der Logdatei stehen ? Ich habe meine aktuellen Versionen von 99_modbus und MBclient mal angehängt damit du sie mit deinen vergleichen kannst.

Bei webCmd würde ich den Wert erneut eintragen, Save config anklicken und mit einem Editor überprüfen ob der Wert in fhem.cfg geschrieben wurde.

Grüße,

ChrisD

leibi

Hallo,

ich gebe es auf, danke für eure Hilfe, es funktioniert bei mir leider nichts.
Habe den Raspberry unf fhem schon zweimal komplett frisch aufgesetzt, Modbus geht dann kurz, dann gar nicht mehr.

Ich steige jetzt auf IP-Symcon um.

Gruß
Markus

leibi

Hallo,

ich habe mich nochmals selbst motiviert, und habs nochmal probiert.
Wie ich vermutet habe lags in der WebCmd( groß/klein Schreibung, Kopierfehler), jetzt funktioniert das Schreiben/Lesen über Modbus auf Wago sowie B&R SPS.
Wie kann ich am einfachsten den Schaltzustand über Icon's darstellen, bei meinen Versuchen blieben die SPS Ausgänge ständig gesetzt.?
Kann ich das Ereigniss/Ergebnis von der Modbus Komunikation, einer Variablen(z.b.FS20) übergeben, damit ich hier mit Codeschniebsel aus dem Board weiterkomme?

Gruß
Markus

ChrisD

Hallo,

Zur Darstellung des Zustandes kannst du ein Dummy verwenden. Den Zustand des digitalen Ausganges kannst du bei Wago direkt über Modbus auslesen, die Ausgänge belegen die Adressen 512 bis 1023. Zum Auslesen der Coils sollte dieser Code funktionieren:
sub
read_modbus_coil($) {
  my $coils = $m->read_coils($_[0], 1) ;
  my $ret="???";
 
  if(defined($coils)) {
    foreach my $coil (@$coils) {
      if ($coil==0) {
        $ret="off";
      } else {
        $ret="on";
      }
    }
    $m->close();
  } else {
    Log 2, "read error address $_[0], er ".$m->last_error()." ex ".$m->last_except();
    $m = MBclient->new();
    # define server target
    $m->host('hier IP-Adresse des Servers eintragen');
    $m->unit_id('hier unit_id eintragen');
  }
  return $ret;
}


Ausgang %Q0.0 sollte sich mit{read_modbus_coil(512)} auslesen lassen. Der Rückgabewert ist on oder off und sollte in FHEM direkt als Glühbirne angezeigt werden. Zum regelmäßigen Auslesen kannst du wieder ein 'at' verwenden, z.B.:
define q0 dummy
define at_read_q0 at +*00:00:05 {fhem "set q0 ".read_modbus_coil(512)}


Zum Schalten des Ausganges kannst du WebCmd verwenden wobei du 1 notify benötigst welches beim Ein- und Ausschalten den Befehl über Modbus sendet, z.B.:
attr q0 webCmd set_off:set_on
define n_set_q0 notify q0:set_. {if($EVENT eq 'set_off') {write_modbus(512,0)} else {write_modbus(512,1)}}
Falls das SPS-Programm den Ausgang jeden Zyklus selbst beschreibt wird dies natürlich nicht funktionieren, in dem Fall musst du über einen Merker fahren.

Wenn du eigene Icons verwenden möchtest kannst du das Attribut devStateIcon verwenden, Informationen dazu gibt es in der Commandref.

Wie die Vorgehensweise bei B&R ist kann ich dir nicht sagen, da ich diese nicht kenne.

Die meisten Codeschnipsel funktionieren auch mit einem Dummy. Du kannst aber auch FS20 anlegen:
define i0 FS20 0000 01
attr i0 dummy 1
define at_read_i0 at +*00:00:05 {fhem "set i0 ".read_modbus_coil(0)}
Die Zahlen hinter FS20 sollten eindeutig sein, Details sind in der Commandref. Schreiben ist mit FS20 schwieriger da set_on/off nicht verwendet werden können.

Damit FHEM sich nicht über ein fehlendes IODev beschwert solltest du zuerst noch einen virtuellen CUL anlegen:
define CUL CUL none 0000
attr CUL dummy 1


Grüße,

ChrisD

leibi

Hallo,

wie kann ich am einfachsten einen Sliderwert, auf ein Modbusregister schreiben?

Ich habe immernoch Probleme die Modbus Befehle mit anderen fehm Befehlen zu kombinieren?

Gruß
Markus