Alle Lektionen anzeigen
Teil 1
Grundlagen
Teil 2
Modbus RTU
- Lektion 5RS485 erklärt: A, B, Common und Terminierung20 Min.
- Lektion 6Baudrate und Parität: warum 8E1 Standard ist16 Min.
- Lektion 7Das Modbus RTU Frame Byte für Byte, plus CRC18 Min.
- Lektion 8Mehrere Modbus Geräte an einem RS485-Bus16 Min.
- Lektion 9Ihr erstes Modbus Gerät mit mbpoll auslesen22 Min.
- Lektion 10Modbus RTU Fehlersuche: vom Symptom zur Ursache20 Min.
Teil 3
Modbus TCP
Teil 4
Fortgeschritten
- Lektion 16Sicher auf ein Modbus Gerät schreiben18 Min.
- Lektion 17Word Order und Float: gleiche Bytes, anderer Wert22 Min.
- Lektion 18Poll-Intervall und Buslast selbst berechnen18 Min.
- Lektion 19Modbus Sicherheit: das Protokoll hilft nicht16 Min.
- Lektion 20Modbus integrieren: SPS, Home Assistant, Cloud20 Min.
- Lektion 21Modbus Inbetriebnahme: Checkliste und Spickzettel18 Min.
Word Order und Float: gleiche Bytes, anderer Wert
Die Modbus Word Order entscheidet, ob Sie 230,5 oder reinen Unsinn lesen. Lernen Sie die vier Varianten, IEEE 754 Floats, Skalierung und Sentinel-Werte.
Was diese Lektion behandelt
- Die vier Varianten, in denen zwei Register einen Float32 bilden
- Der Plausibilitätstest, der die richtige Word Order findet
- Sentinel-Werte, und warum ein Energiezähler nicht in einen Float32 passt
Vorher lesen: Modbus Adressierung: von 40001 zur Adresse, Eine Modbus Registertabelle richtig lesen
Die Word Order entscheidet, ob aus vier Bytes eine Netzspannung von 230,5 V wird oder eine Zahl in der Größenordnung von 10 hoch 23. Modbus legt die Reihenfolge innerhalb eines Registers fest, zwischen zwei Registern aber nicht, und diese Lücke füllt jeder Hersteller selbst. Nach dieser Lektion bauen Sie einen Float32 aus zwei Registern, probieren die vier Varianten durch und entscheiden über die Plausibilität, welche davon stimmt.
Was der Standard festlegt und was nicht
Festgelegt ist genau eine Sache: innerhalb eines Registers kommt das höherwertige Byte zuerst. Die Spezifikation zeigt das an der 16-Bit-Zahl 0x1234, bei der 0x12 vor 0x34 auf die Leitung geht, und wiederholt es bei jedem lesenden Funktionscode.
Nicht festgelegt ist, in welcher Reihenfolge zwei Register stehen, wenn sie zusammen einen 32-Bit-Wert bilden. Das Datenmodell kennt Bits und 16-Bit-Register, mehr nicht. Ein Float32 oder ein uint32 existiert darin gar nicht als Typ, er ist eine Vereinbarung zwischen Hersteller und Client. Deshalb hat Ihre Software einen Schalter dafür, und deshalb ist dieser Schalter kein Fehler im Protokoll. Am besten dokumentiert ist die SunSpec-Konvention, nachzulesen in der Einführung zu SunSpec über Modbus.
Einen Float32 aus zwei Registern bauen
Nehmen Sie eine echte Messung: 230,5 V als Float32 über zwei aufeinanderfolgende Holding-Register. Das Datenblatt sagt Ihnen, ab welcher Adresse die beiden stehen, das Lesen einer solchen Zeile steht in der Lektion Registertabelle lesen.
| Register | Rohwert | Bytes |
|---|---|---|
| Register n | 0x4366 | 43 66 |
| Register n+1 | 0x8000 | 80 00 |
Aneinandergehängt sind das die vier Bytes 43 66 80 00, also 0x43668000. Aufgeschlüsselt:
| Feld | Bits | Wert |
|---|---|---|
| Vorzeichen | 1 | 0, also positiv |
| Exponent | 8 | 0x86 ist 134, minus Bias 127 ergibt 7 |
| Mantisse | 23 | 6.717.440 von 8.388.608, also 0,80078125 |
Die Rechnung: (1 + 0,80078125) x 2^7 ist 1,80078125 x 128 und damit 230,5. Erst jetzt die allgemeine Regel, kurz: ein Float32 besteht aus 1 Vorzeichenbit, 8 Exponentenbits und 23 Mantissenbits, und der Exponent trägt den Bias 127.
Ein zweites Beispiel, das sich in genau einem Punkt unterscheidet. Der Zählerstand 1.234.567 Wh ist als int32 0x0012D687, verteilt auf 0x0012 und 0xD687. Bei einem Float verrät sich eine falsche Reihenfolge sofort. Bei einem int32 nicht: dort bekommen Sie eine Zahl, die aussieht wie ein Zählerstand.
Die vier Varianten und ihre Namen
Die vier Bytes heißen der Reihe nach A, B, C und D: A ist 0x43, B ist 0x66, C ist 0x80, D ist 0x00. Daraus entstehen die vier Kürzel. Dieselben vier Bytes, vier Reihenfolgen, vier völlig verschiedene Zahlen:
| Reihenfolge | Register n | Register n+1 | Als Float32 gelesen |
|---|---|---|---|
| ABCD | 0x4366 | 0x8000 | 230,5 |
| BADC | 0x6643 | 0x0080 | 2,3 x 10^23 |
| CDAB | 0x8000 | 0x4366 | -2,4 x 10^-41 |
| DCBA | 0x0080 | 0x6643 | 1,2 x 10^-38 |
ABCD heißt Big-Endian, CDAB heißt Word-Swap (niedriges Wort zuerst), BADC heißt Byte-Swap (Bytes innerhalb jedes Wortes getauscht), DCBA heißt Little-Endian. In der Home-Assistant-Integration erreichen Sie dieselben vier über kein swap, swap: byte, swap: word und swap: word_byte. Andere Werkzeuge benennen dieselbe Vertauschung anders, deshalb ist der Name ein schlechter Anker.
Dass es sich um eine Einstellung handelt und nicht um Theorie, zeigen die Geräte selbst. Eastron dreht die Registerreihenfolge um, sobald Sie den bekannten Wert 2141,0 in das Parameterregister schreiben, und leitet daraus ab, wie Ihr Client rechnet. NIBE liefert das Register 48852 "Modbus40 Word Swap" mit, das ab Werk auf 1 steht, also auf vertauscht.
Der Plausibilitätstest statt Fachjargon
Sie müssen keine der vier Abkürzungen auswendig können. Wählen Sie eine Größe, deren Ergebnis Sie ungefähr kennen, lesen Sie sie in allen Varianten und behalten Sie die eine, die eine sinnvolle Zahl liefert.
Netzspannung und Netzfrequenz sind die besten Kandidaten dafür, rund 230 V und rund 50 Hz, denn beide stehen zusätzlich auf dem Display des Geräts. Ein Zählerstand ist der schlechteste Kandidat, denn dieselben 1.234.567 Wh aus dem vorigen Abschnitt sehen in allen vier Varianten aus wie ein echter Zählerstand:
| Reihenfolge | Register n | Register n+1 | Als int32 gelesen |
|---|---|---|---|
| ABCD | 0x0012 | 0xD687 | 1.234.567 |
| BADC | 0x1200 | 0x87D6 | 302.024.662 |
| CDAB | 0xD687 | 0x0012 | -695.795.694 |
| DCBA | 0x87D6 | 0x1200 | -2.016.013.824 |
Prüfen Sie also zuerst an einer Messung, die Sie physikalisch kennen, und übernehmen Sie das Ergebnis danach für die Zähler desselben Geräts.
Manche Werkzeuge nehmen Ihnen den Vergleich ab: ModbusCloud Diagnostics ermittelt im Register Explorer automatisch die Byte Order mit dem plausibelsten Wert. Bei einem Zählerstand bleibt das Urteil bei Ihnen, denn dort wirken alle vier Varianten glaubwürdig.
Skalierungsfaktoren im eigenen Register
Manche Hersteller lösen das Kommaproblem ohne Float: der Messwert bleibt eine ganze Zahl, und daneben steht ein zweites Register mit der Zehnerpotenz. SunSpec nennt diesen Typ sunssf, ein vorzeichenbehaftetes 16-Bit-Register mit dem Bereich -10 bis 10. Der echte Wert ist der Rohwert mal 10 hoch sunssf.
Bei einem SMA-Wechselrichter steht unter der Datenblattnummer 40200 die Wirkleistung und unter 40201 ihr Skalierungsfaktor, fest auf 1: Rohwert 550 sind also 5.500 W. Zwei Fallen aus derselben Tabelle. Das DC-Leistungsregister mit der Datenblattnummer 40217 hat seinen Skalierungsfaktor 2 im Register 40218: Rohwert 57 bedeutet also 5.700 W, und wer den Faktor überspringt, meldet 57 W für einen String, der 5,7 kW liefert. Register 40219, die Innentemperatur, hat dagegen überhaupt keinen Skalierungsfaktor. Die Regel "jeder Wert hat einen SF" gilt also nicht, das steht so in der Erklärung der Modbus-Register.
Wenn eine Zahl keine Messung ist
Ein Register, das der Hersteller nicht befüllt, ist nicht leer, sondern trägt einen festen Sentinel-Wert.
| Typ | Sentinel | Quelle |
|---|---|---|
| int16, int32, sunssf | 0x8000, als 32 Bit 0x80000000 | SunSpec |
| uint16 | 0xFFFF | SunSpec |
| float32 | 0x7FC00000 | Fronius |
| Daikin, alle Typen | 32767, 32766, 32765 | Daikin |
Die drei Daikin-Werte heißen der Reihe nach: Register nicht unterstützt, Register nicht verfügbar, Wert noch nicht geladen. Ein Temperaturregister mit 32767 meldet also keine 327,67 Grad.
Warum ein Energiezähler nicht in einen Float gehört
Ein Float32 hat 24 Bit effektive Genauigkeit. Oberhalb von 2^24, also 16.777.216, kann er nicht mehr jede ganze Zahl darstellen: 16.777.216 und 16.777.217 sind derselbe Wert. Ein Zähler in Wh wird damit ab rund 16,78 MWh ungenau.
In kWh sieht es besser aus. Bei 1.000.000 kWh beträgt die kleinste Stufe noch 0,0625 kWh, und das genügt für eine Verbrauchsauswertung. Genau deshalb geben Energiezähler ihre Arbeit in kWh aus und nicht in Wh. Für einen Zähler, der nur steigt, bleibt uint32 oder uint64 mit einem festen Skalierungsfaktor trotzdem die sauberere Wahl, denn dort ist jede Stufe gleich groß, egal wie hoch der Stand ist. Lesen Sie einen solchen Zähler dann aber auch unsigned: ein uint32-Zähler in Wh überschreitet bei 2.147.483.648 Wh, also rund 2,15 GWh, die Grenze des int32 und kippt vorzeichenbehaftet gelesen ins Negative.
Häufige Fehler
- Byte-Reihenfolge und Word Order verwechseln. Innerhalb eines Registers liegt die Reihenfolge fest, zwischen zwei Registern nicht. Wer im Client an "byte swap" dreht, obwohl "word swap" nötig wäre, probiert BADC statt CDAB und kommt nie an. Ändern Sie immer nur einen Schalter und notieren Sie das Ergebnis.
- Sich auf den Jargon verlassen statt auf die Messung. Dieselbe Vertauschung heißt in jedem Werkzeug anders. Der Plausibilitätstest funktioniert immer, die Bezeichnung nicht.
- Einen Sentinel in die Kurve schreiben.
0x7FC00000bei Fronius und0x80000000bei SMA bedeuten "kein Messwert". Ungefiltert steht nachts eine Spitze von gut zwei Milliarden Watt im Diagramm, und der Alarm darauf ist wertlos. - Einen kWh-Zähler als Float32 führen. Ab 16.777.216 verlieren Sie Auflösung, und bei einer Million kWh ist die kleinste Stufe 0,0625 kWh. Verbrauchsdifferenzen unterhalb dieser Stufe verschwinden dann still.
Selbst ausprobieren
Sie lesen dieselben beiden Register dreimal und entscheiden selbst, welches Ergebnis stimmen kann. mbpoll und pymodbus sind kostenlos nutzbar, auch gewerblich.
- 1
Die Rohwerte lesen
Lesen Sie die beiden Register, die laut Datenblatt zusammen einen Float bilden, zuerst als reine Hexwerte. Das ist der erste Befehl unten, mit
-t 4:hex. Das-r 100zählt bei mbpoll ab 1; nennt Ihr Datenblatt PDU-Adressen, ergänzen Sie-0. - 2
Dieselben Register als Float lesen
Nur der Typ hinter dem Doppelpunkt ändert sich, von
hexauffloat. Auf der Leitung passiert dabei nichts anderes. - 3
Die Wortreihenfolge umdrehen
Der dritte Befehl ist der zweite plus
-B. Gleiche Bytes, andere Interpretation im Client. - 4
Beide Ergebnisse bewerten
Schreiben Sie beide Zahlen nebeneinander und entscheiden Sie, welche für die gemessene Größe plausibel ist. Bei einer Netzspannung ist das die Zahl in der Nähe von 230.
- 5
Dasselbe in Python gegenprüfen
Mit pymodbus wechseln Sie die Reihenfolge über einen Parameter statt über einen Schalter.
- 6
Das Ergebnis dokumentieren
Notieren Sie die gefundene Kombination aus Marke, Modell und Wortreihenfolge in Ihrer Anlagendokumentation. Für dieses Gerät suchen Sie danach nie wieder.
mbpoll -m rtu -a 1 -b 9600 -P none -t 4:hex -r 100 -c 2 -1 /dev/ttyUSB0
mbpoll -m rtu -a 1 -b 9600 -P none -t 4:float -r 100 -c 2 -1 /dev/ttyUSB0
mbpoll -m rtu -a 1 -b 9600 -P none -t 4:float -B -r 100 -c 2 -1 /dev/ttyUSB0
Und in Python, Schritt 5:
value = client.convert_from_registers(rr.registers, data_type=client.DATATYPE.FLOAT32, word_order="big")
Danach dieselbe Zeile mit word_order="little".
Ohne Hardware. Starten Sie den pymodbus-Simulator, wie in mit dem Simulator üben beschrieben, und ersetzen Sie die seriellen Argumente durch -m tcp -p 5020 und -0 127.0.0.1, mit -r 6. Auf PDU-Adresse 6 liegt über zwei Register ein Float32 rund um 404, der bei jeder Lesung ansteigt. Probieren Sie beide Wortreihenfolgen und behalten Sie die, die eine ansteigende, plausible Reihe ergibt.
Erwartetes Ergebnis: zwei Interpretationen derselben Bytes, davon eine plausibel, und ein Eintrag in Ihrer Dokumentation.
Zusammenfassung
- Modbus legt die Byte-Reihenfolge innerhalb eines Registers fest, die Reihenfolge zweier Register bei einem 32-Bit-Wert dagegen nicht.
- Die vier Bytes
43 66 80 00ergeben als Float32 in der Reihenfolge ABCD den Wert 230,5, in den drei anderen Reihenfolgen Zahlen zwischen 10 hoch minus 41 und 10 hoch 23. - Der Plausibilitätstest an einer bekannten Größe wie 230 V oder 50 Hz findet die richtige Reihenfolge schneller als jede Jargontabelle.
- Ein Sentinel wie
0x8000,0xFFFF,0x7FC00000oder 32767 ist keine Messung und gehört herausgefiltert, bevor Sie skalieren. - Ein Float32 verliert oberhalb von 16.777.216 die Auflösung für ganze Zahlen, deshalb gehört ein großer Zähler in ein uint32 oder uint64 mit Skalierungsfaktor.
Überprüfen Sie sich selbst
Vier Fragen zu dieser Lektion. Zu jeder Antwort gibt es eine Erläuterung.
Frage 1 von 4
Selbst sehen, wie es funktioniert?
Das ModbusCloud Gateway liest die Geräte aus diesem Kurs aus, ohne dass Sie ein einziges Register programmieren.