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.
Sicher auf ein Modbus Gerät schreiben
Ein Modbus Register schreiben kann eine Anlage stoppen. Lernen Sie den Unterschied zwischen FC05, FC06 und FC16 und eine feste Routine für sicheres Schreiben.
Was diese Lektion behandelt
- FC05, FC06, FC15 und FC16, mit der Grenze von 1968 Coils und 123 Registern
- Warum FC05 nur die Werte 0xFF00 und 0x0000 akzeptiert
- Die Routine, die den alten Wert sichert, und was ein Echo nicht beweist
Vorher lesen: Exception-Codes lesen und den Funktionscode wählen, Eine Modbus Registertabelle richtig lesen
Ein Modbus Register schreiben dauert genauso lange wie ein Register lesen, nur kennt das Protokoll kein Rückgängig. Der Unterschied zwischen einem sicheren und einem teuren Schreibvorgang liegt nicht im Funktionscode, sondern in einer Routine, die Sie jedes Mal gleich durchlaufen. Nach dieser Lektion wählen Sie den passenden Funktionscode, lesen die Antwort richtig und erkennen die Fälle, in denen Sie besser nichts anfassen.
Was schiefgeht, wenn Sie einfach schreiben
Lesen verändert nichts, Schreiben verändert den Zustand des Geräts, und niemand fragt Sie vorher. Ein Beispiel aus der Gebäudeautomation: Eine Wärmepumpe regelt auf ein Sollwertregister, die Gebäudeleittechnik schreibt dort im Minutentakt ihren Wert hinein, und Sie schreiben zum Testen einmal 21,5 °C. Auf demselben Register gewinnt der letzte Client, und das ist selten der, der gerade misst.
Modbus hilft Ihnen dabei nicht. Das Protokoll kennt keine Sperre und keine Historie, und die Bedeutung Ihres Registers legt der Hersteller fest, nicht die Spezifikation. Das Gerät führt Ihren Schreibvorgang deshalb genauso brav aus, wenn dahinter ein Ventil sitzt statt einer Anzeige.
Welcher Funktionscode passt zu welchem Schreibvorgang?
Vier Funktionscodes decken den täglichen Schreibbetrieb ab, und die Wahl folgt dem Datenblock, nicht dem Geschmack. FC05 schreibt eine einzelne Coil, FC06 ein einzelnes Holding-Register, FC15 bis zu 1968 Coils am Stück und FC16 bis zu 123 Holding-Register am Stück. Input-Register und Discrete Inputs sind per Definition nicht schreibbar; ein Versuch endet mit Exception 01 oder 02. Die vollständige Übersicht steht in der Referenz der Modbus Funktionscodes, hier geht es um die Wahl im konkreten Fall.
Manchmal nimmt das Gerät Ihnen die Wahl ab. Der Eastron SDM630 legt Serveradresse und Baudrate als Float über je zwei Register ab und verlangt dafür FC16, obwohl es formal nur ein Parameter ist. Wie Sie das im Datenblatt erkennen, steht in der Lektion über das Lesen einer Registertabelle.
Warum FC05 nur zwei Werte akzeptiert
FC05 kennt genau zwei gültige Werte, und die 1 ist keiner davon. So sieht ein vollständiges RTU-Frame aus, das die Coil auf PDU-Adresse 172 einschaltet, im Datenblatt die 1-basierte Nummer 173:
01 05 00 AC FF 00 4C 1B
| Bytes | Feld | Bedeutung |
|---|---|---|
01 | Serveradresse | Gerät 1 auf dem Bus |
05 | Funktionscode | Write Single Coil |
00 AC | Output Address | PDU-Adresse 172, 0-basiert |
FF 00 | Output Value | AN |
4C 1B | CRC-16 | Low Byte zuerst |
Die Antwort darauf ist ein Echo, Byte für Byte dieselbe Folge 01 05 00 AC FF 00 4C 1B. Daraus die Regel, kompakt: 0xFF00 heißt an, 0x0000 heißt aus, und jeder andere Wert ist ungültig und lässt den Ausgang unverändert.
Jetzt dasselbe Beispiel mit genau einer Abweichung. Sie senden die PDU 05 00 AC 00 01, weil 1 doch an bedeutet. Zurück kommt eine Exception-Antwort von genau zwei Bytes:
85 03
0x05 plus 0x80 ergibt 0x85, und die 03 steht für ILLEGAL DATA VALUE. Die Coil hat sich nicht bewegt. Wohin welche Exception zeigt, steht in der Lektion über Funktionscodes und Exceptions.
Die Antwort auf einen Schreibvorgang lesen
FC05 und FC06 spiegeln Ihre Anfrage vollständig zurück, FC15 und FC16 bestätigen nur Startadresse und Anzahl. Ein FC06-Vorgang mit dem Wert 3 auf PDU-Adresse 1 sieht in beide Richtungen gleich aus:
01 06 00 01 00 03 98 0B
Was ein Echo nicht sagt: ob die Applikation im Gerät den Wert auch benutzt. Der SDM630 bestätigt eine neue Serveradresse sofort, aktiviert sie laut Datenblatt aber erst nach einem Neustart. Andere Geräte verlangen ein Freigaberegister oder eine bestimmte Betriebsart.
Einen Block schreiben ohne Zwischenzustände
Zusammenhängende Sollwerte gehören in eine Nachricht, sonst steht das Gerät zwischendurch halb alt und halb neu eingestellt da. Das Beispiel der Spezifikation schreibt zwei Register ab PDU-Adresse 1, Werte 10 und 258:
01 10 00 01 00 02 04 00 0A 01 02 92 30
| Bytes | Feld | Bedeutung |
|---|---|---|
01 | Serveradresse | Gerät 1 auf dem Bus |
10 | Funktionscode | FC16, Write Multiple Registers |
00 01 | Startadresse | PDU-Adresse 1, 0-basiert |
00 02 | Anzahl Register | 2 |
04 | Byte Count | 2 mal 2 Bytes |
00 0A 01 02 | Werte | 10 und 258 |
92 30 | CRC-16 | Low Byte zuerst |
Die Antwort trägt nur die PDU 10 00 01 00 02, also Funktionscode, Startadresse und Anzahl. Die geschriebenen Werte bekommen Sie nicht zurück, weshalb hier das Zurücklesen doppelt zählt.
Die Grenze von 123 Registern ist Rechenergebnis: 6 Bytes Overhead plus 123 mal 2 sind 252 Bytes und passen gerade in die PDU-Grenze von 253. Wer im selben Vorgang schreiben und lesen will, nimmt FC23, bis zu 121 Register schreiben und 125 lesen, wobei der Schreibteil zuerst ausgeführt wird.
Die Routine, die Sie jedes Mal befolgen
Vier Schritte, und nur der dritte trägt Risiko. Lesen Sie den alten Wert. Notieren Sie ihn mit Adresse, Zählweise und Zeitpunkt. Schreiben Sie den neuen Wert. Lesen Sie zurück und prüfen Sie, ob die Anlage sich verhält, wie Sie es erwarten.
Zwei Ergänzungen aus der Praxis. Ändern Sie pro Nachricht einen Parameter und pro Versuch eine Größe, sonst wissen Sie hinterher nicht, was gewirkt hat. Und schreiben Sie nie in einen laufenden Regelkreis, ohne den anderen Client stillzulegen: Solange die Gebäudeleittechnik ihren Wert nachschiebt, prüfen Sie nicht Ihr Register, sondern die Reaktionszeit der Konkurrenz. Für Home Assistant über Modbus einbinden gilt dasselbe.
Wann Sie besser nicht schreiben
In drei Fällen ist der richtige Schreibvorgang gar keiner. Der erste ist Broadcast. Auf der Serveradresse 0 führt jedes Gerät am Segment die Nachricht aus, und keines antwortet; gültige Einzeladressen sind 1 bis 247, die Adressen 248 bis 255 sind reserviert. Sie sparen ein paar Nachrichten und geben dafür jede Rückmeldung auf. Der SDM630 widerspricht sich im eigenen Handbuch sogar darüber, ob er Broadcast unterstützt.
Der zweite Fall sind Register, über die das Datenblatt schweigt: Ein Register, das antwortet, ist noch lange kein dokumentiertes Register. Der dritte Fall sind Parameter, die das Gerät dauerhaft in seinen Flash-Speicher legt. Wie viele Schreibzyklen dieser Speicher verträgt, steht im Datenblatt und nicht im Protokoll, und ein zyklisch nachgeschriebener Sollwert macht so ein Gerät auf Dauer unbrauchbar. Bei Ladestationen über Modbus überwachen ist genau das ein Dauerthema.
Häufige Fehler
Schreiben, ohne den alten Wert zu notieren. Ohne diese Notiz kommen Sie nicht zurück, und im Zweifel weiß auch der Betreiber nicht mehr, wie die Anlage eingestellt war. Was hilft: den Lesevorgang zur Pflicht vor jedem Schreibvorgang machen, mit schriftlicher Ablage.
0x0001 senden, um ein Relais einzuschalten. FC05 kennt nur 0xFF00 und 0x0000. Alles andere ist ungültig, ergibt Exception 03, und die Coil bleibt, wo sie war. Was hilft: 0xFF00 als Konstante behandeln, nicht als Zahl.
Ein Echo für eine Bestätigung halten. FC05 und FC06 spiegeln die Anfrage zurück, sobald der Wert geschrieben ist. Über die Applikation im Gerät sagt das nichts. Was hilft: zurücklesen und die Wirkung prüfen, notfalls nach einem Neustart.
Broadcast benutzen, um Zeit zu sparen. Auf Adresse 0 antwortet niemand. Sie wissen weder, ob die Nachricht angekommen ist, noch welches Gerät sie nicht ausgeführt hat. Was hilft: jedes Gerät einzeln adressieren und einzeln kontrollieren.
Selbst ausprobieren
Sie durchlaufen die Routine einmal vollständig und provozieren danach bewusst einen Fehler, damit Sie eine abgewiesene Schreibanfrage auch einmal gesehen haben.
- 1
Ein ungefährliches Register aussuchen
Ein Register, das laut Datenblatt beschreibbar ist und nichts steuert, das sich bewegt. Ein Anzeigesollwert oder ein Kommunikationsparameter ist gut, eine Ventilstellung nicht.
- 2
Den alten Wert lesen und aufschreiben
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 20 -c 1 -1 /dev/ttyUSB0. mbpoll steht unter GPLv3 und ist frei nutzbar, auch geschäftlich. Notieren Sie Adresse, Zählweise und Wert auf Papier. - 3
Den neuen Wert schreiben
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 20 /dev/ttyUSB0 1234. Der Wert am Ende der Zeile ist das, was geschrieben wird. - 4
Zurücklesen und kontrollieren
Derselbe Befehl wie in Schritt 2. Kontrolle: Es steht 1234 im Register. Prüfen Sie zusätzlich am Display oder an der Anlage, ob sich etwas verändert hat.
- 5
Den alten Wert zurückschreiben
Schritt 3 mit dem notierten Wert, danach Schritt 4 erneut. Erst jetzt ist der Versuch abgeschlossen.
- 6
Bewusst eine Exception auslösen
Senden Sie an eine Coil den Wert 0x0001 statt 0xFF00. Erwartung laut Spezifikation: Exception 03, und die Coil bleibt unverändert.
Ohne Hardware. Die Schritte 2 bis 5 laufen genauso gegen den pymodbus-Simulator, frei nutzbar unter der BSD-3-Lizenz, auch geschäftlich. Bauen Sie sich mit SimData und SimDevice einen Server mit einem beschreibbaren Register, wie in der Lektion über Modbus mit dem Simulator üben, und hängen Sie an mbpoll -m tcp -p 5020 127.0.0.1 statt der seriellen Argumente.
Erwartetes Ergebnis: ein geänderter und wieder zurückgesetzter Wert, dazu eine Exception, die Sie selbst provoziert haben.
Zusammenfassung
- Der Funktionscode folgt dem Datenblock: FC05 für eine Coil, FC06 für ein Register, FC15 für bis zu 1968 Coils und FC16 für bis zu 123 Register in einer Transaktion.
- FC05 akzeptiert ausschließlich 0xFF00 für an und 0x0000 für aus, jeder andere Wert ergibt Exception 03 und lässt den Ausgang unverändert.
- Ein Echo bestätigt, dass der Server den Wert übernommen hat, aber nicht, dass die Applikation im Gerät ihn benutzt.
- Die sichere Routine lautet immer gleich: alten Wert lesen, notieren, neuen Wert schreiben, zurücklesen und die Wirkung kontrollieren.
- Auf Serveradresse 0 antwortet kein Gerät, deshalb ist ein Broadcast-Schreibvorgang ein Vorgang ohne jede Rückmeldung.
Ü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.