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.
Exception-Codes lesen und den Funktionscode wählen
Ein Modbus Exception Code sagt Ihnen genau, wo der Fehler sitzt. Sie lernen, welchen Funktionscode Sie senden und was 0x83 mit Exception 02 wirklich bedeutet.
Was diese Lektion behandelt
- Welcher Funktionscode zu welchem Datenblock und welcher Bitbreite gehört
- 0x83 mit Exception 02 lesen, und wo Sie danach suchen
- Warum ein CRC-Fehler Stille erzeugt und keine Exception
Vorher lesen: Modbus Adressierung: von 40001 zur Adresse
Ein Exception-Code ist die höfliche Absage eines Modbus-Servers: Das Gerät hat Ihre Anfrage fehlerfrei empfangen, verstanden und sagt Ihnen in einem einzigen Byte, welche Ihrer Annahmen falsch war. Der Funktionscode davor ist die Frage, die Sie gestellt haben. Nach dieser Lektion lesen Sie ein Antwortframe im Hex-Dump und wissen sofort, ob Sie im Datenblatt, im Gerät oder im Gateway weitersuchen.
Welche Frage stellt welcher Code?
Der Funktionscode ist das zweite Byte im Frame und sagt dem Server zwei Dinge gleichzeitig: aus welchem der vier Datenblöcke Sie etwas wollen, und ob Sie lesen oder schreiben. Ein echtes Beispiel, drei Holding-Register ab PDU-Adresse 107:
01 03 00 6B 00 03 74 17
| Byte | Wert | Feld | Bedeutung |
|---|---|---|---|
| 1 | 01 | Adresse | Serveradresse 1 |
| 2 | 03 | Funktionscode | Read Holding Registers |
| 3-4 | 00 6B | Daten | Startadresse, PDU-Adresse 107 |
| 5-6 | 00 03 | Daten | Anzahl: 3 Register |
| 7-8 | 74 17 | CRC-16 | Prüfsumme, Low Byte zuerst |
Die Antwort desselben Geräts darauf:
01 03 06 02 2B 00 00 00 64 05 7A
| Byte | Wert | Feld | Bedeutung |
|---|---|---|---|
| 1 | 01 | Adresse | dasselbe Gerät |
| 2 | 03 | Funktionscode | unverändert, also eine normale Antwort |
| 3 | 06 | Daten | Byte Count: 3 Register mal 2 Byte |
| 4-9 | 02 2B 00 00 00 64 | Daten | die Werte 555, 0 und 100 |
| 10-11 | 05 7A | CRC-16 | Prüfsumme |
Daraus folgt die Regel: Bei einer normalen Antwort spiegelt der Server Ihren Funktionscode unverändert zurück. Datenblock und Operation zusammen legen fest, welcher Code der richtige ist.
Acht Codes decken die tägliche Arbeit ab: FC01 und FC02 lesen Bits, FC03 und FC04 lesen Register, FC05 und FC06 schreiben ein einzelnes Objekt, FC15 und FC16 einen ganzen Block. Die vollständige Liste aller öffentlichen Codes samt ihrer Grenzen steht in der Referenz der Modbus Funktionscodes. FC05, FC06 und FC16 schreiben und können deshalb etwas kaputt machen; die feste Routine dafür steht in der Lektion über sicheres Schreiben.
Warum zwei Codes fast dasselbe lesen
FC03 liest Holding-Register, FC04 liest Input-Register. Beide liefern 16-Bit-Werte, aber sie greifen auf zwei getrennte Datenblöcke zu, und jeder Block hat seine eigene Zählung ab 0. Holding-Register sind les- und schreibbar, Input-Register nur lesbar.
Auf der Leitung haben beide Anfragen dieselbe Form und unterscheiden sich in einem Feld, dem Funktionscode. Hier das FC04-Beispiel aus der Norm:
01 04 00 08 00 01 B0 08
Byte 2 trägt hier 04 statt 03, die übrigen Felder haben dieselbe Bedeutung. Sie lesen ein einzelnes Input-Register auf PDU-Adresse 8. Setzen Sie in der FC03-Anfrage weiter oben nur Byte 2 auf 04, dann lesen Sie dieselben Adressen im anderen Block, mit neu gerechneter Prüfsumme. Das Ergebnis ist trotzdem meist ein anderes als bei FC03, denn viele Geräte führen nur einen der beiden Blöcke. Dann kommt statt eines Messwerts eine Exception zurück.
In der Gebäudeautomation sehen Sie beide Varianten nebeneinander. Ein Zähler legt seine Momentanwerte oft in Input-Registern ab, die Sollwerte einer Regelung stehen dagegen fast immer in Holding-Registern. Welcher Block gilt, steht im Datenblatt und sonst nirgendwo: Das Protokoll kennt die Bedeutung eines Registers nicht. Wie die beiden Zählweisen zusammenhängen, zeigt die Lektion zur Modbus Adressierung und die Erklärung der Modbus Register.
Wie Sie eine Exception sofort erkennen
Sie schauen auf das zweite Byte. Ist es 0x80 oder größer, ist es eine Exception. Der Server behält Ihren Funktionscode und setzt dessen höchstes Bit, aus 0x03 wird also 0x83.
Damit liegt auch die Länge fest: Eine Exception-Antwort besteht immer aus genau zwei PDU-Bytes, dem gespiegelten Funktionscode und dem Exception-Code. Auf RS485 kommen Serveradresse und CRC dazu, macht fünf Byte:
01 83 02 C0 F1
| Byte | Wert | Feld | Bedeutung |
|---|---|---|---|
| 1 | 01 | Adresse | Serveradresse 1 |
| 2 | 83 | Funktionscode | 0x03 plus 0x80, also Exception auf ein FC03 |
| 3 | 02 | Daten | Exception-Code 02, Illegal Data Address |
| 4-5 | C0 F1 | CRC-16 | Prüfsumme über dieses Frame |
Ein auffällig kurzes Frame direkt nach Ihrer Anfrage ist deshalb schon ohne Rechnen verdächtig: fünf Byte statt der elf aus dem Beispiel oben.
Die neun Exception-Codes nach Ursache
Der Code sagt Ihnen, wo Sie suchen sollen. Die aktuelle Norm V1.1b3 kennt neun Exception-Codes: 01 bis 06, 08, 0A und 0B. Eine 07 und eine 09 gibt es dort nicht.
Eine Exception 07 begegnet Ihnen nur noch in alter Modicon-Dokumentation. Die heutige Norm kennt sie nicht.
Was Exception 02 wirklich sagt
Exception 02 heißt nicht "diese Adresse gibt es nicht", sondern "diese Adresse zusammen mit dieser Anzahl gibt es nicht". Die Spezifikation macht das an einem Regler mit 100 Registern deutlich: Auf der Leitung heißt das erste Register 0 und das letzte 99. Eine Anfrage ab Startadresse 96 über 4 Register trifft 96, 97, 98 und 99 und wird beantwortet. Dieselbe Startadresse über 5 Register greift zusätzlich auf ein Register 100 zu, das es nicht gibt, und liefert Exception 02.
Rechnen Sie bei Exception 02 also immer beide Enden nach, die Startadresse und die Startadresse plus Anzahl minus 1. Die zweite große Ursache ist der Zählversatz zwischen Datenblatt und Leitung: Datenblattnummer 40108 ist auf der Leitung PDU-Adresse 107, nicht 108 und schon gar nicht 40108.
Warum Stille etwas anderes bedeutet
Eine Anfrage hat vier mögliche Ausgänge, und nur einer davon ist eine Exception.
- Der Server empfängt die Anfrage fehlerfrei und kann sie ausführen: normale Antwort.
- Der Server empfängt die Anfrage gar nicht: keine Antwort, Sie laufen in einen Timeout.
- Der Server empfängt die Anfrage, erkennt aber einen Paritäts- oder CRC-Fehler: keine Antwort, wieder ein Timeout.
- Der Server empfängt die Anfrage fehlerfrei, kann sie aber nicht ausführen: Exception.
Fall 3 ist die wichtigste Praxisregel dieser Lektion. Bei einem CRC-Fehler verwirft der Server das Telegramm stillschweigend, genau wie bei einer Anfrage an eine leere Serveradresse. Ein Timeout lässt Kabel, Baudrate, Parität und Adresse also alle offen.
Wie Sie einen kompletten Bus nach einem Timeout systematisch abklopfen, zeigt die Anleitung zum Modbus Netzwerk scannen.
Was FC43 über ein unbekanntes Gerät verrät
FC43 mit MEI-Typ 14, Read Device Identification, fragt das Gerät nach sich selbst. Drei Objekte sind dabei verpflichtend: VendorName, ProductCode und MajorMinorRevision. Die Anfrage-PDU ist vier Byte lang, 2B 0E 01 00: Funktionscode, MEI-Typ, Read Device ID Code 01 für die Basisidentifikation und Objekt-Id 0x00. Damit haben Sie Hersteller, Typnummer und Revision, ohne ein einziges Datenblatt aufzuschlagen.
In einer Bestandsanlage, in der niemand mehr weiß, was im Schaltschrank hängt, ist das viel wert. Nicht jedes Gerät unterstützt den Code. Kennt es ihn nicht, antwortet es mit 0xAB und Exception 01, und auch das ist eine brauchbare Information: Das Gerät lebt und hört auf diese Serveradresse.
Eine vollständige Identifikation passt nicht immer in eine PDU von 253 Byte. Deshalb trägt die Antwort die Felder More Follows und Next Object Id, mit denen Sie den Rest in einer zweiten Anfrage abholen.
Häufige Fehler
- FC03 und FC04 verwechseln. Sie lesen mit
FC03, weil Sie es immer so machen, und bekommen Exception 01, wenn das Gerät den Code gar nicht kennt, oder Exception 02, wenn der Block kleiner ist als gedacht. Schauen Sie im Datenblatt nach, welchen Block das Gerät führt, statt zu raten. - Eine Exception für ein Verkabelungsproblem halten. Dieser Fehler kostet die meiste Zeit, denn Sie suchen an der einzigen Stelle, die nachweislich in Ordnung ist. Eine Exception belegt, dass Ihr Frame fehlerfrei angekommen ist. Physikalische Ebene, Busparameter und Serveradresse sind dann bereits in Ordnung.
- Exception 03 auf den Registerinhalt beziehen. Die Spezifikation sagt ausdrücklich, dass es dabei um die Struktur Ihrer Anfrage geht, etwa um eine Anzahl außerhalb des erlaubten Bereichs. Ein Sollwert, der für die Anlage zu hoch ist, erzeugt keine Exception 03.
- Auf eine Exception 07 oder 09 warten. V1.1b3 kennt neun Codes: 01 bis 06, 08, 0A und 0B. Wer eine 07 sucht, sucht etwas, das die heutige Norm nicht mehr enthält.
Selbst ausprobieren
Ziel: Sie lösen absichtlich eine echte Exception aus und sehen das Frame. Das ist der Unterschied zwischen "Exceptions gibt es" und "die erkenne ich".
- 1
Simulator starten
Der Simulator von pymodbus ist kostenlos nutzbar, auch geschäftlich. Starten Sie ihn mit
pymodbus.simulator --modbus_server server --modbus_device device. Der Server hört auf Port 5020, die Weboberfläche liegt aufhttp://127.0.0.1:8081/. - 2
Ein gültiges Register lesen
Lesen Sie ein Register ab PDU-Adresse 3. Sie bekommen den Wert 17001 zurück. Damit steht fest, dass Ihre Verbindung funktioniert.
- 3
Eine Exception auslösen
Lesen Sie jetzt PDU-Adresse 1. Der Simulator antwortet mit einer echten Exception:
function_code=131undexception_code=2. - 4
Selbst nachrechnen
Rechnen Sie nach, warum 131 dasselbe ist wie
0x83, und begründen Sie daraus, welchen Funktionscode Ihre Anfrage getragen hat. - 5
Die Grenze überschreiten
Fragen Sie 130 Register mit
FC03ab. Erlaubt sind 125, also erwarten Sie Exception 03. Notieren Sie, was Ihr Gerät oder der Simulator tatsächlich zurückschickt.
Ein Beispielaufruf für Schritt 2 und 3:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1", port=5020)
client.connect()
print(client.read_holding_registers(address=3, count=1, device_id=1).registers)
print(client.read_holding_registers(address=1, count=1, device_id=1))
Mit eigener Hardware. Machen Sie dasselbe an Ihrem Gerät: Fragen Sie ein Register ab, das es laut Datenblatt nicht gibt. Fast jedes Gerät antwortet mit 0x83 und Exception 02.
Erwartetes Ergebnis: eine Exception-Antwort auf dem Schirm, und die Erkenntnis, dass die Kommunikation in diesem Moment nachweislich in Ordnung ist.
Zusammenfassung
- Der Funktionscode legt Datenblock und Operation zugleich fest, und eine normale Antwort trägt genau denselben Code wie die Anfrage.
- Eine Exception-Antwort trägt den Funktionscode plus
0x80und danach genau ein Byte mit dem Exception-Code, also01 83 02plus CRC auf einFC03. - Die Norm V1.1b3 kennt neun Exception-Codes, die sich in drei Bereiche sortieren lassen: Ihre Anfrage (01, 02, 03), das Gerät (04, 05, 06, 08) und das Gateway (0A, 0B).
- Exception 02 bewertet Startadresse und Anzahl gemeinsam, deshalb prüfen Sie immer beide Enden Ihres Lesebereichs.
- Ein CRC-Fehler erzeugt keine Exception, sondern Stille: Eine Exception beweist, dass Verkabelung, Busparameter und Serveradresse bereits stimmen.
Ü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.