Zwei Digitaleingänge, zwei Analogeingänge, vier Relaisausgänge · Prof. Dr.-Ing. Ralph Wystup M.Sc. — erstellt mit KI und Agent (Claude Code, Anthropic)
| Befehl | — |
| gesendet | — |
| zurück | — |
| gespiegelt | — |
| Antwort nach | — |
Der Eingang misst 0 bis 20 mA. Der Strom fließt über einen Bürdewiderstand von 100 Ω (Herstellerangabe). Daran fallen bei Vollausschlag 2 V ab.
| Strom | Spannung über der Bürde | Verlustleistung | Bemerkung |
|---|---|---|---|
| 10 mA | 1,0 V | 10 mW | Betrieb |
| 20 mA | 2,0 V | 40 mW | Vollausschlag |
| 50 mA | 5,0 V | 250 mW | zerstört den Widerstand |
Wer eine Spannung einspeisen will, etwa aus einem Drehgeber mit 0 bis 10 V, braucht einen Reihenwiderstand. Die Masse der Quelle muss mit der Masse des Moduls verbunden sein.
U_Quelle ──[ R_vor ]──> AI+ R_vor = U_max / I_max − 100 Ω Masse ─────────────────> AI− (bei 10 V und 20 mA: 400 Ω)
| R_vor | Strom bei 10 V | Rohwert | ein Zählschritt | Anteil am Bereich |
|---|---|---|---|---|
| 10 kΩ | 0,99 mA | rund 134 | 75 mV | 3 % |
| 4,7 kΩ | 2,08 mA | rund 282 | 35 mV | 7 % |
| 1 kΩ | 9,1 mA | rund 1230 | 8,1 mV | 30 % |
| 510 Ω | 16,4 mA | rund 2220 | 4,5 mV | 54 % |
Je kleiner der Vorwiderstand, desto feiner die Auflösung. Die Grenze setzt die Quelle: Ein Ausgang, der nur 1 mA treiben kann, bricht bei 510 Ω ein. Dann sinkt die Spannung, und der Zusammenhang ist nicht mehr gerade. Deshalb mit 10 kΩ beginnen und schrittweise verkleinern, solange der Rohwert proportional mitgeht.
Das Modul nimmt beide Arten von Signalen an, trockene und beschaltete Kontakte.
| Art | Was anzuschließen ist | Hinweis |
|---|---|---|
| Trockener Kontakt | Schalter oder Brücke zwischen DI und COM beziehungsweise GND | der sichere Weg, keine Fremdspannung nötig — damit anfangen |
| Beschalteter Kontakt | äußere Gleichspannung auf DI, gemeinsame Masse | nur mit geprüfter Angabe aus dem Handbuch, sonst Schaden |
Zum Prüfen genügt ein Stück Draht zwischen DI0 und COM. Die Leuchte oben muss dann binnen einer Sekunde angehen. Solange die Spannungsfestigkeit der Eingänge nicht aus dem Handbuch belegt ist, bleibt es beim trockenen Kontakt.
Potentialfreie Schließer. Last und Spannung richten sich nach dem Aufdruck des Relais; ohne belegte Angabe nicht über Kleinspannung hinausgehen. Für einen Funktionsnachweis genügt das hörbare Klicken und die Rückmeldung über Funktion 01.
| Zeit | gesendet | empfangen |
|---|---|---|
| – | ||
| Ebene | Woher sie kommt |
|---|---|
| Welche Bytes | gemessen — mitgelesen aus der laufenden Verbindung |
| Welche Bits, in welcher Reihenfolge | zwingend — die Norm der seriellen Schnittstelle legt fest: Startbit tief, acht Datenbits mit dem niederwertigsten zuerst, Stoppbit hoch. Hier gibt es keinen Spielraum, aus dem Byte folgt die Bitfolge eindeutig. |
| Wie lange ein Bit dauert | zwingend — der Kehrwert der Baudrate, bei 9600 Baud 104,17 µs |
| Wann die Antwort kam | gemessen — mit Zeitstempel beim Empfang, siehe Abschnitt 0 |
| die Pegel | normiert auf −1, 0 und +1 — es werden keine Spannungen behauptet. Welche Volt der Treiber liefert, wurde nicht gemessen und ist für das Protokoll unerheblich. |
| die Flankenform | idealisiert — gezeichnet werden saubere Kanten. In Wirklichkeit steigen sie endlich steil, mit Überschwingern und Reflexionen am Leitungsende. |
| die einblendbare Störung | hinzugerechnet, um die Wirkung der symmetrischen Übertragung zu zeigen |
Kurz: Was wann auf der Leitung lag, stimmt. Wie die Kanten genau aussahen, zeigt erst ein Oszilloskop oder ein Logikanalysator.
Hier wird nicht gerechnet, sondern gemessen: Der Dienst sendet ein Telegramm und hält fest, nach wie vielen Mikrosekunden die Antwort eintrifft. Die Zeitachse unten ist echt. Nur die Bitmuster innerhalb der beiden Blöcke sind berechnet, denn die Pegel zwischen den Bytes kann keine serielle Schnittstelle melden.
So liegt das Byte in der Schnittstelle: Ruhe auf 1, ein Startbit auf 0, acht Datenbits mit dem niederwertigsten zuerst, dann ein Stoppbit auf 1.
Aufgetragen sind die binären Werte, nicht Spannungen. Ob der Treiber daraus 5 V oder 3,3 V macht, ist für das Protokoll ohne Belang und wurde hier nicht gemessen.
Dasselbe für den vollständigen Vorgang. Links die Bits der Frage, rechts die Bits der Antwort, dazwischen die gemessene Bedenkzeit. Die Zeitachse ist durchgehend und maßstäblich, deshalb schrumpfen die Telegramme zu schmalen Blöcken — genau dieses Verhältnis ist die Aussage.
Der RS485-Treiber macht daraus zwei gegenläufige Pegel. Keine der beiden Adern trägt die Information allein. Aufgetragen ist normiert auf −1, 0 und +1, nicht in Volt.
Der Empfänger misst nur den Unterschied. Oberhalb der Schwelle liest er eine Eins, unterhalb der unteren Schwelle eine Null, dazwischen entscheidet er nicht. Die Norm legt diese Schwelle bei 200 Millivolt fest; hier ist sie normiert eingezeichnet, weil die tatsächlichen Pegel nicht gemessen wurden.
Setzen Sie den Haken bei „Störung einblenden". Dann hebt eine eingekoppelte Störung beide Adern gemeinsam an — im zweiten Bild deutlich sichtbar. Im dritten Bild, der Differenz, ist sie verschwunden. Genau das ist der Grund, warum ein Feldbus symmetrisch überträgt und nicht gegen Masse.
Eine Störung, die beide Adern gleich trifft, heißt Gleichtaktstörung. Der Empfänger unterdrückt sie, solange sie die zulässige Gleichtaktspannung nicht überschreitet, bei RS485 von −7 V bis +12 V.
Das ist eine Festlegung der seriellen Schnittstelle, keine von Modbus. Beim Lesen eines Oszillogramms muss man deshalb rückwärts zusammensetzen: Das erste Datenbit nach dem Startbit ist Bit 0, das letzte ist Bit 7.
Jedes Byte belegt zehn Bitzeiten: ein Start, acht Daten, ein Stopp. Bei 9600 Baud sind das 1,042 ms je Byte.
t_Byte = 10 / 9600 Bit/s = 1,042 ms t_Telegramm (8 Byte) = 8,33 ms dazu die Antwortzeit des Moduls, hier gemessen über 40 ms
Daran sieht man sofort, warum die Wartezeit von 40 ms im ersten Scan zu knapp war: Die reine Übertragung ist nur ein Bruchteil der Zeit, die das Modul zum Antworten braucht.
Modbus RTU trennt zwei Telegramme nicht durch ein Sonderzeichen, sondern durch eine Pause von mindestens 3,5 Zeichenzeiten. Bei 9600 Baud sind das 3,65 ms. Wer diese Pause nicht einhält, hängt zwei Telegramme aneinander, und der Empfänger findet den Anfang nicht mehr.
t_Pause ≥ 3,5 · 10 / 9600 Bit/s = 3,65 ms Ab 19200 Baud gilt eine feste Pause von 1,75 ms.
Ein Register ist bei Modbus immer genau 16 Bit breit. Nicht 8, nicht 32. Alles, was ein Gerät an Zahlen herausgibt oder entgegennimmt, muss in diese Schublade passen oder auf mehrere verteilt werden. Aus dieser einen Festlegung folgen fast alle Schwierigkeiten, die man in der Praxis hat.
| Bereich | Breite | Richtung | Funktionen | Wofür |
|---|---|---|---|---|
| Coils | 1 Bit | lesen, schreiben | 01, 05, 15 | Relais, Schaltausgänge |
| Discrete Inputs | 1 Bit | nur lesen | 02 | Schalter, Melder |
| Input Registers | 16 Bit | nur lesen | 04 | Messwerte |
| Holding Registers | 16 Bit | lesen, schreiben | 03, 06, 16 | Sollwerte, Einstellungen |
Die Trennung ist eine Festlegung des Geräteherstellers, keine Naturgesetz. Manche Geräte legen Messwerte in Holding Register, andere in Input Register. Es gibt Geräte, die beides anbieten. Nur das Handbuch oder die Messung sagt, wo etwas liegt.
In alten Unterlagen steht oft eine fünfstellige Zahl wie 40001. Das ist keine
Adresse, sondern eine Schreibweise aus der Zeit von Modicon:
| Schreibweise | Bereich | Was im Telegramm steht |
|---|---|---|
| 0xxxx, z. B. 00001 | Coils | Adresse 0 |
| 1xxxx, z. B. 10001 | Discrete Inputs | Adresse 0 |
| 3xxxx, z. B. 30001 | Input Register | Adresse 0 |
| 4xxxx, z. B. 40001 | Holding Register | Adresse 0 |
Die führende Ziffer nennt den Bereich, der Rest ist die Adresse plus eins. Register 40001 ist also das Holding Register mit der Adresse 0. Wer die 40001 ins Telegramm schreibt, liest an einer ganz anderen Stelle — oder bekommt eine Ausnahme.
Faustregel: Im Telegramm steht immer null-basiert. Alles andere ist Darstellung in einem Handbuch oder in einer Bediensoftware.
Ein Register fasst Werte von 0 bis 65535, oder mit Vorzeichen von −32768 bis 32767. Für eine Temperatur mit einer Nachkommastelle reicht das; für eine Gleitkommazahl nicht. Geräte verteilen solche Werte deshalb auf zwei aufeinanderfolgende Register.
Eine 32-Bit-Zahl besteht aus vier Bytes, nennen wir sie A, B, C und D. Zwei Register können sie auf vier Arten tragen:
| Name | Register n | Register n+1 | Üblich bei |
|---|---|---|---|
| ABCD (big endian) | A B | C D | Advantech ADAM, viele Messgeräte |
| CDAB (word swap) | C D | A B | viele SPS, Schneider |
| BADC (byte swap) | B A | D C | selten |
| DCBA (little endian) | D C | B A | selten |
Liest man mit der falschen Reihenfolge, bekommt man keine Fehlermeldung, sondern eine plausibel aussehende falsche Zahl. Das ist die gefährlichste Art von Fehler.
Aus einem früheren Projekt. Das Modul liefert acht Analogkanäle, je zwei Register, als 32-Bit-Gleitkommazahl nach IEEE 754, höherwertiges Wort zuerst. Der Zahlenwert ist direkt die Spannung, ohne jede Umrechnung.
volt = struct.unpack('>f', struct.pack('>HH', reg[2*k], reg[2*k+1]))[0]
Der ursprüngliche Code las jedes Register einzeln als Ganzzahl und rechnete mit einem Skalierungsfaktor. Das ging zufällig gut bei 6,25 Volt:
| Spannung | als Float | Register n | falsch gelesen ergab |
|---|---|---|---|
| 6,25 V | 0x40C80000 | 0x40C8 = 16584 | zufällig fast richtig |
| 0 V | 0xBA83126F | 0xBA83 = 47747 | −6,862 V — grober Unsinn |
Die vermeintliche Kalibrierung war ein Ein-Punkt-Fit-Artefakt. Sie wurde an einem einzigen Wert geprüft und stimmte deshalb nur dort.
Die Lehre: Eine Umrechnung, die an einem Punkt stimmt, ist nicht geprüft. Mindestens zwei Punkte, besser drei, und einer davon nahe null.
Viele Geräte lassen sich über Modbus selbst umstellen: Busadresse, Baudrate, Messbereich. Diese Register liegen meist weit oben im Adressraum, damit sie nicht mit Nutzdaten kollidieren.
Ein weiteres Gerät aus einem früheren Projekt, verifiziert mit einem Multimeter.
| Was | Funktion | Adresse | Bedeutung |
|---|---|---|---|
| Relais 1 und 2 | 05 | 0x0000, 0x0001 | 0xFF00 ein, 0x0000 aus, 0x5500 umschalten |
| Digitaleingänge | 02 | 0x0000 | 2 Bit |
| Analogeingänge | 04 | 0x0000 | Einheit hängt vom Modus ab |
| Messbereich AI | 03, 06 | 0x3000, 0x3001 | 0 = 0–5/10 V in mV · 1 = 1–5/2–10 V · 2 = 0–20 mA in µA · 3 = 4–20 mA · 4 = Rohwert |
| Analogausgänge | 03, 06 | 0x0000, 0x0001 | nur Strom, Wert in µA von 0 bis 20000 |
| Busadresse | 03, 06 | 0x4000 | Vorsicht: danach antwortet es anders |
| Schnittstelle | 03, 06 | 0x2000 | Baudrate und Format |
| Firmwarestand | 03 | 0x8000 | Wert durch hundert |
Zwei Dinge sind daran bemerkenswert. Erstens der Umschaltbefehl 0x5500: Die Norm kennt nur 0xFF00 und 0x0000, dieser Hersteller hat einen dritten Wert ergänzt. Zweitens die Einheit µA statt eines Prozentwerts, was die Umrechnung erspart.
Wer die Busadresse über Register 0x4000 ändert, verliert sofort die Verbindung — das Gerät antwortet ab dem nächsten Telegramm unter der neuen Adresse. Das ist kein Fehler, sondern die Folge. Vorher aufschreiben, was man einstellt.
Das MA01-AACX2240 verhält sich anders. Seine Holding Register liefern bei jeder Adresse denselben Wert 0x3132, ob man Register 0, 100, 1000 oder 4096 abfragt. Dort liegen keine Einstellungen. Wer sie dort vermutet, liest ein Füllmuster und hält es für Daten.
Diese Gegenprobe — dieselbe Frage an verschiedene Stellen — kostet eine Minute und gehört an den Anfang jeder Inbetriebnahme.
Aus einem dritten Projekt. Ein ESP32 wurde zum Modbus-RTU-Teilnehmer gemacht, damit eine Visualisierung ihn wie ein gekauftes Modul ansprechen kann. Der Registerplan wurde dabei selbst festgelegt — und genau das ist der Punkt: Ein Registerplan ist eine Vereinbarung, keine Eigenschaft der Hardware.
| Größe | Register | Anschluss am ESP32 | Wertebereich |
|---|---|---|---|
| AI1 bis AI4 | Holding 0 bis 3 | GPIO 34, 35, 32, 33 | 0 bis 4095 |
| AO1 und AO2 | Holding 10 und 11 | GPIO 25, 26 | 0 bis 255 |
| Leuchte | Coil 0 | GPIO 2 | ein oder aus |
Der Teilnehmer beherrscht die Funktionen 01, 03, 05, 06 und 16. Das Telegrammende erkennt er an einer Sendepause von fünf Millisekunden — die Umsetzung der Regel von dreieinhalb Zeichenzeiten.
| Einstellung | Wert | Warum |
|---|---|---|
| Datenpunkttyp | WI, also Wort-Eingang, 16 Bit | Register sind 16 Bit |
| Wortreihenfolge | normal | Einzelregister, keine 32-Bit-Werte |
| Adressversatz | roh, null-basiert | der Testwert liegt auf Register 0 |
| Funktion | 03 | Holding Register |
In manchen Visualisierungen steckt der Funktionscode in der Klammerzahl hinter dem Datenpunkttyp. Wer das nicht weiß, sucht lange nach einer Einstellung, die scheinbar fehlt.
Modbus gibt es in zwei Verpackungen. Der Inhalt ist identisch: Funktionscode, Adresse, Daten. Unterschiedlich ist, was außen herum steht.
| Modbus RTU | Modbus TCP | |
|---|---|---|
| Träger | RS485 oder RS232 | Ethernet |
| Vorspann | keiner | MBAP-Kopf, genau 7 Byte |
| Prüfsumme | CRC-16, 2 Byte | keine — das macht TCP |
| Telegrammgrenze | Pause von 3,5 Zeichen | Längenangabe im Kopf |
| Teilnehmer | Adresse 1 bis 247 | Unit-Kennung, meist 1 |
Der MBAP-Kopf enthält eine laufende Nummer, eine Protokollkennung, die Länge und die Unit-Kennung. Wer RTU-Telegramme über eine transparente Brücke schickt, lässt ihn weg und behält das CRC — das nennt sich dann RTU over TCP und ist etwas anderes als Modbus TCP. Beide Wege kamen in früheren Projekten vor, und die Verwechslung kostet Zeit.
Ein Erfahrungswert aus dem Betrieb eines solchen Umsetzers: Manche Gateways verkraften nur eine gleichzeitige Verbindung. Ein offenes Webinterface blockiert dann den Datenverkehr, ohne eine Meldung zu erzeugen.
Trendows spricht Modbus, aber mit eigenen Begriffen. Wer die Übersetzung kennt, ist in zehn Minuten fertig; wer sie nicht kennt, sucht stundenlang nach Einstellungen, die es gar nicht gibt. Diese Seite zeigt die Dialoge aus drei wirklich aufgebauten Anlagen.
Element bearbeiten, Bus-Modul. Oben die Teilnehmeradresse, darunter die Schnittstelle, dann Modul-Typ und Modul-Einstellung. Unten die Tabelle der Datenpunkte.
| Trendows sagt | Modbus heißt das | Breite |
|---|---|---|
| Modul-Adresse | Teilnehmeradresse, das erste Byte jedes Telegramms | 1 bis 247 |
| Schnittstellen-Einstellung | Anschluss, Baudrate, Parität, Datenbits, Stoppbits | z. B. COM10: 9600,N,8,1 |
| Modul-Typ | das Protokoll — hier immer „Modbus" | |
| Modul-Einstellung | die Wortreihenfolge bei mehrwortigen Zahlen | „normale Modbus word order" |
| Adress-Offset | die Startadresse im Telegramm, null-basiert | 0 = das erste Register |
| Anzahl | wie viele Register oder Bits am Stück gelesen werden |
Unter der Modul-Einstellung steht eine Zeile, die leicht übersehen wird und doch den Schlüssel enthält:
Typ: DI[1/2], WI, LI, AI[4/3] = Bit, Word, Long, Analog In
DO, WO, LO, AO = Bit, Word, Long, Analog Out
Der Buchstabe nennt die Breite und die Richtung, die Zahl in Klammern ist der Modbus-Funktionscode. Damit löst sich auf, was sonst rätselhaft bleibt:
| Eintrag | bedeutet | Funktion | Modbus-Bereich |
|---|---|---|---|
DI (1) | Bit-Eingang | 01 | Coils lesen |
DI (2) | Bit-Eingang | 02 | Discrete Inputs |
WI (3) | Wort-Eingang, 16 Bit | 03 | Holding Register |
WI (4) | Wort-Eingang, 16 Bit | 04 | Input Register |
AI (4) | Analogwert | 04 | Input Register |
LI | Langwort, 32 Bit über zwei Register | 03 oder 04 | hier zählt die Wortreihenfolge |
DO (5) | Bit-Ausgang, einzeln | 05 | eine Coil schreiben |
DO (15) | Bit-Ausgang, mehrere | 15 (0x0F) | mehrere Coils |
WO (6) | Wort-Ausgang, einzeln | 06 | ein Register |
WO (16) | Wort-Ausgang, mehrere | 16 (0x10) | mehrere Register |
Wer hier die falsche Zahl wählt, bekommt eine Ausnahmeantwort mit Code 1, „Funktion nicht erlaubt". Das Gerät antwortet also, kann aber mit der Funktion nichts anfangen. Diese Meldung ist ein Hinweis auf die Klammerzahl, nicht auf die Verdrahtung.
Für das MA01-AACX2240 dieses Versuchs, gemessen und belegt:
| Feld | Wert | woher |
|---|---|---|
| Modul-Adresse | 32 | gemessen, nicht von den DIP-Schaltern ablesbar |
| Schnittstelle | COM4: 9600, N, 8, 1 | gemessen |
| Modul-Typ | Modbus | |
| Modul-Einstellung | normale Modbus word order | keine 32-Bit-Werte im Spiel |
Die Datenpunkte in der Tabelle darunter:
| Nr. | Typ | Anzahl | Adress-Offset | Was es ist |
|---|---|---|---|---|
| 1 | DI (2) | 2 | 0 [0x0000] | die beiden Digitaleingänge |
| 2 | AI (4) | 2 | 0 [0x0000] | die beiden Analogeingänge, Rohwert |
| 3 | DO (5) | 4 | 0 [0x0000] | die vier Relais |
Die Analogwerte kommen als Rohwert an, nicht in Milliampere. Die Umrechnung gehört in die Visualisierung: gemessen entsprechen 135,5 Zählschritte einem Milliampere. Wer eine Spannung über einen Vorwiderstand einspeist, rechnet weiter mit U = I · (R_vor + 100 Ω).
Für die Relais ist DO (5) die sichere Wahl: Funktion 05
schaltet eine einzelne Coil und wird vom Modul gespiegelt, was eine Rückmeldung ergibt.
DO (15) schaltet alle vier gleichzeitig, falls das gewünscht ist.
Derselbe Dialog, aber als Lan-IO: statt einer Schnittstelle steht hier eine Netzwerkadresse mit Port 502.
| Feld | Wert | Bemerkung |
|---|---|---|
| Port | 502 | der feste Port für Modbus TCP |
| Adresse im Netz | 192.168.x.x | das Gateway, nicht das Modul (Adresse hier anonymisiert) |
| Wartezeit zwischen zwei Messungen | 100 ms | Abfragetakt |
| Datenpunkt | AI (4), Anzahl 24, Offset 200 [0x00C8] |
drei Module zu je acht Kanälen als ein Block |
| Modul-Adresse | 2 | die Unit-Kennung des Gateways |
Zwei Dinge sind hier lehrreich. Erstens ist die Modul-Adresse nicht die des Messmoduls, sondern die Unit-Kennung, unter der das Gateway den Block anbietet. Zweitens liegen die 24 Kanäle nicht ab Adresse 0, sondern ab 200 — ein Versatz, den das Gateway festlegt.
Die Falle dieses Aufbaus: Die 24 Werte sind keine 24 Zahlen, sondern zwölf Gleitkommazahlen zu je zwei Registern. Wer sie einzeln als Ganzzahl liest, bekommt plausible, aber falsche Werte. Siehe den Reiter Register.
Ein Mikrocontroller als Modbus-Teilnehmer. Der Registerplan wurde selbst festgelegt, Trendows merkt davon nichts.
| Nr. | Typ | Anzahl | Offset | Was dahintersteckt |
|---|---|---|---|---|
| 1 | WI (4) | 4 | 0 [0x0000] | vier Analogeingänge des Mikrocontrollers |
| 2 | WO (16) | 2 | 10 [0x000A] | zwei Analogausgänge |
| 3 | DO (15) | 1 | 0 [0x0000] | eine Leuchte |
Hier sieht man die Klammerzahlen in ihrer vollen Bedeutung: (16) schreibt
mehrere Register am Stück, (15) mehrere Bits. Der selbstgebaute Teilnehmer
musste genau diese Funktionen beherrschen, sonst hätte er mit einer Ausnahme geantwortet.
Beim Offset 10 für die Ausgänge ist nichts geraten: Der Registerplan des Teilnehmers legt die Analogausgänge auf die Register 10 und 11. Ein Registerplan ist eine Vereinbarung zwischen zwei Programmen, und beide Seiten müssen dieselbe kennen.
| Beobachtung | Wahrscheinliche Ursache |
|---|---|
| gar keine Verbindung | Adresse, Baudrate oder Anschluss falsch; oder ein anderes Programm hält die Schnittstelle besetzt |
| Ausnahme 1, Funktion nicht erlaubt | falsche Klammerzahl beim Datenpunkttyp |
| Ausnahme 2, Adresse nicht erlaubt | Offset oder Anzahl zu groß |
| Werte da, aber unsinnig | Wortreihenfolge, oder 32-Bit-Werte als Einzelregister gelesen |
| Werte um eins verschoben | die 40001-Schreibweise unbesehen übernommen |
| es läuft, bricht aber zusammen, sobald ein zweites Programm zugreift | bei RS485 darf nur ein Leiter senden; manche Gateways erlauben nur eine Verbindung |
Vorlesung Feldbusse · Prof. Dr.-Ing. Ralph Wystup M.Sc. — erstellt mit KI und Agent (Claude Code, Anthropic) · 24. Oktober 2026
Vor Ihnen liegt kein Lehrbuchkapitel, das ein fertiges Ergebnis vorführt. Es ist das Protokoll einer Inbetriebnahme, die am 24. Oktober 2026 um 15:58 Uhr begann und um 16:53 Uhr mit einem fertigen Prüfstand endete. Fünfundfünfzig Minuten, von einem Modul, dessen Adresse niemand kannte, bis zu einer Bedienseite mit Zeigerinstrumenten, Verlaufsgraph und zwei voneinander unabhängigen Zugriffswegen.
Das ist die eigentliche Botschaft. Nicht, dass Modbus RTU ein einfaches Protokoll ist — das war es immer schon. Sondern dass sich die Zeit von der ersten Frage bis zur belastbaren Messung heute in Minuten rechnet, wenn ein Mensch mit Hardwareverstand und eine KI mit Zugriff auf diese Hardware zusammenarbeiten.
Wichtiger als die Geschwindigkeit ist allerdings, was dabei schiefging. Drei Fallen haben uns aufgehalten, und jede einzelne hätte einen Anfänger zu dem Schluss gebracht, das Modul sei defekt. Alle drei sind in diesem Manuskript dokumentiert, mit den Messwerten, die sie aufgedeckt haben.
In einer Anlage sitzen Sensoren und Aktoren verteilt. Jeder einzelne mit eigenem Kabel zur Steuerung zu führen, nennt man Parallelverdrahtung, und sie ist aus drei Gründen schlecht: Das Kupfer wird teuer, die Fehlersuche wird unübersichtlich, und jede Erweiterung bedeutet ein neues Kabel durch die ganze Halle.
Ein Feldbus führt stattdessen eine einzige Leitung an allen Teilnehmern vorbei. Jeder hat eine Adresse, und wer etwas will, spricht einen gezielt an. Aus n Kabeln wird eines.
Modbus ist der älteste dieser Busse, 1979 von Modicon veröffentlicht, und er ist aus einem Grund nicht totzukriegen: Er ist so einfach, dass man ihn vollständig verstehen kann. Genau das machen wir in diesem Versuch. Wir benutzen keine fertige Modbus-Bibliothek. Jedes Telegramm wird von Hand gebaut, jede Prüfsumme selbst gerechnet. Was Sie hier lesen, können Sie auf Papier nachvollziehen.
Man muss zwei Dinge auseinanderhalten, die oft in einen Topf geworfen werden:
| Ebene | Was sie regelt | Hier im Versuch |
|---|---|---|
| Physikalisch | Spannungen, Leitungen, Pegel | RS485, zwei Adern A und B |
| Protokoll | Wer wann was sagt, Datenformat | Modbus RTU |
RS485 ist eine symmetrische Übertragung: Das Signal steht nicht als Spannung gegen Masse, sondern als Differenz zwischen zwei Adern. Fängt sich das Kabel eine Störung ein, trifft sie beide Adern gleich, und die Differenz bleibt unverändert. Deshalb schafft RS485 über tausend Meter, während ein einfacher Spannungspegel nach wenigen Metern aufgibt.
Modbus RTU ist das Protokoll darüber. RTU heißt remote terminal unit und bedeutet hier: Die Daten gehen als rohe Bytes über die Leitung, nicht als lesbarer Text. Es gibt auch Modbus ASCII, das ist lesbar, aber doppelt so lang.
Modbus kennt nur eine Gesprächsform: Ein Leiter (früher Master) fragt, ein Teilnehmer (früher Slave) antwortet. Teilnehmer reden nie von selbst. Das klingt altmodisch, hat aber einen unschlagbaren Vorteil: Auf der Leitung kann es keine Kollision geben, weil immer nur einer sendet.
Im Versuch ist der PC der Leiter und das Modul der Teilnehmer. Wenn Sie in der Telegrammtabelle des Prüfstands mitlesen, sehen Sie genau dieses Wechselspiel: eine Zeile hin, eine Zeile zurück.
Ein Modbus-RTU-Telegramm hat immer denselben Aufbau:
┌─────────┬──────────────┬────────────┬──────────────┐
│ Adresse │ Funktionscode│ Nutzdaten │ Prüfsumme │
│ 1 Byte │ 1 Byte │ 0..252 B │ 2 Byte │
└─────────┴──────────────┴────────────┴──────────────┘
Nehmen wir das erste Telegramm, das unser Modul je beantwortet hat:
gesendet: 20 03 00 00 00 01 82 bb
empfangen: 20 03 02 31 32 90 06
Die Frage zerlegt:
| Byte | Wert | Bedeutung |
|---|---|---|
| 1 | 20 |
Adresse 32 (hexadezimal 0x20) |
| 2 | 03 |
Funktion 3: Halteregister lesen |
| 3–4 | 00 00 |
ab Register 0 |
| 5–6 | 00 01 |
ein Register |
| 7–8 | 82 bb |
Prüfsumme |
Die Antwort zerlegt:
| Byte | Wert | Bedeutung |
|---|---|---|
| 1 | 20 |
von Adresse 32 |
| 2 | 03 |
Antwort auf Funktion 3 |
| 3 | 02 |
es folgen 2 Byte |
| 4–5 | 31 32 |
der Inhalt, 0x3132 = 12594 |
| 6–7 | 90 06 |
Prüfsumme |
Mehr ist es nicht. Wer das verstanden hat, versteht Modbus.
Modbus unterscheidet vier Arten von Daten. Die Einteilung stammt aus der Welt der Relaissteuerungen und wirkt heute altertümlich, ist aber eindeutig:
| Bereich | Größe | Richtung | Funktionscode | In unserem Modul |
|---|---|---|---|---|
| Coils | 1 Bit | lesen und schreiben | 01, 05, 15 | die vier Relaisausgänge |
| Discrete Inputs | 1 Bit | nur lesen | 02 | die zwei Digitaleingänge |
| Input Registers | 16 Bit | nur lesen | 04 | die zwei Analogeingänge |
| Holding Registers | 16 Bit | lesen und schreiben | 03, 06, 16 | Einstellungen |
Coil heißt wörtlich Spule und meint die Spule eines Relais. Was früher ein Relais war, ist heute ein Bit — der Name blieb.
Merken Sie sich die Zuordnung: Bit oder Wort, lesen oder schreiben. Daraus folgt der Funktionscode von selbst.
Modbus kennt über zwanzig Funktionscodes. In der Praxis braucht man acht, und die stehen hier vollständig, jeweils mit dem Aufbau von Frage und Antwort. Alle Beispiele stammen aus diesem Versuch, Adresse 32 (0x20).
Frage : Adr | 01 | Start hi | Start lo | Anzahl hi | Anzahl lo | CRC lo | CRC hi
Antwort: Adr | 01 | Bytezahl | Daten... | CRC lo | CRC hi
Beispiel aus dem Versuch, vier Relais ab Nummer 0:
hin : 20 01 00 00 00 04 3b 78
zurück : 20 01 01 00 5b b4
Die Antwort enthält ein Datenbyte, weil vier Bits in
ein Byte passen. Der Wert 00 bedeutet: alle vier aus. Die
Bits stehen von rechts nach links: Bit 0 ist DO0.
Nach dem Einschalten aller vier Relais sah dieselbe Abfrage so aus:
zurück : 20 01 01 0f ... 0x0F = 0b00001111 = alle vier ein
Gleicher Aufbau wie 01, nur nicht beschreibbar.
hin : 20 02 00 00 00 02 ff 7a
zurück : 20 02 01 00 ab b4 beide Eingänge offen
Frage : Adr | 03 | Start hi | Start lo | Anzahl hi | Anzahl lo | CRC
Antwort: Adr | 03 | Bytezahl | Wort 1 hi | Wort 1 lo | ... | CRC
Jedes Register ist 16 Bit breit, die Bytezahl ist also immer das Doppelte der Registeranzahl:
ein Register : 20 03 00 00 00 01 82 bb → 20 03 02 31 32 90 06
zwei Register: 20 03 00 00 00 02 c2 ba → 20 03 04 31 32 31 32 f0 47
vier Register: 20 03 00 00 00 04 42 b8 → 20 03 08 31 32 31 32 31 32 31 32 ed 63
Diese drei Zeilen sind der Beleg für Falle 3: Die Bytezahl wächst richtig mit, der Inhalt wiederholt sich aber stumpf.
Aufbau wie 03, aber nur lesbar. Hier liegen die Analogeingänge:
hin : 20 04 00 00 00 02 77 7a
zurück : 20 04 04 00 00 00 00 ca 86 beide Eingänge 0
Mit 10 mA an AI1 lautete die Antwort:
zurück : 20 04 04 05 4b 00 00 ... 0x054B = 1355
Frage : Adr | 05 | Adr hi | Adr lo | Wert hi | Wert lo | CRC
Antwort: dasselbe Telegramm zurück
Der Wert kennt nur zwei erlaubte Belegungen:
| Wert | Bedeutung |
|---|---|
FF 00 |
ein |
00 00 |
aus |
Alles andere beantwortet das Gerät mit einer Ausnahme. Diese Eigenheit stammt aus der Zeit, als eine Coil wirklich eine Relaisspule war.
DO0 ein : 20 05 00 00 ff 00 8a 8b → 20 05 00 00 ff 00 8a 8b
DO0 aus : 20 05 00 00 00 00 cb 7b → 20 05 00 00 00 00 cb 7b
Das Gerät spiegelt den Befehl. Das ist die Bestätigung auf Protokollebene.
Frage : Adr | 06 | Adr hi | Adr lo | Wert hi | Wert lo | CRC
Antwort: dasselbe Telegramm zurück
Hier ist jeder 16-Bit-Wert erlaubt. Typisch für Einstellungen wie Busadresse oder Baudrate. In diesem Versuch nicht benutzt, weil die Halteregister des Moduls keine echten Daten führen.
Frage : Adr | 0F | Start hi | Start lo | Anzahl hi | Anzahl lo | Bytezahl | Daten | CRC
Antwort: Adr | 0F | Start hi | Start lo | Anzahl hi | Anzahl lo | CRC
Damit schaltet man alle vier Relais in einem Telegramm. Für alle ein:
hin : 20 0f 00 00 00 04 01 0f ... Bytezahl 1, Daten 0x0F
Der Vorteil ist nicht die Ersparnis an Bytes, sondern die Gleichzeitigkeit: Alle vier Relais schalten im selben Moment. Bei vier einzelnen Telegrammen liegen zwischen dem ersten und dem letzten rund eine halbe Sekunde.
Frage : Adr | 10 | Start hi | Start lo | Anzahl hi | Anzahl lo | Bytezahl | Daten | CRC
Antwort: Adr | 10 | Start hi | Start lo | Anzahl hi | Anzahl lo | CRC
Das Gegenstück zu 15 für Wortdaten.
| Code | Bedeutung | Typischer Anlass |
|---|---|---|
| 01 | unerlaubte Funktion | Gerät kennt den Funktionscode nicht |
| 02 | unerlaubte Datenadresse | Register oder Coil gibt es nicht |
| 03 | unerlaubter Datenwert | etwa ein anderer Wert als FF 00 bei Funktion 05 |
| 04 | Gerätefehler | interner Fehler |
| 05 | Anfrage wird bearbeitet | Antwort folgt später |
| 06 | Gerät belegt | später erneut fragen |
Das Antworttelegramm ist immer fünf Byte lang:
Adr | Funktionscode + 0x80 | Ausnahmecode | CRC lo | CRC hi
Die beiden letzten Bytes sichern das Telegramm. Modbus verwendet eine zyklische Redundanzprüfung mit dem Polynom 0xA001 und dem Startwert 0xFFFF. Der Algorithmus ist kurz genug, um ihn hinzuschreiben:
def crc16(daten):
pruef = 0xFFFF
for byte in daten:
pruef ^= byte # Byte einmischen
for _ in range(8): # acht Schiebeschritte
if pruef & 1:
pruef = (pruef >> 1) ^ 0xA001
else:
pruef = pruef >> 1
return pruef
Zwei Feinheiten, an denen Anfänger scheitern:
82, dann
bb. Das ist die umgekehrte Reihenfolge wie bei den
Registeradressen, die höherwertig zuerst stehen. Modbus ist hier
inkonsequent, und das ist historisch gewachsen.Rechnen wir die Prüfsumme für 20 03 00 00 00 01 aus,
also unsere erste Frage. Der Startwert ist 0xFFFF.
Erstes Byte, 0x20:
Start 1111 1111 1111 1111 = 0xFFFF
XOR mit 0x20 0000 0000 0010 0000
ergibt 1111 1111 1101 1111 = 0xFFDF
Jetzt acht Schiebeschritte. In jedem Schritt wird geprüft, ob das unterste Bit gesetzt ist:
| Schritt | Wert vorher | unterstes Bit | Aktion | Wert nachher |
|---|---|---|---|---|
| 1 | 0xFFDF | 1 | schieben, dann XOR 0xA001 | 0xDFEF |
| 2 | 0xDFEF | 1 | schieben, dann XOR 0xA001 | 0xAFF6 |
| 3 | 0xAFF6 | 0 | nur schieben | 0x57FB |
| 4 | 0x57FB | 1 | schieben, dann XOR 0xA001 | 0xEBFC |
| 5 | 0xEBFC | 0 | nur schieben | 0x75FE |
| 6 | 0x75FE | 0 | nur schieben | 0x3AFF |
| 7 | 0x3AFF | 1 | schieben, dann XOR 0xA001 | 0x9D7E |
| 8 | 0x9D7E | 0 | nur schieben | 0x4EBF |
Nach dem ersten Byte steht also 0x4EBF. Dasselbe wiederholt sich für die übrigen fünf Bytes. Am Ende steht 0xBB82.
Und jetzt der Fallstrick: Auf die Leitung kommt das niederwertige Byte zuerst:
0xBB82 → 82 bb
Deshalb endet unser Telegramm auf 82 bb und nicht auf
bb 82. Vergleichen Sie mit der Registeradresse im selben
Telegramm: Die steht höherwertig zuerst. Modbus ist hier uneinheitlich,
und diese eine Zeile Code hat schon viele Abende gekostet.
Warum überhaupt eine Prüfsumme? Weil auf einem Kabel in einer Anlage Störungen auftreten. Ein umgekipptes Bit würde sonst unbemerkt als Messwert durchgehen. Mit CRC-16 bleibt die Wahrscheinlichkeit, dass ein gestörtes Telegramm dennoch als gültig gilt, unter 1 zu 65536.
Kann der Teilnehmer die Anfrage nicht erfüllen, antwortet er nicht mit Schweigen, sondern mit einer Ausnahme. Dann ist im Funktionscode das höchste Bit gesetzt:
| Gesendet | Ausnahmeantwort | Bedeutung |
|---|---|---|
03 |
83 |
Funktion 3 abgelehnt |
05 |
85 |
Funktion 5 abgelehnt |
Das folgende Byte nennt den Grund: 1 für unerlaubte Funktion, 2 für unerlaubte Adresse, 3 für unerlaubten Wert, 4 für Gerätefehler.
Eine Ausnahmeantwort ist ein gutes Zeichen. Sie beweist, dass das Gerät da ist, zuhört und Ihre Telegramme versteht. Nur der Inhalt passt nicht. Schlimmer ist Schweigen.
| Teil | Was es ist |
|---|---|
| Wandler | Waveshare USB TO RS232/485 (B), mit einem FTDI FT232, meldet sich als COM4 |
| Modul | EBYTE MA01-AACX2240 |
| Verbindung | zwei Adern, A und B |
Das Modul bringt mit:
Ein solches Modul heißt Remote-I/O. Es sitzt dort, wo die Signale entstehen, und führt nur den Bus zur Steuerung zurück. Genau dafür wurden Feldbusse erfunden.
Drei Dinge braucht man, um mit einem unbekannten Modbus-Teilnehmer zu sprechen:
Keines davon stand fest. Der Anschluss war schnell gefunden: Die Abfrage der seriellen Schnittstellen meldete COM3 mit einem CH340-Chip und COM4 mit einem FTDI. Der Waveshare-Wandler trägt einen FTDI, also COM4.
Die übliche Methode bei unbekannter Adresse ist ein Scan: Man fragt der Reihe nach alle Adressen von 1 bis 247 und schaut, wer antwortet. Das lief über sechs Baudraten. Ergebnis:
Keine einzige Antwort.
Nach der üblichen Logik wäre die Diagnose jetzt: falsch verdrahtet, A und B vertauscht, Modul ohne Strom oder defekt. Die Diagnose wäre falsch gewesen.
Falle 1: Die Antwortzeit. Der Scan wartete 40 Millisekunden auf Antwort. Das Modul braucht länger. Mit 150 Millisekunden Wartezeit antwortete es auf Anhieb.
Rechnen wir nach, warum 40 ms zu wenig sind. Bei 9600 Baud und 8N1 braucht ein Byte zehn Bitzeiten:
Ein Antworttelegramm von sieben Byte dauert also gut 7 ms. Dazu kommt die Zeit, die das Modul zum Nachdenken braucht, und die steht in keinem Datenblatt. Bei diesem Modul sind es offenbar über 40 ms.
Die Lehre: Wer zu ungeduldig misst, hält ein gesundes Gerät für tot. Bei einem unbekannten Teilnehmer beginnt man großzügig und verkürzt erst, wenn die Antwort sicher kommt.
Mit längerer Wartezeit und zusätzlich geprüften Paritäten meldete sich das Modul:
9600 8N1 Adresse 32: 20 03 02 31 32 90 06
Adresse 32, 9600 Baud, 8N1. Der Auftraggeber bestätigte unabhängig: „jetzt habe ich auch zwei mal kurz die RX-LED gesehen.” Ein Beleg mehr, und zwar ein physikalischer.
Falle 2: Die Adresse stimmt nicht mit den Schaltern überein. Auf dem Modul sitzen fünf DIP-Schalter, und alle standen auf Null. Nach der üblichen Erwartung wäre die Adresse damit 0 oder 1. Sie ist 32. Die Schalter addieren nur zu einer im Gerät gespeicherten Grundadresse.
Die Lehre: Ein Blick auf die Schalter ist eine Vermutung, keine Messung. Nur das Telegramm, das zurückkommt, beweist die Adresse.
Mit bekannter Adresse wurden alle vier Bereiche abgefragt:
| Bereich | Funktion | Antwort | Deutung |
|---|---|---|---|
| Relais | 01 | 20 01 01 00 5b b4 |
alle vier aus |
| Digitaleingänge | 02 | 20 02 01 00 ab b4 |
beide offen |
| Analogeingänge | 04 | 20 04 04 00 00 00 00 ca 86 |
beide 0 |
| Halteregister | 03 | 20 03 02 31 32 90 06 |
siehe unten |
Drei Bereiche lieferten plausible Werte. Der vierte war merkwürdig:
Egal ob Register 0, 1, 10, 100, 1000, 256 oder 4096 abgefragt wurde —
die Antwort war immer dieselbe, 31 32.
Falle 3: Die Halteregister sind nicht belegt. Das Gerät prüft die Registeradresse dort gar nicht und gibt ein Füllmuster zurück. Hätten wir dem Handbuch geglaubt, hätten wir dort Konfigurationsdaten vermutet und falsch interpretiert.
Die Lehre: Ein Wert, der sich bei jeder Adresse gleich verhält, ist kein Messwert. Diese Gegenprobe kostet eine Minute und verhindert eine Fehldeutung.
Um 16:03 Uhr wurde das erste Relais geschaltet. Nicht blind, sondern mit Rückmessung:
DO0 EIN hin 20 05 00 00 ff 00 8a 8b
zurück 20 05 00 00 ff 00 8a 8b Echo gleich dem Befehl
gemessen DO0..DO3 = [1, 0, 0, 0] mit Funktion 01 zurückgelesen
DO0 AUS hin 20 05 00 00 00 00 cb 7b
zurück 20 05 00 00 00 00 cb 7b
gemessen DO0..DO3 = [0, 0, 0, 0]
Beachten Sie den Aufbau des Schreibbefehls: Funktion 05 schaltet eine
einzelne Coil. Der Wert FF 00 bedeutet ein,
00 00 bedeutet aus. Andere Werte sind nicht erlaubt — eine
Eigenheit von Modbus, die auf die Relaisvergangenheit zurückgeht.
Das Modul spiegelt den Befehl, es antwortet mit demselben Telegramm. Das ist die Bestätigung auf Protokollebene.
Damit lagen drei unabhängige Belege vor:
Methodisch ist das der Kern. Ein einzelner Beleg ist eine Behauptung. Drei unabhängige Belege sind ein Nachweis.
Was folgt, sind die tatsächlichen Ausgaben der Programme, unverändert. Sie gehören in ein Manuskript, weil ein Ergebnis ohne das Protokoll seiner Entstehung nur eine Behauptung ist.
pyserial 3.5 — Suche auf COM4
9600 Baud 8N1: 0 Antwort(en)
19200 Baud 8N1: 0 Antwort(en)
38400 Baud 8N1: 0 Antwort(en)
4800 Baud 8N1: 0 Antwort(en)
115200 Baud 8N1: 0 Antwort(en)
57600 Baud 8N1: 0 Antwort(en)
Keine Antwort. Moegliche Gruende: andere Paritaet (8E1/8O1), A und B vertauscht,
Modul ohne Versorgung, oder Adresse ausserhalb 1..247.
Sechs Baudraten mal 247 Adressen sind 1482 Telegramme, und keines kam an. Beachten Sie die Schlussfolgerungen des Programms: Alle vier sind plausibel, und alle vier sind falsch. Die Wartezeit stand nicht auf der Liste, weil sie im Programm selbst steckte.
=== 1 Hoeren: sendet etwas von selbst? (3 s bei 9600 8N1) ===
nichts — normal bei einem Modbus-Slave, der nur antwortet
=== 2 Wahrscheinliche Adressen, alle Paritaeten und Baudraten ===
9600 8N1 Adresse 32: 20 03 02 31 32 90 06
9600 8E1 Adresse 32: 20 20 50 93 82 06
9600 8O1 Adresse 32: 20 20 a0 93 82 06
9600 8N2 Adresse 32: 20 03 02 31 32 90 06
=== 3 Sendet der Wandler ueberhaupt? (Schleifenprobe) ===
kein Echo — der Wandler sendet auf die Leitung, hoert aber nichts zurueck
Drei Dinge sind hier zu lernen:
Erstens beginnt das Programm mit stillem Zuhören. Ein Modbus-Teilnehmer darf von selbst nichts senden; kommt doch etwas, stimmt die Grundannahme nicht.
Zweitens sehen Sie an den Zeilen für 8E1 und 8O1,
wie eine falsche Parität aussieht: Die Bytes kommen verstümmelt an,
20 20 50 93 82 06 statt 20 03 02 31 32 90 06.
Die Prüfsumme schlägt fehl. Wer nur auf „es kommt etwas zurück” prüft,
hält das für eine Antwort.
Drittens ist 8N2 ebenfalls erfolgreich. Zwei Stoppbits statt einem stören den Empfänger nicht, weil er nach dem ersten Stoppbit ohnehin auf die nächste Flanke wartet. Umgekehrt ginge es nicht.
=== Register, verschiedene Stellen (gleiche Menge) ===
FC03 ab 0 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 1 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 10 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 100 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 1000 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 256 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
FC03 ab 4096 Anzahl 1 zurück: 20 03 02 31 32 90 06 CRC ok
Dieser Versuchsaufbau ist der ganze Trick: dieselbe Frage an verschiedene Stellen stellen. Antwortet das Gerät immer gleich, liegt dort nichts.
Hätte man nur Register 0 gelesen, wäre 0x3132 als Messwert oder Gerätekennung durchgegangen. Sieben Zeilen Protokoll haben diese Fehldeutung verhindert.
Nach dem Einzelnachweis wurden alle vier Relais über HTTP geprüft, jedes Mal mit Rückmessung:
vorher : [0, 0, 0, 0]
DO0 ein -> Antwort ok=True zurueckgelesen [1, 0, 0, 0] STIMMT
DO1 ein -> Antwort ok=True zurueckgelesen [1, 1, 0, 0] STIMMT
DO2 ein -> Antwort ok=True zurueckgelesen [1, 1, 1, 0] STIMMT
DO3 ein -> Antwort ok=True zurueckgelesen [1, 1, 1, 1] STIMMT
DO0 aus -> Antwort ok=True zurueckgelesen [0, 1, 1, 1] STIMMT
DO1 aus -> Antwort ok=True zurueckgelesen [0, 0, 1, 1] STIMMT
DO2 aus -> Antwort ok=True zurueckgelesen [0, 0, 0, 1] STIMMT
DO3 aus -> Antwort ok=True zurueckgelesen [0, 0, 0, 0] STIMMT
nachher: [0, 0, 0, 0]
Warum nicht einfach alle vier gleichzeitig einschalten und einmal
prüfen? Weil dieser Ablauf eine zusätzliche Frage beantwortet:
Trifft jeder Befehl genau sein Relais? Ein
Verdrahtungs- oder Adressierungsfehler, der DO1 und DO2 vertauscht,
bliebe bei einer Sammelprüfung unentdeckt. Hier fiele er sofort auf,
weil nach „DO1 ein” das Muster [1,1,0,0] stehen muss und
nichts anderes.
Der Auftraggeber legte nacheinander 10 mA an beide Eingänge. Das Protokoll:
Zeit AI1 roh AI2 roh
16:21:45 0 0
16:21:50 1 0
16:21:54 0 1
16:21:55 1455 1 ← Strom liegt an AI1
16:21:57 1365 1
16:21:58 1355 1
16:21:59 1328 1
16:22:01 1355 1
16:22:05 1354 1
16:22:07 1 1 ← abgeklemmt
16:22:08 1 1688 ← Strom liegt an AI2
16:22:09 1 1390
16:22:11 1 1355
16:22:14 1 1327
16:22:15 1 0 ← abgeklemmt
Zwei Beobachtungen:
Der erste Wert ist jeweils zu hoch (1455 und 1688). Das ist der Einschaltvorgang; die Quelle schwingt sich ein. Wer den ersten Messwert nimmt, misst den Einschwingvorgang.
Beide Kanäle zeigen denselben Wert bei demselben Strom, rund 1355. Das ist ein guter Beleg dafür, dass sie gleich aufgebaut sind.
Nachdem der Dienst stand, wurde die Zeit zwischen Absenden und Antwort für alle vier Lesefunktionen gemessen, und zwar mehrfach:
| Funktion | Telegramm | Bedenkzeit, erster Durchgang | zweiter Durchgang |
|---|---|---|---|
| 03 Halteregister | 20 03 00 00 00 01 82 bb |
37,30 ms | 35,48 ms |
| 01 Relais | 20 01 00 00 00 04 3b 78 |
33,35 ms | 48,18 ms |
| 02 Eingänge | 20 02 00 00 00 02 ff 7a |
32,46 ms | 48,53 ms |
| 04 Analogwerte | 20 04 00 00 00 02 77 7a |
33,77 ms | 48,70 ms |
Die erste Messreihe legte den Schluss nahe, die Bedenkzeit sei eine feste Eigenschaft des Moduls, etwa 33 Millisekunden, unabhängig von der Funktion. Die zweite Reihe widerlegt das: Dieselben Telegramme brauchten 48 Millisekunden.
Die Spanne über alle Messungen beträgt 32 bis 49 Millisekunden. Woher die Schwankung kommt, ist mit diesen Mitteln nicht zu klären. In der gemessenen Zeit stecken drei Anteile: die echte Bearbeitungszeit im Modul, die Pufferung im USB-Wandler und die Planung des Betriebssystems. Nur ein Oszilloskop an der Leitung könnte sie trennen.
Was daraus für die Praxis folgt: Die Wartezeit muss sich am ungünstigsten Fall orientieren, nicht am Mittelwert. Wer 40 Millisekunden wartet, bekommt mal eine Antwort und mal nicht — und sucht den Fehler dann in der Verdrahtung. Die 150 Millisekunden dieses Prüfstands haben Reserve.
Methodisch ist das der wichtigere Punkt. Eine einzelne Messreihe sah nach einem festen Wert aus. Erst die Wiederholung zeigte die Streuung. Eine Zahl ohne Wiederholung ist eine Momentaufnahme, keine Eigenschaft.
Vierzig Messungen am unbeschalteten Eingang:
AI1: 40 Werte
Mittelwert 0.2
kleinster 0
groesster 1
Spanne 1 Zaehlschritte
Streuung (1 Sigma) 0.40 Zaehlschritte
AI2: 40 Werte
Mittelwert 0.2
Streuung (1 Sigma) 0.43 Zaehlschritte
Diese Messung beantwortet die Frage, die bei den schwankenden 1327 bis 1390 offenblieb: Wer rauscht, das Modul oder die Quelle? Am offenen Eingang schwankt der Wert um weniger als einen Zählschritt. Also war es die Quelle.
Eine Messung, die zwanzig Sekunden kostet und eine Fehlersuche an der falschen Stelle erspart.
In der Industrie überträgt man Messwerte als Strom, typisch 4 bis 20 Milliampere. Das hat drei Gründe, die Sie sich merken sollten:
Unser Modul misst 0 bis 20 mA. Der Strom fließt über einen Bürdewiderstand von 100 Ohm (Herstellerangabe), an dem die Spannung abfällt, die der Wandler dann misst.
Daraus folgt sofort, was man nicht tun darf:
| Strom | Spannung über der Bürde | Verlustleistung | Bewertung |
|---|---|---|---|
| 10 mA | 1,0 V | 10 mW | Betrieb |
| 20 mA | 2,0 V | 40 mW | Vollausschlag |
| 50 mA | 5,0 V | 250 mW | zerstört den Widerstand |
Fünf Volt direkt an den Eingang treiben fünfzig Milliampere durch einen Widerstand, der für vierzig Milliwatt ausgelegt ist. Bei zwölf Volt wären es 1,4 Watt. Dann raucht es.
Bei 12 V und 100 Ω: W.
Ein Drehgeber mit 0 bis 10 V Ausgang lässt sich trotzdem anschließen, über einen Vorwiderstand:
U_Quelle ──[ R_vor ]──> AI+
Masse ─────────────────> AI−
Der Strom ergibt sich aus der Maschenregel:
Für Vollausschlag bei 10 V:
Bei einem bekannten Strom von 10 mA zeigte das Modul den Rohwert 1355. Daraus folgt der Maßstab:
Rechnet man rückwärts auf zwölf Bit, also 4095 Schritte, ergibt sich ein Messbereich von
Ein Bereich bis 30 mA ist bei solchen Modulen üblich, damit Übersteuerung noch erkennbar bleibt.
Nun die Frage, die ein Student stellen sollte: Wie groß darf der Vorwiderstand sein?
| R_vor | Strom bei 10 V | Rohwert | ein Zählschritt | Anteil am Bereich |
|---|---|---|---|---|
| 10 kΩ | 0,99 mA | rund 134 | 75 mV | 3 % |
| 4,7 kΩ | 2,08 mA | rund 282 | 35 mV | 7 % |
| 1 kΩ | 9,1 mA | rund 1230 | 8,1 mV | 30 % |
| 510 Ω | 16,4 mA | rund 2220 | 4,5 mV | 54 % |
Mit 10 Kiloohm bekommen Sie 134 Stufen über den ganzen Bereich. Das ist grob, aber funktioniert. Mit 510 Ohm sind es 2220 Stufen, also siebzehnmal feiner.
Die Grenze setzt aber nicht der Wandler, sondern die Quelle. Ein 0-bis-10-V-Ausgang, der nur 1 mA treiben kann, bricht bei 510 Ohm ein. Die Spannung sinkt, und der Zusammenhang ist nicht mehr linear. Deshalb lautet die Vorschrift: mit großem Widerstand beginnen und schrittweise verkleinern, solange der Rohwert proportional mitgeht. Tut er das nicht mehr, ist die Quelle am Anschlag.
Vierzig Messungen am unbeschalteten Eingang ergaben:
| AI1 | AI2 | |
|---|---|---|
| Mittelwert | 0,2 | 0,2 |
| Spanne | 1 Zählschritt | 1 Zählschritt |
| Streuung (1σ) | 0,40 | 0,43 |
Das Modul selbst ist also ausgesprochen ruhig. Die zuvor beobachteten Schwankungen des Messwerts zwischen 1327 und 1390 kamen folglich nicht vom Eingang, sondern von der Stromquelle.
Das ist eine wichtige methodische Unterscheidung: Wer Rauschen misst, muss wissen, wessen Rauschen er misst. Die Messung am unbeschalteten Eingang trennt Gerät und Quelle.
Das Modul nimmt zwei Arten von Signalen an:
| Art | Was anzuschließen ist | Bewertung |
|---|---|---|
| Trockener Kontakt | Schalter oder Brücke zwischen DI und COM | sicher, keine Fremdspannung nötig |
| Beschalteter Kontakt | äußere Gleichspannung auf DI | nur mit belegter Angabe aus dem Handbuch |
Ein trockener Kontakt ist ein potentialfreier Schalter. Das Modul legt selbst eine Spannung an den Eingang und misst, ob der Kontakt sie gegen Masse zieht.
Zum Prüfen genügt ein Stück Draht zwischen DI0 und COM. Solange die Spannungsfestigkeit nicht aus dem Handbuch belegt ist, bleibt es dabei. Eine Vermutung über zulässige Spannungen kostet im Zweifel das Modul.
Der Prüfstand kann auf zwei Arten mit dem Modul sprechen. Beide sind vollständig umgesetzt, und beide liefern dieselben Telegramme.
Browser ──HTTP──> Python-Dienst ──RS485──> Modul
Ein Python-Programm hält die serielle Verbindung, misst zyklisch und bietet eine HTTP-Schnittstelle auf 127.0.0.1. Die Bedienseite holt sich von dort ihre Werte.
Vorteile: Der Dienst misst weiter, auch wenn kein Browser offen ist. Die HTTP-Schnittstelle kann jedes andere Programm benutzen, etwa eine Visualisierung oder eine Anlagensteuerung. Jeder Browser funktioniert.
Browser ──Web Serial──> Modul
Seit einigen Jahren können Chrome und Edge über die Web-Serial-Schnittstelle direkt auf serielle Anschlüsse zugreifen, nach ausdrücklicher Freigabe durch den Benutzer. Damit rechnet die Seite die Modbus-Telegramme selbst, einschließlich CRC-16, in JavaScript.
Vorteile: Eine einzige Datei, kein Dienst, nichts zu installieren. Zum Weitergeben ideal.
Grenzen: Nur Chrome und Edge. Ist der Tab geschlossen, misst niemand. Und kein anderes Programm kommt an die Daten.
Zwei unabhängige Umsetzungen desselben Protokolls, einmal in Python, einmal in JavaScript, sind mehr als Bequemlichkeit. Wenn beide dieselben Bytes senden und dieselben Werte anzeigen, ist das ein Kreuznachweis: Ein Fehler müsste in beiden Umsetzungen gleich auftreten, und das ist unwahrscheinlich.
Dieses Prinzip gilt weit über Modbus hinaus. Ein Ergebnis, das nur auf einem Weg entstanden ist, ist eine Behauptung.
Alle Programme liegen in C:\Modbus_MA01 und sind einzeln
ausführbar. Sie bauen aufeinander auf, und jedes beantwortet genau eine
Frage.
| Programm | Frage, die es beantwortet |
|---|---|
modbus_scan.py |
Welche Adresse, welche Baudrate? (mit zu kurzer Wartezeit — als Gegenbeispiel aufgehoben) |
modbus_scan2.py |
dasselbe mit Paritäten und ausreichender Wartezeit — findet das Modul |
modbus_lesen.py |
Was steht in allen vier Bereichen? |
modbus_roh.py |
Wie sehen die Telegramme roh aus? (deckte die Halteregister-Falle auf) |
relais_probe.py |
Lässt sich ein Relais schalten und zurücklesen? |
modbus_dienst.py |
Dauerbetrieb mit HTTP-Schnittstelle |
dashboard.html |
Bedienung und Anzeige |
Alles Weitere ist Beiwerk um diese eine Funktion herum:
def wechsel(ser, adresse, fc, *woerter):
kopf = bytes([adresse, fc]) + b"".join(w.to_bytes(2, "big") for w in woerter)
telegramm = kopf + crc16(kopf)
ser.reset_input_buffer() # alte Reste wegwerfen
ser.write(telegramm)
time.sleep(0.15) # dem Modul Zeit lassen — siehe Falle 1
antwort = ser.read(ser.in_waiting or 0)
if len(antwort) < 4:
raise IOError("keine Antwort")
if crc16(antwort[:-2]) != antwort[-2:]:
raise IOError("Prüfsumme falsch")
if antwort[1] & 0x80:
raise IOError("Ausnahme %d" % antwort[2])
return antwort
Drei Prüfungen in drei Zeilen, und jede fängt einen anderen Fehler:
Für den Weg direkt aus dem Browser wurde derselbe Kern ein zweites Mal geschrieben:
crc(d){
let c = 0xFFFF;
for(const b of d){
c ^= b;
for(let i = 0; i < 8; i++) c = (c & 1) ? (c >> 1) ^ 0xA001 : c >> 1;
}
return [c & 0xFF, c >> 8]; // niederwertiges Byte zuerst
}
Vergleichen Sie Zeile für Zeile mit der Python-Fassung. Dieselbe Rechnung, dieselben Konstanten. Wenn beide Umsetzungen dieselben Bytes erzeugen, ist das ein Kreuznachweis.
Ein Unterschied steckt im Lesen. Python wartet einfach und liest dann, was da ist. Die Web-Serial-Schnittstelle liefert die Bytes dagegen häppchenweise über eine Leseschleife, und das Programm muss selbst entscheiden, wann genug da ist:
async wechsel(tele, mindest){
this.puffer = new Uint8Array(0);
await this.writer.write(tele);
const ende = performance.now() + this.warte + 260;
while(performance.now() < ende){
if(this.puffer.length >= mindest) break;
await new Promise(r => setTimeout(r, 12));
}
...
}
Der Dienst lauscht nur auf 127.0.0.1, nichts verlässt den Rechner. Jede Anfrage liefert JSON.
| Weg | Verfahren | Wirkung |
|---|---|---|
/zustand |
GET | alle Messwerte |
/verlauf |
GET | die letzten Messpunkte für den Graphen |
/telegramme |
GET | die letzten Telegramme, roh |
/schalten |
POST | {"do":0..3,"wert":0 oder 1} |
/kalibrieren |
POST | {"ai":1 oder 2,"ma":10.0} |
/vorwiderstand |
POST | {"ai":1 oder 2,"ohm":510} |
Eine Antwort auf /zustand sieht so aus:
{
"verbunden": true,
"zeit": "16:39:32",
"do": [0, 0, 0, 0],
"di": [0, 0],
"ai_roh": [1355, 0],
"ai_ma": [10.0, null],
"ai_v": [null, null],
"adresse": 32, "port": "COM4", "baud": 9600,
"gesendet": 2016, "beantwortet": 2016, "gestoert": 0,
"umlauf_ms": 452
}
Warum das wichtig ist: Diese Schnittstelle ist der Anschlusspunkt für alles Weitere. Eine Visualisierung, eine Anlagensteuerung oder ein Prozessleitsystem spricht hier an, ohne etwas von Modbus wissen zu müssen. Der Dienst übersetzt.
Die Felder gesendet, beantwortet und
gestoert sind keine Spielerei. Ihr Verhältnis ist das Maß
für die Güte der Übertragung. Im Dauerbetrieb über zweitausend
Telegramme lag es bei 2016 zu 2016 zu 0 — keine einzige Störung.
Um 16:24 Uhr meldete der Dienst:
"fehler": "WriteFile failed (PermissionError(13, 'Zugriff verweigert', None, 5))"
Nach 2016 fehlerfreien Telegrammen. Gleichzeitig meldete der Auftraggeber einen Ton und zog den USB-Stecker.
Die Diagnose: Der Wandler hatte sich für einen Moment vom USB-Bus abgemeldet. Windows gibt dann den Anschluss frei, und das Handle, das das Programm noch hält, zeigt ins Leere. Der Anschluss selbst war unversehrt, die Abfrage der Schnittstellen zeigte COM4 weiterhin.
Die Abhilfe gehört zur Aufgabe, nicht zur Kosmetik. Ein Dienst, der in einer Anlage läuft, muss einen Abriss überstehen:
except Exception as e:
self.gestoert += 1
try: self.ser.close()
except Exception: pass
self.ser = None # Handle wegwerfen
raise IOError("Anschluss verloren: %s" % e)
Und in der Messschleife:
if self.modul.ser is None:
time.sleep(1.5)
if self.modul.erneuern(): # neu öffnen
continue
Der Dienst zählt die Wiederverbindungen mit und zeigt sie an. Eine stillschweigende Reparatur wäre schlechter als gar keine: Wer nicht sieht, wie oft die Verbindung abreißt, hält eine wacklige Anlage für gesund.
Für die Praxis folgt daraus: In der späteren Anlage gehört eine galvanische Trennung zwischen Bus und Rechner, oder wenigstens ein geschirmtes Kabel mit beidseitig aufgelegtem Schirm. Der Abriss trat auf, als an den Analogeingängen hantiert wurde.
Am Tag nach der Inbetriebnahme meldete der Auftraggeber: „die verbindung scheint öfters abzubrechen.” Die Fehlersuche dazu ist lehrreicher als manches Kapitel über die Norm.
Der naheliegende Verdacht bei einem USB-Seriell-Wandler ist das Energiesparen: Windows darf USB-Geräte abschalten, und die Abfrage bestätigte, dass es für alle Anschlüsse dieses Rechners erlaubt ist.
Das Windows-Ereignisprotokoll widerlegte den Verdacht aber eindeutig:
=== An- und Abmeldungen von Geräten in den letzten 6 Stunden ===
keine Einträge
Der Wandler hatte sich kein einziges Mal abgemeldet. Damit war die ganze USB-Schiene als Ursache ausgeschlossen, und zwar durch eine Messung, nicht durch eine Überlegung.
Die Bedienseite maß in einem festen Takt von 900 Millisekunden. Eine Messung besteht aber aus drei Telegrammen — Relais, Eingänge, Analogwerte —, und jedes wartet bis zu 420 Millisekunden auf Antwort, falls keine kommt.
Dauerte eine Messung länger als der Takt, startete die nächste, während die vorige noch auf Antwort wartete. Dann lagen zwei Telegramme gleichzeitig auf der Zweidrahtleitung.
Und hier schlägt die Physik von RS485 zu. Auf einer Zweidrahtleitung gibt es nur ein Adernpaar für beide Richtungen. Senden zwei Treiber gleichzeitig, treiben sie dieselben Adern in verschiedene Richtungen. Der Empfänger sieht eine Spannung, die zu keinem der beiden Telegramme gehört. Beide gehen verloren.
Schlimmer noch: Der Fehler pflanzt sich fort. Die verlorene Antwort führt zu einem weiteren Timeout, der nächste Umlauf verschiebt sich, und die Störungen häufen sich.
Jetzt versteht man die Regel aus Abschnitt 2.2 nicht mehr als Formsache: Ein Leiter fragt, ein Teilnehmer antwortet, und solange eine Antwort aussteht, sendet niemand. Das ist keine Höflichkeit, sondern die einzige Möglichkeit, eine gemeinsame Leitung ohne Kollision zu benutzen.
Dieselbe Regel steckt auch hinter der Telegrammpause von dreieinhalb Zeichenzeiten und dahinter, dass ein Teilnehmer nie von selbst sendet.
Drei Änderungen, alle auf dasselbe gerichtet:
Ein Taktgeber ist kein Ablaufplan. Wer eine Messung in festem Takt anstößt, ohne zu prüfen, ob die vorige fertig ist, baut sich diesen Fehler ein. Das gilt für jede Bussteuerung, nicht nur für Modbus.
Die Fehlersuche gehört an den Anfang der Kette, nicht ans Ende. Hier hat ein Blick ins Ereignisprotokoll die Hardware in einer Minute entlastet. Ohne diesen Blick hätte man Stunden mit Treibern und Energieeinstellungen verbracht.
Und: Zwei Programme dürfen nie gleichzeitig an denselben Anschluss. Dasselbe Problem in größerem Maßstab trat in diesem Versuch schon einmal auf, als der Dienst im Hintergrund lief und der Browser denselben Anschluss öffnen wollte. Am Wandler blinkte es ununterbrochen — das sichere Zeichen, dass jemand anderes bereits sendet.
| Uhrzeit | Was geschah |
|---|---|
| 15:58 | Anschlüsse abgefragt, COM4 als FTDI erkannt |
| 15:58 | erster Scan über 247 Adressen und sechs Baudraten — keine Antwort |
| 15:59 | Scan mit längerer Wartezeit und Paritäten — Adresse 32 gefunden |
| 16:01 | alle vier Datenbereiche ausgelesen, Falle der Halteregister entdeckt |
| 16:03 | erstes Relais geschaltet und dreifach belegt |
| 16:17 | Dienst und Bedienseite auf den Rechner gelegt |
| 16:18 | alle vier Relais über die HTTP-Schnittstelle geprüft |
| 16:21 | Analogeingänge mit 10 mA vermessen, Maßstab bestimmt |
| 16:24 | Abriss des USB-Wandlers, Wiederverbindung eingebaut |
| 16:34 | Rauschen gemessen: 0,4 Zählschritte |
| 16:39 | Bedienseite umgestaltet, Anschlusskarte ergänzt |
| 16:47 | zweiter Weg über Web Serial eingebaut |
| 16:53 | einzelne Datei ohne Dienst erfolgreich geprüft |
Fünfundfünfzig Minuten von der ersten Abfrage bis zum geprüften Prüfstand mit zwei Zugriffswegen.
Dieses Manuskript entstand gemeinsam mit einer KI, die Zugriff auf den Laborrechner hatte. Sie konnte Programme schreiben, auf den Rechner übertragen, ausführen und die Antworten der Hardware lesen. Was sie nicht konnte: ein Kabel anschließen, eine LED sehen, einen Knall hören.
Die Programme zur Inbetriebnahme entstanden in Minuten. Der Scan über alle Adressen, die Zerlegung der Telegramme, die Umrechnung der Rohwerte, der Dienst mit HTTP-Schnittstelle, die Bedienseite mit Zeigerinstrumenten und Graph, schließlich die zweite Umsetzung in JavaScript — all das ist Fleißarbeit, bei der eine KI ihre Stärke ausspielt.
An vier Stellen wäre die Arbeit ohne den Menschen am Gerät stehengeblieben:
Ehrlichkeit gehört dazu. Drei Fehler, die in diesem Versuch gemacht wurden, gingen auf das Konto der KI:
Die Lehre für Sie: Eine KI mit Hardwarezugriff arbeitet schnell und macht trotzdem Fehler. Was sie nicht ersetzt, ist die Messung. Jede Zahl in diesem Manuskript stammt aus einem Telegramm, das wirklich über die Leitung ging. Keine stammt aus einem Datenblatt allein.
Aufgabe 1 — Telegramm von Hand. Schreiben Sie das Telegramm auf, mit dem Sie von Adresse 17 die Relais 0 bis 3 lesen. Rechnen Sie die Prüfsumme von Hand aus. Prüfen Sie Ihr Ergebnis im Prüfstand nach, indem Sie die Adresse umstellen und das Telegramm in der Tabelle vergleichen.
Aufgabe 2 — Auflösung. Ein Sensor liefert 0 bis 5 V und kann höchstens 2 mA treiben. Welchen Vorwiderstand wählen Sie, und wie viele Zählschritte bleiben Ihnen? Begründen Sie, warum ein kleinerer Widerstand hier nicht geht.
Aufgabe 3 — Leitungsbruch. Warum erkennt ein 4-bis-20-mA-Signal einen Kabelbruch, ein 0-bis-20-mA-Signal aber nicht? Was bedeutet das für die Auslegung einer Anlage?
Aufgabe 4 — Die Ausnahme. Fragen Sie im Prüfstand ein Register ab, das es nicht gibt. Was antwortet das Modul? Warum ist diese Antwort nützlicher als Schweigen?
Aufgabe 5 — Der Kreuznachweis. Lassen Sie denselben Messwert einmal über den Dienst und einmal über den Browser anzeigen. Vergleichen Sie die Telegramme. Was wäre zu folgern, wenn sie auseinanderliefen?
| Begriff | Bedeutung |
|---|---|
| RS485 | symmetrische Übertragung über zwei Adern, störfest, bis 1200 m |
| Modbus RTU | Protokoll mit rohen Bytes, Leiter fragt, Teilnehmer antwortet |
| Coil | einzelnes Bit zum Schreiben, historisch die Relaisspule |
| Discrete Input | einzelnes Bit zum Lesen |
| Input Register | 16-Bit-Wort zum Lesen, typisch Messwerte |
| Holding Register | 16-Bit-Wort zum Lesen und Schreiben, typisch Einstellungen |
| CRC-16 | Prüfsumme, Polynom 0xA001, Startwert 0xFFFF, niederwertiges Byte zuerst |
| Bürdewiderstand | Widerstand am Stromeingang, wandelt Strom in messbare Spannung |
| Trockener Kontakt | potentialfreier Schalter ohne eigene Spannung |
| Remote-I/O | Ein-/Ausgabemodul am Bus, sitzt beim Prozess |