Hallo Ich habe ein Siemens Sentron Pac3200 (Ein Messgerät) von diesem möchte ich Daten per Modbus Auslesen. Ich bekomme auch Daten aber die Zusammensetzung ist mir schleierhaft Also bei 230v am Eingang bekomme ich auf der Adresse 1 0x43 und auf Adresse 2 x066 bei 232 bekomme ich 0x43+x068 Das ergibt nach meiner berechnung (0x43*256)=17152+102 = 17254 Und genau das wird auch in meiner Anwendung angezeigt. Wenn ich die Spannung trenne bekomme ich zwei mal 0. Auch auf anderen Adressen wie Leistung und Frequenz bekomme ich Daten aber ich finde nicht so recht wie ich die auswerten kann. Das Datenblatt von dem Gerät https://cache.industry.siemens.com/dl/files/150/26504150/att_906559/v1/A5E01168664A-04_DE_122016_201612221316291494.pdf
Da steht was von Float. Dann könnte noch sein dass die Reihenfolge vertauscht ist.
Also da ist irgendwas sehr komisch. Modbus hat immer 16Bit Register und du bekommst 2x8Bit zurück? Wenn man jeweils die oberen 8Bit als 0 ansieht, so kommt bei online hex->float konvertern nur Gülle raus. (egal welche Reihenfolge) https://www.h-schmidt.net/FloatConverter/IEEE754.html Kannste nochmal gucken ob due da was fehlerhaft ausließt? Werner M. schrieb: > Das ergibt nach meiner berechnung (0x43*256)=17152+102 = 17254 Wo auch immer du das her hast, so wandelt man kein float zu int um.
Das ist dann aber ein sehr beklopptes Format wenn man sich aus 2 16Bit Modbusregistern einen 16Bit float zusammenbauen muss. Dann steht da nichtmal float16, sondern float (das ist dann eigentlch 32Bit). Nunja ... Siemens eben ...
Die Beschreibung im Eröffnungsposting schreibt klar, daß je zwei Register zu einem Float-Wert zusammengefasst werden. Modbus kennt nur zwei Datentypen, das Register, das immer 16 Bit groß ist, und das Bit ("Coil"). Irgendwie mag ich an 16-Bit-Float verpackt in zwei nur zur Hälfte genutzten Register nicht glauben. Siemens ist zwar Weltmarktführer, wenn es ums inkompetente Stümpern geht, aber so etwas würde dem ganzen noch eine Sonderlocke aufsetzen, die ich selbst denen nicht zutraue. Ich tippe hier auf ein Interpretationsproblem. Interessant wäre es hier, die Rohdaten der Modbustelegramme zu sehen, d.h. den Hexdump der kompletten empfangenen Daten, die als Reaktion auf das Kommando Read Input Register bzw. Read Holding Register gesendet werden. Ein Tool, mit dem man Modbus-Geräten etwas auf die Schliche kommen kann, auch wenn es nicht die Telegramm-Rohdaten anzeigt, findet sich hier: https://www.the-sz.com/products/medford/ Damit kann man sich den Inhalt gleich mehrer Register in einem Rutsch anzeigen lassen.
Mw E. schrieb: > Modbus hat immer 16Bit Register und du bekommst 2x8Bit zurück? https://de.m.wikipedia.org/wiki/Modbus https://www.feldbusse.de/ModbusTCP/modbustcp_protokoll.shtml Laut der Unterlage https://cache.industry.siemens.com/dl/files/150/26504150/att_906559/v1/A5E01168664A-04_DE_122016_201612221316291494.pdf bezieht sich der Offset auf die Registernummer. Das Register selbst ist 16 Bit groß! Man sieht es an der IP Adresse, die 2 Register benötigt. Die IP Adresse ist 32 Bit lang (unsigned long). Die Daten werden im Big Endian Format gespeichert. https://de.m.wikipedia.org/wiki/Byte-Reihenfolge Die Frage ist was wird auf der 3. und 4. Adresse gespeichert. Es sollte 2x die Null sein!
Rufus Τ. F. schrieb: > Irgendwie mag ich an 16-Bit-Float verpackt in zwei nur zur Hälfte > genutzten Register nicht glauben. Es sind vermutlich 2 Bytes zu wenig ausgelesen worden. Daher 0x4366 statt 0x43660000 0x43 ist der Vorzeichen behaftete binäre Expont, und 0x660000 die Mantisse. Zwei Byte mehr einlesen, dann stimmt's. Die zwei unteren Bytes sind vermutlich nicht mehr relevant, da unter der Messgenauigkeit (<1%). Es kann sein, dass diese immer Null sind.
1 | #include <stdio.h> |
2 | |
3 | union U |
4 | {
|
5 | float f; |
6 | unsigned long i; |
7 | }u; |
8 | |
9 | |
10 | int main(void) |
11 | {
|
12 | |
13 | u.i = 0x43660000; |
14 | |
15 | printf("\r\n%f\r\n",u.f); |
16 | }
|
Manchmal ist es auch sehr verwirrend, dass die Modbus Adressen ab 1 gezählt werden, aber dann trotzdem als eine Adresse=0 übertragen wird. Ich hab das bisher noch nie kapiert, aber alle bisher verwendeten Displays am Modbus machen das so. In manchen Systemen läßt sich auch noch die Wort-Reihenfolge umschalten. 32bit floats funktionieren im Allgemeinen aber immer. Kinco hat einen double Eintrag, der aber nur Unfug anstellt, bzw. vielleicht hab ich es einfach noch nicht geschnallt.
Schorsch X. schrieb: > In manchen Systemen läßt sich auch noch die Wort-Reihenfolge umschalten Wort oder Bytereihenfolge (Endian)?
Schorsch X. schrieb: > Manchmal ist es auch sehr verwirrend, dass die Modbus Adressen ab 1 > gezählt werden, aber dann trotzdem als eine Adresse=0 übertragen wird. Es gibt insgesamt drei Arten, Registeradressen auf dem Modbus anzugeben. Zwei codieren die Art des Registers in die Registernummer, in der alten Variante waren so je 10000 Register je Typ möglich, und Registernummern begannen mit 1. 00001 - 10000 : Read/Write Coil 10001 - 20000 : Read Discrete Input 30001 - 40000 : Read Input Register 40001 - 50000 : Read/Write Holding Register (Adressen zwischen 20001 und 30000 sind undefiniert, Adressen ab 50001 ebenso) Die etwas neuere Variante fügt eine zusätzliche Null in die Adresse ein, so daß 65536 Register je Typ möglich werden: 000001 - 065536 : Read/Write Coil 100001 - 165536 : Read Discrete Input 300001 - 365536 : Read Input Register 400001 - 465536 : Read/Write Holding Register (diese neuere Notation soll zwingend mit führenden Nullen geschrieben werden, so daß bei Read/Write Coil klar ist, was gemeint ist) Diese beiden Formen sind überbestimmt, denn die Art des Registers wird im Modbusprotokoll durch den Code unabhängig von der Adressierung festgelegt. Zur weiteren Verwirrung wird manchmal auch der Begriff Offset verwendet. Aber all das sind nur unterschiedliche Darstellungsformen für ein und die selbe Angelegenheit - das eigentliche Protokoll ist davon komplett unberührt, das adressiert jeden Registertyp mit einer bei 0 beginnenden 16-Bit-Adresse. Was bei Modbus nicht festgelegt ist, und jedem Hersteller selbst überlassen bleibt, ist das Zusammenlegen mehrerer Register, um größere Datentypen als 16-Bit-Int zu transportieren. Die Wortreihenfolge muss in der Dokumentation beschrieben werden, bei besseren Geräten ist sie das auch, bei weniger guten muss man das durch Ausprobieren und Vergleichen mit (hoffentlich anderswoher bekannter) Werte bestimmen.
:
Bearbeitet durch User
@TO Ich arbeite gerade ein einer ähnlichen Sache, allerdings nicht Siemens sondern Entes (EPM-06CS). Bist Du Dir sicher das in den Registern eine Floatzahl steht? Bei dem von mir genannten Gerät sind alle Werte integer und müssen mit einem Koeffizienten bewertet werden. Die Werte stehen immer in einem 16Bit Registerpaar (also insgesamt 32Bit) Beispiel: Spannung L1-N steht im Register R0 und R1. R0 ist immer 0 und der Wert steht inh R1 als integer und muß mit 0.1 multpliziert werden. Dann kommt auch genau der Messwert raus. Ausnahme sind Register wo auch negative Werte stehen können COS PHI. Bei positiven Werten steht dann nur ein Wert im 2. Register des Paares, während bei negativen Werten im ersten Register immer -1 (65535) steht und im zweiten Register der eigentliche Wert, natürlich dann negativ. Google mal nach mbpoll. Das hat mir sehr weiter geholfen. Damit kann man für's erste die Register mal auslesen und sich ausgeben lassen.
Zeno schrieb: > Bist Du Dir sicher das in den Registern eine Floatzahl steht? Bei dem > von mir genannten Gerät sind alle Werte integer und müssen mit einem > Koeffizienten bewertet werden. Das ist geräteabhängig. Der Modbus-Standard selbst sieht weder float- noch 32-Bit-Übertragung vor, das ist eine zusätzliche hoffentlich in der Gerätedokumentation beschriebene Konvention.
Rufus Τ. F. schrieb: > Das ist geräteabhängig. Der Modbus-Standard selbst sieht weder float- > noch 32-Bit-Übertragung vor, das ist eine zusätzliche hoffentlich in > der Gerätedokumentation beschriebene Konvention. Naja so ins Detail bin ich da erst mal nicht eingestiegen, ich wollte nur das von mir genannte Gerät auslesen. Die Dokumentation von Entes ist da nicht so9 hilfreich, wenn man neu auf dem Gebiet ist und erst mal sehen will ob es überhaupt funktioniert. Das von mir genannte Programm hat dann aber sehr weiter geholfen und dann war auch die Dokumentation von Entes verständlich.
Hallo Werner, ich hatte mal eine ähnliche Aufgabe. Dazu mussten Siemens-Profibus-Daten die jeweils ein oder zwei 16bit-Register lang waren und dazu auch noch in verschiedenen Datenformaten vorlagen in 32-bit-Register einer Jetter-SPS übertragen und aufbereitet werden. Im nachfolgen Task 1 des SPS-Programms sieht man, welche 16-bit Siemens-Profibus-Daten wie zusammengesetzt und konvertiert werden musste, damit sinnvolle 32-bit-Daten entstehen. Es gibt ein paar Erläuterungen am Anfang des Tasks und anschließend ist der Programmcode kommentiert. Zuerst kommt die Kopierroutine, danach die Datenkonvertierung. Der Programmcode ist mit Absicht nicht auf maximale Effizienz sondern auf maximale Verständlichkeit ausgelegt. Vielleicht hilft das weiter. Ich könnte mir vorstellen, daß einige Modbus-Daten ähnlich konvertiert werden müssen: ------------------------------------------------------------------------ ----------- TASK 1 //Profibus-Daten übertragen und Formatkonvertierung //Datenformat "BOOL" (Bit) --> keine Formatkonvertierung notwendig, // jedoch beachten, daß HIGH-und LOW-Byte vertauscht sind. //-------------------------- //Datenformat "INTEGER" (Ganzzahl) --> Formatkonvertierung notwendig: //Daten vom 16-bit-Profibus-INTEGER-Format in das 32-bit-Jetter-INTEGER-Format konvertieren: //Grund: Im 16-bit-Profibus-INTEGER-Format befindet sich das Vorzeichen auf Bit 15. //Hinweis: Negative Zahlen werden als Zweierkomplement dargestellt. //Um in der Jetter-SPS das Vorzeichen korrekt verarbeiten zu können muß folgendes gemacht werden: // Bit 16 bis 31 mit Einsen auffüllen wenn Bit 15 (Vorzeichen Minus) gesetzt ist. //-------------------------- //Datenformat "REAL" (Gleitkommazahl) --> Formatkonvertierung notwendig: //Analogwerte im REAL-Format konvertieren: //Siemens-32-bit-Real-Zahlen werden als zwei aufeinanderfolgende // 16-bit-Profibus-Wörter übertragen. //Die beiden 16-bit-Profibus-Wörter landen Jetter-Seitig in zwei 32-bit-Registern // und müssen anschließend wieder lagerichtig zusammengesetzt werden. //Das Ergebnis ist ein 32-bit Integer-Register, welche die korrekte Bitfolge enthält. //Diese muß anschließend noch als "Real"-Wert gemäß "IEE 754" interpretiert werden. //-------------------------- LABEL 10 //Sprungmarke //Die nachfolgende Schleife dient dazu 120 Register aus dem Profibusmodul in die SPS zu kopieren. // Es werden die Register 12400 bis 12519 in die Register 400 bis 519 kopiert. // Da der Kopierbefehl nicht unterbrechbar ist, werden nicht alle Register auf einmal kopiert. WHEN FLAG 1 //Wenn "Profibus-Konfiguration erfolgreich" // AND BIT_CLEAR (12100, 6) //und gerade keine Profibus-Daten ausgetauscht werden THEN //dann REG 580 = 12400 //Adressregister mit der Nummer des Profibus-Startregisters laden REG 581 = 400 //Adressregister mit der Nummer des SPS-Startregisters laden LABEL 17 //Sprungmarke COPY (20, @580, @581) //Kopiere 20 Register vom Profibus-Modul in die SPS (indirekte Adressierung) REG 580 = REG 580 + 20 //Erhöhe den Inhalt des Profibus-Adressregisters um 20 REG 581 = REG 581 + 20 //Erhöhe den Inhalt des SPS-Adressregisters um 20 IF REG 581 > 519 //Wenn die Schleife bis zur letzten Adresse durchgezählt hat THEN GOTO 18 //dann gehe zur angegebenen Sprungmarke ELSE GOTO 17 //ansonsten gehe zur angegebenen Sprungmarke LABEL 18 //Sprungmarke //Daten im INTEGER-Format konvertieren: //Die nachfolgende Schleife dient dazu die Register 418 bis 451 zu adressieren // und dort die oben beschriebene Konvertierung durchzuführen. REG 590 = 418 //Adressregister mit der Nummer des Startregisters laden (indirekte Adressierung) LABEL 11 //Sprungmarke IF BIT_SET (@590, 15) //Wenn Bit 15 (Vorzeichen Minus) vom indirekt adressierten Register gesetzt ist, THEN REG @590 = REG @590 WOR 0b11111111111111110000000000000000 //dann fülle die ersten 16 Bit mit Einsen auf ELSE REG @590 = REG @590 WAND 0b00000000000000001111111111111111 //ansonsten fülle die ersten 16 Bit mit Nullen auf THEN //dann REGINC 590 //Erhöhe den Inhalt des Adressregisters um 1 IF REG 590 > 451 //Wenn die Schleife bis zur letzten Adresse durchgezählt hat THEN GOTO 12 //dann gehe zur angegebenen Sprungmarke ELSE GOTO 11 //ansonsten gehe zur angegebenen Sprungmarke LABEL 12 //Sprungmarke //Alle Vorzeichen-konvertierten INTEGER-Register auf einen neuen Registerbereich kopieren zwecks Weiterverarbeitung. COPY (34, 418, 618) //kopiere die an erster Stelle genannte Anzahl von Registern //vom danach genannten Register beginnend, auf das zu Schluß genannte Register und folgende. //---------------------------------------------------------------- //Daten im REAL-Format konvertieren: //Die nachfolgende Schleife dient dazu die Register 452 bis 507 zu adressieren // und dort die oben beschriebene Konvertierung durchzuführen. REG 591 = 20000 //Adressregister mit der Nummer des Startregisters K2 laden (indirekte Adressierung) REG 592 = 452 //Adressregister mit der Nummer des Startregisters K1a laden (indirekte Adressierung) REG 593 = 453 //Adressregister mit der Nummer des Startregisters K1b laden (indirekte Adressierung) LABEL 13 //Sprungmarke SHIFT_LEFT (@592, 16) //Im genannten Register werden die Bits 16 Stellen nach links verschoben REG @591 = REG @592 WOR REG @593 //Die rechten 16 Bits vom zweiten Register werden in das erste // Register übertragen und in ein (Gleitkomma-definierbares) Register kopiert. REGINC 591 //Erhöhe den Inhalt des Adressregisters um 1 REGINC 592 //Erhöhe den Inhalt des Adressregisters um 1 REGINC 592 //Erhöhe den Inhalt des Adressregisters nochmal um 1 (also insgesamt um 2) REGINC 593 //Erhöhe den Inhalt des Adressregisters um 1 REGINC 593 //Erhöhe den Inhalt des Adressregisters nochmal um 1 (also insgesamt um 2) IF REG 593 > 507 //Wenn die Schleife bis zur letzten Adresse durchgezählt hat THEN GOTO 14 //dann gehe zur angegebenen Sprungmarke ELSE GOTO 13 //ansonsten gehe zur angegebenen Sprungmarke LABEL 14 //Sprungmarke REGISTER_LOAD (2909, 20000) //Beginn der Gleitkommaregister auf diese Adresse umschalten //Dadurch werden die Bits in diesen Registern jetzt als Gleitkommazahl interpretiert. COPY (28, 20000, 65024) //Kopiere die an erster Stelle genannte Anzahl von Registern //vom danach genannten Register beginnend, auf das zu Schluß genannte Register und folgende. //Sinn dieser Aktion ist es, die zuvor auf Gleitkomma umgeschalteten Registerinhalte in den //Standard-Gleitkommabereich zu kopieren, damit die Ursprungsregister wieder auf //Ganzzahl zurückgeschaltet werden können. REGISTER_LOAD (2909, 65024) //Beginn der Gleitkommaregister auf diese Adresse (Standard) umschalten //Dadurch werden die Bits in den davorliegenden Registern wieder als Ganzzahl interpretiert. //---------------------------------------------------------------- //Daten im INTEGER-Format konvertieren: //Die nachfolgende Schleife dient dazu die Register 508 bis 519 zu adressieren // und dort die oben beschriebene Konvertierung durchzuführen. REG 594 = 508 //Adressregister mit der Nummer des Startregisters laden (indirekte Adressierung) LABEL 15 //Sprungmarke IF BIT_SET (@594, 15) //Wenn Bit 15 (Vorzeichen Minus) vom indirekt adressierten Register gesetzt ist, THEN REG @594 = REG @594 WOR 0b11111111111111110000000000000000 //dann fülle die ersten 16 Bit mit Einsen auf ELSE REG @594 = REG @594 WAND 0b00000000000000001111111111111111 //ansonsten fülle die ersten 16 Bit mit Nullen auf THEN //dann REGINC 594 //Erhöhe den Inhalt des Adressregisters um 1 IF REG 594 > 519 //Wenn die Schleife bis zur letzten Adresse durchgezählt hat THEN GOTO 16 //dann gehe zur angegebenen Sprungmarke ELSE GOTO 15 //ansonsten gehe zur angegebenen Sprungmarke LABEL 16 //Sprungmarke //Alle Vorzeichen-konvertierten INTEGER-Register auf einen neuen Registerbereich kopieren zwecks Weiterverarbeitung. COPY (12, 508, 708) //kopiere die an erster Stelle genannte Anzahl von Registern //vom danach genannten Register beginnend, auf das zu Schluß genannte Register und folgende. GOTO 10 //dann gehe zur Sprungmarke (Task-Anfang)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.