ModBus TCP Interface
Moderator: Co-Administratoren
- Black
- Beiträge: 5483
- Registriert: 12.09.2015, 22:31
- System: Alternative CCU (auf Basis OCCU)
- Wohnort: Wegberg
- Hat sich bedankt: 424 Mal
- Danksagung erhalten: 1074 Mal
- Kontaktdaten:
Re: ModBus TCP Interface
32Bit Float entspricht ja dem Datentyp Single bei aktuellen Hochsprachen
Entweder sich für sie Umsetzung kleines Programm in einem CrossCompiler schreiben
oder
gucken ob der integrierte TCL die convertierung mit dem Datentyp beherrscht
oder
gemäß https://en.wikipedia.org/wiki/Single-pr ... int_format sich selber die Umrechnung coden
Black
Entweder sich für sie Umsetzung kleines Programm in einem CrossCompiler schreiben
oder
gucken ob der integrierte TCL die convertierung mit dem Datentyp beherrscht
oder
gemäß https://en.wikipedia.org/wiki/Single-pr ... int_format sich selber die Umrechnung coden
Black
Wenn das Fernsehprogramm immer mehr durch nervende Werbung unterbrochen wird und der Radiomoderator nur noch Müll erzählt, ist es besser, die Zeit für sinnvolle Dinge zu nutzen -
mal aufs Klo zu gehen, ein Bier zu holen oder einfach mal den roten AUS-Knopf zu drücken. Klick - und weg
Script Time Scheduler V1.3
AstroSteuerung über Zeitmodul flexibel mit Offset / spätestens, frühestens
SDV 5.03.01 Das umfassende Entwicklungs und Diagnosetool für Homematik
Selektive Backups - Nützliche Dinge, die die WebUI nicht kann
Intel NUC6 Celeron 16GB mit 512GB SSD unter Proxxmox mit insgesamt 5 VM: 2 x bloatwarebefreiter Raspberrymatik, 2 x IOBroker als Middleware und einer MariaDB zur Archivierung. Verbrauch: 6W
technical contribution against annoying advertising
mal aufs Klo zu gehen, ein Bier zu holen oder einfach mal den roten AUS-Knopf zu drücken. Klick - und weg
Script Time Scheduler V1.3
AstroSteuerung über Zeitmodul flexibel mit Offset / spätestens, frühestens
SDV 5.03.01 Das umfassende Entwicklungs und Diagnosetool für Homematik
Selektive Backups - Nützliche Dinge, die die WebUI nicht kann
Intel NUC6 Celeron 16GB mit 512GB SSD unter Proxxmox mit insgesamt 5 VM: 2 x bloatwarebefreiter Raspberrymatik, 2 x IOBroker als Middleware und einer MariaDB zur Archivierung. Verbrauch: 6W
technical contribution against annoying advertising
-
- Beiträge: 93
- Registriert: 17.04.2013, 16:40
Re: ModBus TCP Interface
Oh das ist für mich zu kompliziert - dem kann ich nicht mehr folgen
Ich habe einfach die Sachen von Indi55 (danke dafür nochmal) in die Verzeichnisse kopiert und dann im Script die Adressen angepasst die ich brauche.
Habe mir die TCL zwar mal angeschaut aber leider nur Bahnhof gesehen.
Kann man mit 32Bit denn keine größere Zahl darstellen oder was passiert ab 32000, weil bis dahin wird die Zahl ja richtig ausgelesen.
Ich habe einfach die Sachen von Indi55 (danke dafür nochmal) in die Verzeichnisse kopiert und dann im Script die Adressen angepasst die ich brauche.
Habe mir die TCL zwar mal angeschaut aber leider nur Bahnhof gesehen.
Kann man mit 32Bit denn keine größere Zahl darstellen oder was passiert ab 32000, weil bis dahin wird die Zahl ja richtig ausgelesen.
-
- Beiträge: 21
- Registriert: 12.05.2016, 11:47
Re: ModBus TCP Interface
Also ich werde aus dieser Library /usr/local/addons/modbus/modbus.tcl, die vom modbus_interface.tcl verwendet wird auch nicht schlau.
Das hier scheint ja irgendwie der Programmteil "read holding registers" zu sein:
Ich hab aber keine Ahnung, wie man hier den zurückgegebenen Datentyp anpassen sollte.
Das müsste sich mal jemand anschauen, der sich auskennt mit tcl...
Das hier scheint ja irgendwie der Programmteil "read holding registers" zu sein:
Code: Alles auswählen
proc ::modbus::cmd03_pack {sta addr len} {
# function : read holding registers
# station : 1 byte
# function : 1 byte (always 0x03)
# addr : 2 bytes
# read len : 2 bytes (how much registers)
# response
#station : 1 byte
#function : 1 byte (always 0x03)
#byte count : 1 byte
#data : N*2 bytes (reg1_low...reg1_hi...reg2_low...reg2_hi...)
# 1+1+1+2*len
# sta=>1 fun=>1 dlen=>1
# return [list [binary format ccSS $sta 0x03 $addr $len] [expr 1+1+1+2*$len]]
return [list [binary format ccSS $sta 0x03 $addr $len] [expr 1+1+1+2*$len]]
}
proc ::modbus::cmd03_unpack {reqCmd rspCmd} {
# response
#station : 1 byte
#function : 1 byte (always 0x03)
#byte count : 1 byte
#data : N*2 bytes (reg1_low...reg1_hi...reg2_low...reg2_hi...)
if {[string range $reqCmd 0 1] != [string range $rspCmd 0 1]} {return [list]}
if {[binary scan [string range $reqCmd 4 5] S reqBytes] == 0} {return [list]}
set data [string range $rspCmd 3 end]
set len [string length $data]
set ret [list]
for {set i 0} {$i < $len} {incr i} {
binary scan [string range $data $i [incr i]] S byte
lappend ret $byte
}
return $ret
}
Das müsste sich mal jemand anschauen, der sich auskennt mit tcl...
Re: ModBus TCP Interface
Hallo Zusammen !
sehr interessant das ganze - ich scheitere zur Zeit noch am EM24
Frage an Mario, kannst Du hier veröffentlichen wie Du den EM24 ausliest ?
Ich erhalte immer nur 0 zurück.
Möchte hier am Ende mit dem Überschuss den stufenlosen E-Heizstab (ATON) füttern.
(steuer ich über PWM an - das funktioniert schon ganz gut)
Gruß in die Runde, Thorsten
sehr interessant das ganze - ich scheitere zur Zeit noch am EM24
Frage an Mario, kannst Du hier veröffentlichen wie Du den EM24 ausliest ?
Ich erhalte immer nur 0 zurück.
Möchte hier am Ende mit dem Überschuss den stufenlosen E-Heizstab (ATON) füttern.
(steuer ich über PWM an - das funktioniert schon ganz gut)
Gruß in die Runde, Thorsten
-
- Beiträge: 19
- Registriert: 10.03.2020, 11:12
- System: Alternative CCU (auf Basis OCCU)
- Wohnort: Köln
- Hat sich bedankt: 4 Mal
- Danksagung erhalten: 1 Mal
Re: ModBus TCP Interface
Man kann auf die Schnelle eine weitere Funktion "13" einbauen, die dann bei Länge 2 die Umrechnung macht.richard.mayer hat geschrieben: ↑11.07.2022, 21:22Das hier scheint ja irgendwie der Programmteil "read holding registers" zu sein:
Ich hab aber keine Ahnung, wie man hier den zurückgegebenen Datentyp anpassen sollte.
Das müsste sich mal jemand anschauen, der sich auskennt mit tcl...
Einfach das hier in die modbus.tcl einfügen z.B. unterhalb der cmd03_unpack:
Code: Alles auswählen
proc ::modbus::cmd13_pack {sta addr len} {
# function : read holding registers
# station : 1 byte
# function : 1 byte (always 0x03)
# addr : 2 bytes
# read len : 2 bytes (how much registers)
# response
#station : 1 byte
#function : 1 byte (always 0x03)
#byte count : 1 byte
#data : N*2 bytes (reg1_low...reg1_hi...reg2_low...reg2_hi...)
# 1+1+1+2*len
# sta=>1 fun=>1 dlen=>1
# return [list [binary format ccSS $sta 0x03 $addr $len] [expr 1+1+1+2*$len]]
return [list [binary format ccSS $sta 0x03 $addr $len] [expr 1+1+1+2*$len]]
}
proc ::modbus::cmd13_unpack {reqCmd rspCmd} {
# response
#station : 1 byte
#function : 1 byte (always 0x03)
#byte count : 1 byte
#data : N*2 bytes (reg1_low...reg1_hi...reg2_low...reg2_hi...)
if {[string range $reqCmd 0 1] != [string range $rspCmd 0 1]} {return [list]}
if {[binary scan [string range $reqCmd 4 5] S reqBytes] == 0} {return [list]}
set data [string range $rspCmd 3 end]
set len [string length $data]
set ret [list]
for {set i 0} {$i < $len} {incr i} {
binary scan [string range $data $i [incr i]] S byte
lappend ret $byte
}
if { $len == 2 } {
if { $ret < 0 && $ret != "" } {
set ret [ expr 65536 + $ret ]
}
}
return $ret
}
Code: Alles auswählen
tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 03 30535 10 | /usr/bin/awk '{print $2}'
Code: Alles auswählen
tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 13 30535 10 | /usr/bin/awk '{print $2}'
Wenn du eine Doku zu den Registern hast und etwas Code-nahe Fleißarbeit nicht scheust, kann man das auch schöner machen und mit einer Abfrage mehr oder alle Werte auf einen Rutsch / Aufruf auslesen.
Viele Grüße,
Jens
-
- Beiträge: 21
- Registriert: 12.05.2016, 11:47
Re: ModBus TCP Interface
Vielen Dank für die Rückmeldung,
ich habe die Anpassung mit der if-Schleife als cmd13 eingefügt und grundsätzlich scheint die Abfrage zu funktionieren.
Jetzt sitze ich gespannt vor der Status-Anzeige und warte darauf, dass die 32kWh gerissen werden...
Zu dem zweiten Thema:
Mehrere Register in einem Rutsch auszulesen würde wahrscheinlich wirklich Sinn machen.
Ich verwende die Werte in Homematic als Systemvariablen für eine AIO Creator Neo Statusanzeige und für das Schalten einen Warmwasserheizstabs und eines Luftentfeuchters.
Das sind 5 Register, die ich momentan alle 10 Sekunden mit modbus_interface.tcl auslese.
Wider Erwarten funktioniert das sogar stabil und weder Raspberrymatic noch der SMA-WR haben ein Problem mit dem häufigen Auslesen.
Aber bzgl. Effizienz wäre es wahrscheinlich wirklich cooler, mehrer Werte auf einmal auszulesen...
Schöne Grüße und besten Dank
Ich werden berichten, ob die Darstellung ab 32kWh auch noch korrekt ist.
ich habe die Anpassung mit der if-Schleife als cmd13 eingefügt und grundsätzlich scheint die Abfrage zu funktionieren.
Jetzt sitze ich gespannt vor der Status-Anzeige und warte darauf, dass die 32kWh gerissen werden...
Zu dem zweiten Thema:
Mehrere Register in einem Rutsch auszulesen würde wahrscheinlich wirklich Sinn machen.
Ich verwende die Werte in Homematic als Systemvariablen für eine AIO Creator Neo Statusanzeige und für das Schalten einen Warmwasserheizstabs und eines Luftentfeuchters.
Das sind 5 Register, die ich momentan alle 10 Sekunden mit modbus_interface.tcl auslese.
Wider Erwarten funktioniert das sogar stabil und weder Raspberrymatic noch der SMA-WR haben ein Problem mit dem häufigen Auslesen.
Aber bzgl. Effizienz wäre es wahrscheinlich wirklich cooler, mehrer Werte auf einmal auszulesen...
Schöne Grüße und besten Dank
Ich werden berichten, ob die Darstellung ab 32kWh auch noch korrekt ist.
- funkleuchtturm
- Beiträge: 2368
- Registriert: 13.06.2011, 16:42
- Hat sich bedankt: 23 Mal
- Danksagung erhalten: 357 Mal
- Kontaktdaten:
Re: ModBus TCP Interface
Ich hab bei meinem Umrichter (Kostal Piko IQ) 32bit float Zahlen, also Länge gleich 4 Bytes.
Werden mit dieser Änderung nun 16bit float oder 32bit float dekodiert ??
Die normale Abfrage von einfachen 2Byte-Integerzahlen funktioniert einwandfrei
die Dekodierung von 32bit-float mit der neuen Funktion '13' funktioniert leider nicht.
Viele Gruesse
Eugen
________________________________________________
SmartHome-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI, den WEATHERMAN-2, den PULSECOUNTER und den AIRSNIFFER
mit vielen Kochrezepten für den ambitionierten Homematiker
Eugen
________________________________________________
SmartHome-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI, den WEATHERMAN-2, den PULSECOUNTER und den AIRSNIFFER
mit vielen Kochrezepten für den ambitionierten Homematiker
-
- Beiträge: 21
- Registriert: 12.05.2016, 11:47
Re: ModBus TCP Interface
Bei mir tut es mit der Änderung leider auch noch nicht:
Laut Doku ist die "Anzahl zusammenhängender SMA Register" = 2, "Datentyp SMA" = U32, "Datenformat SMA" = FIX0.
Code: Alles auswählen
root@ccu:~# tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 13 30535 2
0 -29656root@ccu:~#
root@ccu:~# while true; do date; tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 13 30535 10 | /usr/bin/awk '{print $2}'; sleep 5; done
Thu Jul 14 13:53:01 CEST 2022
32739
Thu Jul 14 13:53:06 CEST 2022
32749
Thu Jul 14 13:53:11 CEST 2022
32755
Thu Jul 14 13:53:16 CEST 2022
32765
Thu Jul 14 13:53:21 CEST 2022
-32764
Thu Jul 14 13:53:27 CEST 2022
-32754
Thu Jul 14 13:53:32 CEST 2022
-32748
Thu Jul 14 13:53:37 CEST 2022
-32738
Thu Jul 14 13:53:42 CEST 2022
-32731
Thu Jul 14 13:53:47 CEST 2022
-32721
Thu Jul 14 13:53:52 CEST 2022
-32715
- funkleuchtturm
- Beiträge: 2368
- Registriert: 13.06.2011, 16:42
- Hat sich bedankt: 23 Mal
- Danksagung erhalten: 357 Mal
- Kontaktdaten:
Re: ModBus TCP Interface
Um mit dem originalen TCL-Skript auch Gleitkommavariablen (32bit-float) von meinem Solar-Umrichter Kostal Piko IQ auszuwerten, habe ich das hier beschriebene HM-Skript erstellt. Dieses Skript rufe ich alle 60sec auf und hole damit vom Umrichter die gewünschten Messwerte ab.
Besonders interessant für die Hauautomation ist die aktuelle vom Umrichter abgegebene Leistung im 32bit-float-Format. Um herauszufinden, auf welcher Modbus-Adresse diese Information verfügbar ist, kann man mit diesem kostenlosen "Modbus Master Simulator" die verschiedene "Holding Register" in verschiedenen Zahlenformaten ansehen.
Bei mir liegt die abgegebene AC-Leistung auf Adresse 172, die device ID ist 71 und der Port ist 1502 (meist ist der Port 502). Mit diesen Informationen wird das nachfolgende HM-Skript angepasst:
Vorher muß man natürlich die TCL-Programme von Indi55 installieren und eine Systemvariable "kostal_leistung" im Format "Zahl" anlegen, auf welche die Leistung im Takt des Skriptaufrufes repliziert wird. Die Leistung wird in kW angezeigt.
Besonders interessant für die Hauautomation ist die aktuelle vom Umrichter abgegebene Leistung im 32bit-float-Format. Um herauszufinden, auf welcher Modbus-Adresse diese Information verfügbar ist, kann man mit diesem kostenlosen "Modbus Master Simulator" die verschiedene "Holding Register" in verschiedenen Zahlenformaten ansehen.
Bei mir liegt die abgegebene AC-Leistung auf Adresse 172, die device ID ist 71 und der Port ist 1502 (meist ist der Port 502). Mit diesen Informationen wird das nachfolgende HM-Skript angepasst:
Code: Alles auswählen
!modbus_tcp 32bit float Register auslesen mit TCL skript
!https://homematic-forum.de/forum/viewtopic.php?f=26&t=55722&hilit=tcl+script#p553720
!Installation:
!Schritt 1: mit WinSCP im CCU-verzeichnis /usr/local/addons/ ein Unterverzeichnis modbus anlegen
!Schritt 2: in dieses neue Verzeichnis die tcl-Files modbus.tcl und modbus_interface.tcl reinkopieren
!Schritt 3: Das folgende HM-Skript mit den Registernummern und Daten des eigenen Umrichters anpassen
!Schritt 4: Dieses HM-Skript auf der CCU mit Steuerprogramm z.B. alle 60sec aufrufen
!Schritt 5: Systemvariable "kostal_leistung" vom Typ Zahl auf der CCU anlegen
string lGetOut;
string lGetErr;
system.Exec("tclsh /usr/local/addons/modbus/modbus_interface.tcl 192.168.178.35 1502 71 03 172 2",&lGetOut,&lGetErr);
!system.Exec("tclsh /usr/local/addons/modbus/modbus_interface.tcl < IP > port ID 03 adres 2",&lGetOut,&lGetErr);
var hword = lGetOut; !WriteLine(hword);
integer space_pos = hword.Find(" "); !WriteLine(space_pos);
var lword = 0 + hword.Substr(0,space_pos);
if(lword < 0) {lword = lword + 32768;} !WriteLine(lword);
hword = 0 + hword.Substr(space_pos);
if(hword < 0) {hword = hword + 32768;} !WriteLine(hword);
integer hochzahl = hword / 128; !WriteLine(hochzahl);
if( (hochzahl & 128) > 0) {hochzahl = 1 + (hochzahl & 127);} else {hochzahl = -128 + 1 + (hochzahl & 127);}
real mantisse = 1.0;
if( (hword & 64) > 0) {mantisse = mantisse + 0.5; }
if( (hword & 32) > 0) {mantisse = mantisse + 0.25; }
if( (hword & 16) > 0) {mantisse = mantisse + 0.125; }
if( (hword & 8 ) > 0) {mantisse = mantisse + 0.0625; }
if( (hword & 4 ) > 0) {mantisse = mantisse + 0.03125; }
if( (hword & 2 ) > 0) {mantisse = mantisse + 0.015625; }
if( (hword & 1 ) > 0) {mantisse = mantisse + 0.0078125; }
if( (lword & 32768) > 0) {mantisse = mantisse + 0.00390625; }
if( (lword & 16384) > 0) {mantisse = mantisse + 0.001953125; }
if( (lword & 8182 ) > 0) {mantisse = mantisse + 0.0009765625; }
if( (lword & 4096 ) > 0) {mantisse = mantisse + 0.00048828125; }
if( (lword & 2048 ) > 0) {mantisse = mantisse + 0.000244140625; }
if( (lword & 1024 ) > 0) {mantisse = mantisse + 0.0001220703125; }
if( (lword & 512 ) > 0) {mantisse = mantisse + 0.0000610351562; }
if( (lword & 256 ) > 0) {mantisse = mantisse + 0.0000305175781; }
if( (lword & 128) > 0) {mantisse = mantisse + 0.0000152587890; }
if( (lword & 64 ) > 0) {mantisse = mantisse + 0.0000076293945; }
if( (lword & 32 ) > 0) {mantisse = mantisse + 0.0000038146972; }
if( (lword & 16 ) > 0) {mantisse = mantisse + 0.0000019073486; }
if( (lword & 8 ) > 0) {mantisse = mantisse + 0.0000009536743; }
if( (lword & 4 ) > 0) {mantisse = mantisse + 0.0000004768371; }
if( (lword & 2 ) > 0) {mantisse = mantisse + 0.0000002384185; }
if( (lword & 1 ) > 0) {mantisse = mantisse + 0.0000001192092; }
mantisse = mantisse * hochzahl.Exp2();
if( (hword & 32768) > 0) {mantisse = (-1) * mantisse;}
dom.GetObject('kostal_leistung').State(0.001* mantisse);
WriteLine(mantisse);
Viele Gruesse
Eugen
________________________________________________
SmartHome-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI, den WEATHERMAN-2, den PULSECOUNTER und den AIRSNIFFER
mit vielen Kochrezepten für den ambitionierten Homematiker
Eugen
________________________________________________
SmartHome-Eintopf mit feinem Homeduino-Gemüse
... und für Feinschmecker gibt´s den WIFFI, den WEATHERMAN-2, den PULSECOUNTER und den AIRSNIFFER
mit vielen Kochrezepten für den ambitionierten Homematiker
-
- Beiträge: 19
- Registriert: 10.03.2020, 11:12
- System: Alternative CCU (auf Basis OCCU)
- Wohnort: Köln
- Hat sich bedankt: 4 Mal
- Danksagung erhalten: 1 Mal
Re: ModBus TCP Interface
Du lässt 10 Register auf einmal abfragen - im Code habe ich die Abfrage fix auf die Länge für 1 Register gesetzt - wirklich nur ein "dirty hack"... Wenn SMA da 2 Register hat, müsste ich nochmal fies nachdenken, dass ich das auch noch reinkriege.richard.mayer hat geschrieben: ↑14.07.2022, 14:36Bei mir tut es mit der Änderung leider auch noch nicht:
Laut Doku ist die "Anzahl zusammenhängender SMA Register" = 2, "Datentyp SMA" = U32, "Datenformat SMA" = FIX0.Code: Alles auswählen
root@ccu:~# while true; do date; tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 13 30535 10 | /usr/bin/awk '{print $2}';
Versuch mal:
Code: Alles auswählen
root@ccu:~# while true; do date; tclsh /usr/local/addons/modbus/modbus_interface.tcl wr1.mayer 502 3 13 30535 1 | /usr/bin/awk '{print $2}';
Für SolarEdge habe ich mir das hier zusammengebaut, danach hatte ich etwas mehr Blick für TCL - ist aber leider schon wieder verschüttet... 2020 hatte man mehr Zeit . Das kann man im Prinzip auch für anderes erweitern. Float-Konvertierung gibt es wie gesagt nicht und man muss die Fleißarbeit investieren die Register zu verdrahten mit Text.
Viele Grüße
Jens