In dieser Lektion

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
ByteWertFeldBedeutung
101AdresseServeradresse 1
203FunktionscodeRead Holding Registers
3-400 6BDatenStartadresse, PDU-Adresse 107
5-600 03DatenAnzahl: 3 Register
7-874 17CRC-16Prüfsumme, Low Byte zuerst

Die Antwort desselben Geräts darauf:

01 03 06 02 2B 00 00 00 64 05 7A
ByteWertFeldBedeutung
101Adressedasselbe Gerät
203Funktionscodeunverändert, also eine normale Antwort
306DatenByte Count: 3 Register mal 2 Byte
4-902 2B 00 00 00 64Datendie Werte 555, 0 und 100
10-1105 7ACRC-16Prü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.

LesenEinzeln schreibenMehrere schreibenCoils0x010x050x0FDiscrete Inputs0x02nicht schreibbarnicht schreibbarHolding-Register0x030x060x10Input-Register0x04nicht schreibbarnicht schreibbar
Datenblock und Operation bestimmen gemeinsam den Funktionscode.

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.

MSBLSBIhre Anfrage0x030bit 70bit 60bit 50bit 40bit 30bit 21bit 11bit 0Bit 7 gesetzt, also plus 0x80Exception-Antwort0x831bit 70bit 60bit 50bit 40bit 30bit 21bit 11bit 0
Eine Exception behält den Funktionscode und setzt das höchste Bit. Aus 0x03 wird 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
ByteWertFeldBedeutung
101AdresseServeradresse 1
283Funktionscode0x03 plus 0x80, also Exception auf ein FC03
302DatenException-Code 02, Illegal Data Address
4-5C0 F1CRC-16Prü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.

Exception-Codes und wo Sie suchenFehler in Ihrer AnfrageDas Gerät lebt und antwortet sauber. Korrigieren Sie Adresse,Funktionscode oder Anzahl.01Illegal function02Illegal data address03Illegal data valueProblem im GerätIhre Anfrage stimmt, aber das Gerät kann sie gerade nicht ausführen.Schauen Sie ins Gerät selbst.04Server device failure05Acknowledge06Server device busy08Memory parity errorProblem im GatewayDiese Antwort kommt vom Gateway, nicht vom Endgerät dahinter.0AGateway path unavailable0BGateway target device failed to respond
Eine Exception ist eine gute Nachricht: Das Gerät antwortet. Der Code sagt, ob der Fehler in Ihrer Anfrage, im Gerät oder im Gateway dazwischen steckt.

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.

  1. Der Server empfängt die Anfrage fehlerfrei und kann sie ausführen: normale Antwort.
  2. Der Server empfängt die Anfrage gar nicht: keine Antwort, Sie laufen in einen Timeout.
  3. Der Server empfängt die Anfrage, erkennt aber einen Paritäts- oder CRC-Fehler: keine Antwort, wieder ein Timeout.
  4. 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

  1. 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.
  2. 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.
  3. 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.
  4. 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. 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 auf http://127.0.0.1:8081/.

  2. 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. 3

    Eine Exception auslösen

    Lesen Sie jetzt PDU-Adresse 1. Der Simulator antwortet mit einer echten Exception: function_code=131 und exception_code=2.

  4. 4

    Selbst nachrechnen

    Rechnen Sie nach, warum 131 dasselbe ist wie 0x83, und begründen Sie daraus, welchen Funktionscode Ihre Anfrage getragen hat.

  5. 5

    Die Grenze überschreiten

    Fragen Sie 130 Register mit FC03 ab. 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 0x80 und danach genau ein Byte mit dem Exception-Code, also 01 83 02 plus CRC auf ein FC03.
  • 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
Sie senden eine Anfrage und bekommen 01 83 02 C0 F1 zurück. Was ist passiert?
Sie senden FC03 an ein Gerät, das laut Datenblatt nur Input-Register führt. Was kommt zurück?
Gerät 1 antwortet mit Exception 02, Gerät 2 am selben Bus läuft in einen Timeout. Was wissen Sie jetzt?
Wie viele Holding-Register dürfen Sie mit einer einzigen FC03-Anfrage lesen, und was passiert bei mehr?

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