Modbus Register-Adressierung: 40001, 0-basiert und Off-by-one-Fehler
· Von Vladimir Chemeris, Entwickler von Modbus TCP FieldKit
Kurzantwort: 40001 bedeutet das erste Holding-Register, und ein Modbus-Frame überträgt es als Adresse 0. Die 4 wählt den Bereich, die übrigen Ziffern zählen ab 1. Ziehen Sie eins ab und lassen Sie das Präfix weg: Aus 40108 wird die Adresse 107.
Drei Zahlen für ein Register
Die Modbus-Spezifikation definiert zwei Nummerierungsschemata. Abschnitt 4.4 der Application Protocol Specification V1.1b3 sagt es klar: „In a MODBUS PDU each data is addressed from 0 to 65535“, während „in the MODBUS data Model each element within a data block is numbered from 1 to n“. Sinngemäß: Die PDU adressiert von 0 bis 65535, das Datenmodell nummeriert jedes Element eines Datenblocks von 1 bis n. Die PDU überträgt ein Element mit der Nummer X als X-1.
Hersteller fügen dann eine dritte Gewohnheit hinzu: das Bereichspräfix. So entstehen diese Namen für dasselbe Register:
| Geschrieben als | Stil | Bedeutung |
|---|---|---|
0 oder 0x0000 |
Protokolladresse | Was der Frame überträgt |
1 |
1-basierte Registernummer | Das erste Element im Block |
40001 |
5-stellige Referenz | Erstes Holding-Register |
400001 |
6-stellige Referenz | Erstes Holding-Register, erweiterter Bereich |
Das Präfix gehört nicht zum Frame-Format der Spezifikation. Es stammt aus alter Modicon-Dokumentation und hat sich gehalten, weil es zugleich den Bereich benennt.
| Präfix | Bereich | Lesen mit | Schreiben mit |
|---|---|---|---|
0xxxx |
Coils | 01 |
05, 15 |
1xxxx |
Diskrete Eingänge | 02 |
keine |
3xxxx |
Eingangsregister | 04 |
keine |
4xxxx |
Holding-Register | 03 |
06, 16 |
Der Adresskonverter übernimmt diese Rechnung für die Zahl, die Sie einfügen.
Wie die falsche Nummer auf der Leitung aussieht
Wir haben einen Server mit pymodbus 3.16.1 betrieben, mit drei Holding-Registern an Adresse 0: 100, 250 und 1024. Ein Raw-Read von Adresse 0 mit Anzahl 3 lieferte alle drei:
TX 00 01 00 00 00 06 01 03 00 00 00 03
RX 00 01 00 00 00 09 01 03 06 00 64 00 FA 04 00
Dann haben wir den klassischen Fehler gemacht und 40000 als Adresse gesendet, als gehörte das Präfix in den Frame. 0x9C40 ist 40000:
TX 00 02 00 00 00 06 01 03 9C 40 00 01
RX 00 02 00 00 00 03 01 83 02
83 02 ist Exception 02, Illegal Data Address. Hier hatten Sie Glück. Hat das Gerät dort oben Register, lesen Sie die falschen Daten und erhalten keinen Fehler.
Ein Off-by-one-Fehler liefert keine Fehlermeldung
Ein Off-by-one-Fehler ist schlimmer, weil das Gerät antwortet. Fragen Sie Adresse 1 ab, obwohl Sie Adresse 0 wollten, erhalten Sie 250 statt 100. Nichts auf dem Bildschirm weist darauf hin. Ein 32-Bit-Wert ist der übelste Fall: Beginnen Sie ein Register zu spät, kombiniert die App die untere Hälfte eines Werts mit der oberen Hälfte des nächsten, was oft wie eine plausible Zahl aussieht.
Ein Test, der es klärt
- Wählen Sie ein Register mit einem Wert, den Sie überprüfen können: eine Firmware-Version, eine Seriennummer oder einen Sollwert, den Sie am Display des Geräts ändern können.
- Lesen Sie ein kleines Fenster um die dokumentierte Nummer, zum Beispiel 5 Register ab zwei unterhalb davon.
- Suchen Sie den bekannten Wert in der Antwort. Seine Position verrät den Offset.
- Notieren Sie den Offset für diese Gerätefamilie und halten Sie ihn in Ihren Notizen oder in einem gespeicherten Profil fest.
Tools haben unterschiedliche Voreinstellungen, prüfen Sie also Ihres. mbpoll beginnt bei Referenz 1, sofern Sie nicht -0 für die PDU-Adressierung übergeben. In FieldKit wählen Sie neben der Verbindung 0-based, 1-based oder PLC 4xxxx und können umschalten, ohne die Verbindung zu trennen.
Die 5-stellige Grenze
Fünf Stellen ergeben 9999 Register pro Bereich, das Protokoll erlaubt aber 65536. Deshalb verwenden Handbücher größerer Geräte sechs Stellen: 400001 bis 465536. Steht in einem Handbuch 412345, lesen Sie es als Holding-Register 12345, also Protokolladresse 12344.
Quellen
- Modbus Application Protocol Specification V1.1b3, Abschnitt 4.4 (Adressierungsmodell)
- Frames aufgezeichnet am 30. Oktober 2026 von pymodbus 3.16.1 unter Linux, über einen rohen TCP-Socket
FAQ
Ist Modbus 0-basiert oder 1-basiert?
Beides, auf unterschiedlichen Ebenen. Der Protokoll-Frame verwendet Adressen von 0 bis 65535. Das Datenmodell nummeriert Elemente ab 1. Nach der Spezifikation überträgt die PDU ein Element mit der Nummer X als X-1.
Welche Adresse sende ich für das Holding-Register 40001?
Adresse 0 mit Function Code 03. Die führende 4 wählt den Bereich der Holding-Register aus und gehört nicht zur Adresse auf der Leitung.
Wie finde ich heraus, welche Nummerierung ein Handbuch verwendet?
Lesen Sie ein Register mit bekanntem Wert, etwa eine Seriennummer oder einen Sollwert, den Sie am Gerät ändern können. Probieren Sie die dokumentierte Nummer und dann die um eins niedrigere. Diejenige, die den bekannten Wert liefert, verrät Ihnen die Nummerierung.