In dieser Lektion

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.

Ein FLOAT32: 230,5 V0x42C80x0000Hohes WortNiedriges WortHohes Wort zuerst (Big-Endian)0x42C80x0000Register nRegister n+1✓ liest 230,5Niedriges Wort zuerst (Little-Endian)0x00000x42C8✗ liest Unsinn
Innerhalb eines Registers legt der Standard die Byte-Reihenfolge fest, zwischen zwei Registern nicht.

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.

RegisterRohwertBytes
Register n0x436643 66
Register n+10x800080 00

Aneinandergehängt sind das die vier Bytes 43 66 80 00, also 0x43668000. Aufgeschlüsselt:

FeldBitsWert
Vorzeichen10, also positiv
Exponent80x86 ist 134, minus Bias 127 ergibt 7
Mantisse236.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:

ReihenfolgeRegister nRegister n+1Als Float32 gelesen
ABCD0x43660x8000230,5
BADC0x66430x00802,3 x 10^23
CDAB0x80000x4366-2,4 x 10^-41
DCBA0x00800x66431,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.

Vier Bytes aus zwei Holding-Registern43A66B80C00DWas Sie erwarteneine Netzspannung, also rund230 VABCD, Big-Endian230,5BADC, Byte-Swap2,3 x 10^23CDAB, Word-Swap-2,4 x 10^-41DCBA, Little-Endian1,2 x 10^-38Nur ABCD liefert eine Spannung, die ein Zähler je misst. Stellen Sieden Client auf Big-Endian.
Vier Interpretationen, ein plausibles Ergebnis. So finden Sie die Reihenfolge ohne Fachjargon.

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:

ReihenfolgeRegister nRegister n+1Als int32 gelesen
ABCD0x00120xD6871.234.567
BADC0x12000x87D6302.024.662
CDAB0xD6870x0012-695.795.694
DCBA0x87D60x1200-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.

40200550×10^402011=5500 W
40200
Rohwert, Wirkleistung (int16)
40201
Skalierungsfaktor W_SF (sunssf)
5500 W
echter Wert
SunSpec legt die Skalierung in ein eigenes Register neben den Messwert. Lesen Sie nur 40200, fehlt Ihnen der Faktor 10.

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.

TypSentinelQuelle
int16, int32, sunssf0x8000, als 32 Bit 0x80000000SunSpec
uint160xFFFFSunSpec
float320x7FC00000Fronius
Daikin, alle Typen32767, 32766, 32765Daikin

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

  1. 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.
  2. 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.
  3. Einen Sentinel in die Kurve schreiben. 0x7FC00000 bei Fronius und 0x80000000 bei SMA bedeuten "kein Messwert". Ungefiltert steht nachts eine Spitze von gut zwei Milliarden Watt im Diagramm, und der Alarm darauf ist wertlos.
  4. 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. 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 100 zählt bei mbpoll ab 1; nennt Ihr Datenblatt PDU-Adressen, ergänzen Sie -0.

  2. 2

    Dieselben Register als Float lesen

    Nur der Typ hinter dem Doppelpunkt ändert sich, von hex auf float. Auf der Leitung passiert dabei nichts anderes.

  3. 3

    Die Wortreihenfolge umdrehen

    Der dritte Befehl ist der zweite plus -B. Gleiche Bytes, andere Interpretation im Client.

  4. 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. 5

    Dasselbe in Python gegenprüfen

    Mit pymodbus wechseln Sie die Reihenfolge über einen Parameter statt über einen Schalter.

  6. 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 00 ergeben 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, 0x7FC00000 oder 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
Zwei Register enthalten 0x4366 und 0x8000. Welchen Wert ergibt das als Float32, wenn das hohe Wort zuerst steht?
Sie lesen eine Netzspannung aus und bekommen wechselnde Werte in der Größenordnung von 10 hoch minus 41. Was probieren Sie zuerst?
Sie lesen einen Zählerstand von rund 1.000.000 kWh als Float32 aus. Was ist die Folge?
Warum legt der Modbus-Standard die Wortreihenfolge zwischen zwei Registern nicht fest?

Kommen Sie bei einem Projekt nicht weiter?

Beschreiben Sie, was Sie sehen und wo es hakt. Wir schauen es uns an und sagen Ihnen, was wir tun würden.

Weiterlesen in der Wissensdatenbank