Modbus-TCP/IP-Protokoll: Alles, was Sie wissen müssen, um Ihre Steuerungen mit der Cloud zu verbinden
Modbus TCP ist das in der französischen Industrie am weitesten verbreitete Protokoll zur Datenerfassung aus SPSen. Es kommt in Dutzenden Millionen Geräten zum Einsatz, die seit über 40 Jahren installiert sind. Wenn Sie Fernzugriff in Ihre Projekte integrieren, werden Sie auf Modbus TCP stoßen – daher lohnt es sich, das Protokoll gründlich zu verstehen.
Dieser Leitfaden behandelt die wichtigsten Aspekte für den Praktiker: Geschichte, Byte-für-Byte-Struktur des Frames, Funktionscodes, Vergleich mit konkurrierenden Protokollen, Leistungsoptimierung, Sicherheit sowie ein vollständiges und funktionsfähiges Python-Code-Beispiel.
1. Von Modbus RTU zu Modbus TCP: 45 Jahre Entwicklung
Die Entstehung von Modbus im Jahr 1979
Modbus wurde 1979 von Modicon (heute Teil von Schneider Electric) entwickelt, um die Kommunikation zwischen den ersten speicherprogrammierbaren Steuerungen vom Typ Modicon 084 zu ermöglichen. Es handelte sich um ein serielles (RS-232, später RS-485) Master-Slave-Protokoll, das für einen einzigen Zweck entwickelt wurde: das Lesen und Schreiben von numerischen Werten auf Feldgeräten.
Einfachheit war das grundlegende Konstruktionsprinzip:
- Keine Netzwerkadressierung – lediglich eine Slave-ID von 1 bis 247 auf dem Bus
- Keine Authentifizierung – jeder Master kann jeden Slave abfragen
- Keine automatische Erkennung – die Liste der Slaves wird manuell konfiguriert
- Keine Sicherheitsmechanismen – das Protokoll setzt eine physisch gesicherte Umgebung voraus
Modbus RTU (Remote Terminal Unit): Kompakte Binärversion für RS-485. Die Daten werden binär übertragen, mit einem 16-Bit-CRC zur Fehlererkennung. Nach wie vor weit verbreitet bei Feldgeräten (Energiezähler, Drucksensoren, Frequenzumrichter).
Modbus ASCII: ASCII-lesbare Version für RS-232-Verbindungen. Weniger effizient (2 Bytes pro Datenbyte), in neuen Anlagen veraltet.
Modbus TCP: Ethernet ohne Protokollrevolution
Um 1996–1999, als sich Ethernet in Fabriken zunehmend durchsetzte, wurde das Modbus-Protokoll in TCP/IP-Frames gekapselt. Die Überarbeitung erfolgte äußerst präzise:
- Gleiches Datenmodell (Coils, diskrete Eingänge, Eingangsregister, Halteregister)
- Gleiche Funktionscodes
- Gleiche Registeradressierung
- Wegfall des CRC (TCP gewährleistet die Integrität)
- Hinzufügung eines 7-Byte-MBAP-Headers für das Routing und die Korrelation von Anfragen
- Standard-TCP-Port: 502
Der Vorteil: Alle vorhandenen Geräte, die Modbus RTU unterstützten, konnten mit minimalen Änderungen auf Modbus TCP umgestellt werden. Der Nachteil: Die ursprünglichen Sicherheitslücken blieben bestehen.
2. Aufbau eines Modbus-TCP-Frames – Byte-für-Byte-Analyse
Überblick über das Raster
┌─────────────────────────────────────────────────────────────────────┐
│ Trame Modbus TCP │
├──────────────────────────────────────────┬──────────────────────────┤
│ MBAP Header (7 octets) │ PDU │
├──────────┬──────────┬──────────┬─────────┼────────────┬─────────────┤
│ Trans.ID │ Proto.ID │ Length │ Unit ID │ Func.Code │ Data │
│ 2 bytes │ 2 bytes │ 2 bytes │ 1 byte │ 1 byte │ n bytes │
└──────────┴──────────┴──────────┴─────────┴────────────┴─────────────┘
Analyse des MBAP-Headers
Transaktionskennung (2 Bytes): Eine vom Kunden frei gewählte Nummer, die in der Antwort unverändert zurückgegeben wird. Ermöglicht die Zuordnung der Antworten zu den Anfragen bei persistenten Verbindungen mit mehreren laufenden Anfragen. In der Praxis verwenden die meisten Clients einen einfachen Zähler (00 01, 00 02, 00 03...) oder eine feste Kennung (00 00), wenn sie im sequenziellen Anfrage-Antwort-Modus arbeiten.
Protokollkennung (2 Bytes):
Für Modbus immer 00 00. Diese Konstante wurde vorgesehen, um eine eventuelle Erweiterung auf andere Protokolle über denselben Port zu ermöglichen, wurde jedoch nie verwendet.
Länge (2 Byte):
Anzahl der folgenden Bytes, im Big-Endian-Format. Beinhaltet die Unit-ID und die PDU, jedoch nicht die ersten 4 Bytes des MBAP-Headers. Bei einer FC=03-Anfrage mit 10 Registern: 6 Bytes (1 Unit-ID + 1 FC + 2 Adressen + 2 Count) → 00 06.
Unit Identifier (1 Byte): Kennung des Modbus-Slaves. Bei direkt angeschlossenen Steuerungen (S7-1200 mit MB_SERVER, M340 mit integriertem Modbus-Server) beträgt der Wert in der Regel 1 oder 255. Bei Modbus-RTU→TCP-Gateways entspricht diese Kennung der Adresse des RTU-Slaves am RS-485-Bus.
Analyse einer vollständigen FC=03-Abfrage
Auslesen von 10 Holding-Registern ab der Adresse 100 (z. B.: %MW100 beim Schneider M340):
Requête client (hex) : 00 01 00 00 00 06 FF 03 00 64 00 0A
Décodage byte par byte :
00 01 → Transaction ID = 1
00 00 → Protocol ID = 0 (Modbus standard)
00 06 → Length = 6 (Unit ID + FC + 2 adresse + 2 count)
FF → Unit ID = 255 (0xFF = CPU locale M340)
03 → Function Code = Read Holding Registers
00 64 → Starting Address = 100 (0x0064 en big-endian)
00 0A → Quantity = 10 registres (0x000A)
Réponse automate (hex) : 00 01 00 00 00 17 FF 03 14 [20 octets]
Décodage :
00 01 → Transaction ID = 1 (même que la requête — corrélation)
00 00 → Protocol ID = 0
00 17 → Length = 23 (1 UID + 1 FC + 1 ByteCount + 20 données)
FF → Unit ID = 255
03 → Function Code = 3 (confirme que c'est une réponse normale)
14 → Byte Count = 20 (10 registres × 2 octets = 0x14 hex)
[suivi de 20 octets de données — 10 valeurs uint16 big-endian]
Ausnahmecodes (Fehlermeldungen)
Wenn der Automat eine Anfrage nicht bearbeiten kann, gibt er einen Ausnahmecode zurück:
Réponse exception (hex) : 00 01 00 00 00 03 FF 83 02
83 → FC + 0x80 = 3 + 128 = 131 → indique une réponse d'exception sur FC=3
02 → Exception code : Illegal Data Address
| Code | Bezeichnung | Bedeutung | Häufige Ursache |
|---|---|---|---|
| 01 | Illegal Function | Nicht unterstützte FC | Die SPS unterstützt diese FC nicht |
| 02 | Illegal Data Address | Adresse außerhalb des Bereichs | Register > SPS-Grenzwert |
| 03 | Ungültiger Datenwert | Ungültiger Datenwert | Zählwert > 125 (FC=03) |
| 04 | Server Device Failure | Interner Fehler | Modbus-Server nicht initialisiert |
| 05 | Acknowledge | Langwierige Verarbeitung läuft | In der Praxis selten |
| 06 | Server Device Busy | Server belegt | Zu viele gleichzeitige Verbindungen |
| 0A | Gateway-Pfad nicht verfügbar | Gateway-Pfad nicht verfügbar | RTU-Slave nicht erreichbar |
| 0B | Gateway-Zielgerät ausgefallen | Slave reagiert nicht | RTU-Slave ausgeschaltet oder defekt |
3. Die Funktionscodes im Detail
FC=01 und FC=02 – Bits auslesen
FC=01 : Read Coils → bits de sortie (écriture autorisée)
FC=02 : Read Discrete Inputs → bits d'entrée (lecture seule)
Requête : FC AddrH AddrL QuantH QuantL
01 00 00 00 00 00 10 (lecture 16 coils depuis @0)
Réponse : FC ByteCount Coil_Data
01 02 [2 bytes = 16 bits d'état]
Note : les coils sont packés en bits, LSB first.
Byte1 bit0 = Coil@0, Byte1 bit1 = Coil@1, etc.
FC=03 — Lesen der Halteregister (am häufigsten verwendet)
Lesen und Schreiben von 16-Bit-Registern. Begrenzung: maximal 125 Register pro Anfrage.
FC=04 — Eingangsregister lesen
Entspricht FC=03, gilt jedoch für die „Eingangsregister“ (nur lesbar). Bei Schneider M340 entspricht dies den %IW. Bei den meisten Steuerungen wird dies selten verwendet, da die analogen Messwerte in die %MW (Holding-Register) kopiert werden.
FC=06 und FC=16 – Schreiben von Registern
FC=06 : Write Single Register
Requête : FC AddrH AddrL ValueH ValueL
06 00 64 00 64 01 F4 (écriture 500 à l'adresse 100)
FC=16 : Write Multiple Registers (jusqu'à 123 registres par requête)
Requête : FC AddrH AddrL CountH CountL ByteCount Values...
10 00 64 00 05 01 2C [données]
Achtung beim Schreiben (FC=06, FC=16): Schreiben Sie nur dann in Register, wenn Sie sich hinsichtlich der Adressierung und der Auswirkungen auf das SPS-Programm sicher sind. Ein Schreibvorgang in ein Sollwertregister verändert sofort das Verhalten des Prozesses. Testen Sie vor der Bereitstellung immer auf einer Entwicklungs-SPS oder einer SPS außerhalb der Produktion.
4. Modbus TCP vs. OPC-UA vs. MQTT: Welches Protokoll eignet sich für Ihre Architektur?
Diese drei Protokolle kommen in modernen IIoT-Architekturen nebeneinander zum Einsatz. Sie bedienen unterschiedliche Schichten und stehen nicht in direktem Wettbewerb zueinander.
| Kriterium | Modbus TCP | OPC-UA | MQTT |
|---|---|---|---|
| Entstehungsjahr | 1979 (RTU), ~1996 (TCP) | 2008 | 1999 |
| Modell | Client/Server (Polling) | Client/Server + Pub/Sub | Pub/Sub (Broker) |
| Ebene | Feldkommunikation | Systeminteroperabilität | IoT-/Cloud-Transport |
| Native Sicherheit | Keine | TLS + Zertifikatsauthentifizierung | TLS + Authentifizierung |
| CPU-Auslastung der SPS | Sehr gering | Hoch | Gering bis mittel |
| Ältere SPSen | Universell (40 Jahre) | Nur moderne SPSen | Über Gateway |
| Automatische Erkennung | Nein | Ja (OPC-Namespace) | Nein |
| Strukturierte Daten | Nein (flache Register) | Ja (Typen, Strukturen, Arrays) | Ja (JSON/CBOR) |
| Latenz | Gering (Polling) | Sehr gering (Pub/Sub) | Sehr gering |
Wie soll man sich entscheiden?
Verwenden Sie Modbus TCP, wenn:
- Die SPS Modbus TCP unterstützt (Siemens S7-1200, Schneider M340/M221/M241, Wago, Allen-Bradley...)
- Sie einfache Messwerte erfassen müssen (16-Bit-Register)
- Die einfache Konfiguration Vorrang vor der Vielseitigkeit des Datenmodells hat
Verwenden Sie OPC-UA, wenn:
- Die SPS OPC-UA-Server nativ unterstützt (S7-1500, B&R, Beckhoff, aktuelle CODESYS 3.x-Versionen)
- Sie komplexe Variablen (Strukturen, Arrays, benutzerdefinierte Typen) überwachen müssen
- Die Interoperabilität mit anderen SCADA- oder MES-Systemen eine Voraussetzung ist
Verwenden Sie MQTT für den Cloud-Transport, wenn:
- Sie über ein Gateway (wie Eziwan) verfügen, das Daten über Modbus/OPC-UA erfasst und über MQTT veröffentlicht
- Sie eine skalierbare Pub/Sub-Architektur für Tausende von Messpunkten benötigen
Die Zielarchitektur für das IIoT in der Cloud:
[Automate] ──Modbus TCP / OPC-UA──→ [Gateway] ──MQTT over TLS──→ [Cloud]
Das Gateway wandelt Daten um und überträgt sie. Es bildet die Brücke zwischen der OT-Welt (Modbus/OPC-UA) und der Cloud-Welt (MQTT/REST).
5. Modbus-TCP-Sicherheit: Das Problem und die Lösungen
Das völlige Fehlen einer Authentifizierung
Modbus TCP verfügt über keine nativen Sicherheitsmechanismen:
- Keine Authentifizierung: Jeder im Netzwerk kann Daten lesen und schreiben
- Keine Verschlüsselung: Die Daten werden im Klartext übertragen (mit Wireshark lesbar)
- Keine Autorisierung: Es gibt keine Lese-/Schreibrechte für einzelne Benutzer
Praktische Konsequenz: Wenn Ihre SPS über das Internet erreichbar ist (Port 502 offen), ist sie völlig ungeschützt. Wenn sich jemand in Ihr OT-Netzwerk einloggt (physisch oder über eine Sicherheitslücke), kann er alle Register lesen und ändern.
Mögliche Antworten
Netzwerksegmentierung (primäre Maßnahme): Den Modbus-TCP-Datenverkehr auf ein isoliertes OT-Netzwerk beschränken. Das Eziwan-Gateway befindet sich in diesem OT-Netzwerk; die Kommunikation mit der Cloud erfolgt über einen VPN-Tunnel und nicht über einen offen zugänglichen Port 502.
IP-Filterung auf der SPS (sekundäre Maßnahme): Bestimmte neuere SPS-Modelle (Schneider M340, Firmware ≥ 2.60; Siemens S7-1200, Firmware V4.x mit FIREWALL-Funktionen) unterstützen eine IP-Filterung: Nur die IP-Adresse des Eziwan-Gateways ist berechtigt, eine Verbindung zum Port 502 herzustellen.
Modbus Security (erweiterte Maßnahme): Die Modbus Organization hat 2018 eine Erweiterung namens „Modbus Security“ (TLS-Transport für Modbus TCP) auf Port 802 veröffentlicht. Diese Erweiterung wird von den auf dem Markt erhältlichen Steuerungen noch nicht flächendeckend unterstützt, ist jedoch auf einigen neueren Geräten verfügbar.
6. Optimierung der Erfassungsleistung
Zusammenfassung von Anfragen (Batching)
Die goldene Regel: Lesevorgänge in zusammenhängende Blöcke zusammenfassen. Das Auslesen von 100 zusammenhängenden Registern in einer einzigen Abfrage ist wesentlich effizienter als 100 Abfragen mit jeweils einem Register:
Configuration inefficace (100 requêtes) :
Lire %MW0 → 1 requête (2 octets de données)
Lire %MW50 → 1 requête
Lire %MW99 → 1 requête
... 97 requêtes supplémentaires ...
Latence totale : 100 × (aller-retour réseau) ≈ 100 × 5ms = 500ms
Configuration optimisée (1 requête) :
Lire %MW0 à %MW99 → 1 requête (200 octets de données)
Latence totale : 1 × 5ms = 5ms
Das Eziwan-Gateway gruppiert die konfigurierten Variablen automatisch in zusammenhängende Bereiche. Um diese Gruppierung zu optimieren, ordnen Sie Ihre Überwachungsvariablen in benachbarten Speicherbereichen an.
Auswirkungen auf den SPS-Zyklus
Jede empfangene Modbus-TCP-Anfrage wird von der SPS am Ende des Programmzyklus verarbeitet. Bei einer M340 mit einem Zyklus von 10 ms können 10 gleichzeitige Modbus-Anfragen den Zyklus um 1 bis 3 ms verlängern.
Empfehlung: Bei Anwendungen mit Echtzeitanforderungen sollte pro SPS-Zyklus nicht mehr als eine Modbus-Anfrage gesendet werden. Verringern Sie die Abfragehäufigkeit, wenn sich der Zyklus verlängert.
7. Vollständiges Python-Beispiel mit pymodbus
"""
Collecte Modbus TCP industrielle avec gestion d'erreurs robuste
Compatible Schneider M340, Siemens S7-1200, Wago, Allen-Bradley...
Testé avec pymodbus >= 3.0
Installation :
pip install pymodbus loguru
"""
from pymodbus.client import ModbusTcpClient
from pymodbus.exceptions import ModbusException, ConnectionException
from loguru import logger
import struct
import time
from dataclasses import dataclass
from typing import Optional
# ─── Configuration ────────────────────────────────────────────────────────────
HOST = "192.168.1.20" # IP automate Schneider M340
PORT = 502 # Port Modbus TCP
UNIT_ID = 255 # 255 pour CPU locale M340, 1 pour S7-1200
TIMEOUT = 3 # Timeout en secondes
RETRIES = 3 # Nombre de tentatives avant abandon
# ─── Structure de données ─────────────────────────────────────────────────────
@dataclass
class VariablesProcess:
temperature_c: float = 0.0
debit_lmin: int = 0
pression_bar: float = 0.0
pompe_1_marche: bool = False
pompe_2_marche: bool = False
code_defaut: int = 0
compteur_production: int = 0
timestamp: float = 0.0
# ─── Client Modbus avec reconnexion automatique ───────────────────────────────
class ModbusCollecteur:
"""Collecteur Modbus TCP avec gestion de reconnexion et retry."""
def __init__(self, host: str, port: int = 502, unit_id: int = 1):
self.host = host
self.port = port
self.unit_id = unit_id
self.client: Optional[ModbusTcpClient] = None
self._connexions_ok = 0
self._connexions_echec = 0
def connecter(self) -> bool:
"""Établit la connexion TCP vers l'automate."""
try:
self.client = ModbusTcpClient(
self.host,
port=self.port,
timeout=TIMEOUT,
retries=1, # Retries gérés par notre code
reconnect_delay=0, # Pas de reconnexion automatique
)
if self.client.connect():
self._connexions_ok += 1
logger.info(f"Connecté à {self.host}:{self.port}")
return True
else:
self._connexions_echec += 1
logger.warning(f"Connexion refusée par {self.host}:{self.port}")
return False
except Exception as e:
logger.error(f"Erreur connexion : {e}")
return False
def deconnecter(self):
if self.client:
self.client.close()
self.client = None
def lire_holding_registers(
self, adresse: int, count: int
) -> Optional[list[int]]:
"""Lit des registres avec retry automatique."""
for tentative in range(1, RETRIES + 1):
try:
if not self.client or not self.client.is_socket_open():
if not self.connecter():
time.sleep(1)
continue
result = self.client.read_holding_registers(
address=adresse, count=count, slave=self.unit_id
)
if result.isError():
exception_code = getattr(result, 'exception_code', '?')
logger.warning(
f"Erreur Modbus addr={adresse} count={count} "
f"exception_code={exception_code}"
)
# Exception 04 (server busy) → attendre avant retry
if exception_code == 6:
time.sleep(0.5)
self.deconnecter()
continue
return result.registers
except ConnectionException:
logger.warning(f"Connexion perdue (tentative {tentative}/{RETRIES})")
self.deconnecter()
time.sleep(0.5)
except Exception as e:
logger.error(f"Erreur inattendue : {e}")
self.deconnecter()
time.sleep(1)
logger.error(f"Échec lecture après {RETRIES} tentatives — addr={adresse}")
return None
@staticmethod
def registres_to_float32_abcd(reg_high: int, reg_low: int) -> float:
"""Décode 2 registres 16-bit en float32 IEEE754 big-endian (ABCD)."""
raw = struct.pack(">HH", reg_high, reg_low)
return struct.unpack(">f", raw)[0]
@staticmethod
def registres_to_int32(reg_high: int, reg_low: int) -> int:
"""Décode 2 registres en entier 32-bit signé big-endian."""
raw = struct.pack(">HH", reg_high, reg_low)
return struct.unpack(">i", raw)[0]
# ─── Lecture des variables process ───────────────────────────────────────────
def lire_variables(collecteur: ModbusCollecteur) -> Optional[VariablesProcess]:
"""
Lecture optimisée : 1 seule requête Modbus pour toutes les variables.
Plan mémoire (M340 EcoStruxure) :
%MW100 : Temperature (int16, ×0.1 → °C)
%MW101 : Débit (int16, L/min)
%MW102-103 : Pression (float32 ABCD, bar)
%MW104 : États machine (bits 0-7)
%MW105 : Code défaut actif
%MW106-107 : Compteur production (int32)
"""
# 1 requête pour %MW100 à %MW107 (8 registres)
registres = collecteur.lire_holding_registers(adresse=100, count=8)
if registres is None:
return None
vars_process = VariablesProcess(
temperature_c = registres[0] * 0.1, # %MW100
debit_lmin = registres[1], # %MW101
pression_bar = ModbusCollecteur.registres_to_float32_abcd( # %MW102+103
registres[2], registres[3]),
pompe_1_marche = bool(registres[4] & 0x0001), # %MW104 bit0
pompe_2_marche = bool(registres[4] & 0x0002), # %MW104 bit1
code_defaut = registres[5], # %MW105
compteur_production = ModbusCollecteur.registres_to_int32( # %MW106+107
registres[6], registres[7]),
timestamp = time.time(),
)
return vars_process
# ─── Boucle principale ────────────────────────────────────────────────────────
def main():
collecteur = ModbusCollecteur(HOST, PORT, UNIT_ID)
INTERVALLE = 5 # secondes entre chaque collecte
logger.info(f"Démarrage collecte Modbus TCP — {HOST}:{PORT} — cycle {INTERVALLE}s")
while True:
try:
vars_process = lire_variables(collecteur)
if vars_process:
logger.info(
f"T={vars_process.temperature_c:.1f}°C "
f"Q={vars_process.debit_lmin}L/min "
f"P={vars_process.pression_bar:.2f}bar "
f"P1={'ON' if vars_process.pompe_1_marche else 'OFF'} "
f"Défaut={vars_process.code_defaut}"
)
# Ici : publier via MQTT, API REST, ou base time-series
# mqtt_client.publish("usine/ligne3/variables", vars_process)
else:
logger.warning("Collecte échouée — attente 10s avant retry")
time.sleep(10)
continue
time.sleep(INTERVALLE)
except KeyboardInterrupt:
logger.info("Arrêt demandé.")
collecteur.deconnecter()
break
if __name__ == "__main__":
main()
Dieser Code veranschaulicht die bewährten Vorgehensweisen für die Modbus-TCP-Datenerfassung in Python: Bündelung von Lesevorgängen, Ausnahmebehandlung, automatische Wiederverbindung und Dekodierung komplexer Datentypen. Im Produktivbetrieb übernimmt das Eziwan-Gateway all diese Funktionen nativ – ohne dass ein Python-Skript vor Ort erforderlich ist.
FAQ – Modbus-TCP/IP-Protokoll
Warum ist der Modbus-TCP-Port 502 und kein Standardport wie 80 oder 443?
Der Port 502 wurde Modbus von der IANA (Internet Assigned Numbers Authority) im Zuge der Standardisierung von Modbus TCP in den 1990er Jahren offiziell zugewiesen. Damals gab es keinen Grund, bereits vorhandene IT-Anwendungsports wiederzuverwenden. Da es sich um einen registrierten Port (< 1024) handelt, erfordert seine Nutzung als Server unter Linux Root-Rechte – was industrielle Firmware nativ unterstützt.
Wie viele Register können bei einer einzelnen FC=03-Abfrage gelesen werden?
Die Obergrenze liegt bei 125 Registern pro FC=03-Anfrage (Read Holding Registers), wie in der offiziellen Modbus-Spezifikation festgelegt. Das entspricht maximal 250 Byte Nutzdaten pro Anfrage. Für FC=16 (Write Multiple Registers) liegt die Obergrenze bei 123 Registern pro Anfrage. Das Eziwan-Gateway übernimmt automatisch die Aufteilung, wenn ein angeforderter Bereich diese Grenzen überschreitet.
Unterstützt Modbus TCP mehrere gleichzeitige Client-Verbindungen?
Ja, aber die Obergrenze wird von der Steuerung festgelegt. Die Schneider M340 unterstützt bis zu 16 gleichzeitige Verbindungen, die Siemens S7-1200 bis zu 8 (über MB_SERVER). Darüber hinaus gibt die SPS die Ausnahme 06 (Server Busy) zurück. In der Praxis erreichen ein Erfassungs-Gateway + ein Diagnosetool + ein lokales SCADA-System leicht 3 gleichzeitige Verbindungen – dies ist zu beachten.
Kann Modbus TCP verschlüsselt werden?
Der native Modbus-TCP-Standard (Port 502) ist nicht verschlüsselt. Eine Erweiterung namens „Modbus Security“ auf Port 802 mit TLS gibt es seit 2018, wird jedoch von aktuellen Steuerungen nur selten unterstützt. Die praktische Lösung besteht darin, Modbus TCP auf ein isoliertes OT-Netzwerk zu beschränken und die gesamte Kommunikation nach außen über einen verschlüsselten VPN-Tunnel (wie OpenVPN von Eziwan) zu leiten – die Verschlüsselung erfolgt auf der Transportschicht, nicht durch Modbus selbst.
Ist pymodbus die einzige Python-Bibliothek für Modbus TCP?
Nein. Die wichtigsten Alternativen sind minimalmodbus (einfacher für Modbus RTU), umodbus (schlank, geringer Speicherbedarf) und pyModbusTCP (rein TCP, ohne Abhängigkeiten). Für industrielle Projekte in Python bleibt pymodbus >= 3.0 die umfassendste Wahl mit Ausnahmebehandlung, Wiederverbindungsfunktion und Unterstützung beider Modi (RTU und TCP).
Wie lässt sich ein Modbus-TCP-Datenaustausch ohne Zugriff auf die SPS debuggen?
Verwenden Sie Modbus Slave (Windows) als lokalen SPS-Simulator oder diagslave (Befehlszeile, plattformübergreifend). Diese Tools simulieren einen Modbus-TCP-Server, der auf konfigurierbare Adressen reagiert. Ideal zum Testen einer Datenerfassungskonfiguration, ohne dabei eine SPS im Produktivbetrieb zu beeinträchtigen.
👉 Nächster Schritt
Ihre Steuerung unterstützt Modbus TCP, aber Sie sind sich nicht sicher, ob dies mit Ihrer Firmware-Version kompatibel ist?
Prüfen Sie die Kompatibilität Ihrer Steuerung →
Siehe auch: Modbus TCP mit einem Schneider M340 und die Siemens S7-Dokumentation für spezifische Konfigurationen.