Revolution Pi goes Modbus

Mit dem Update auf Raspbian Jessie wurde dem RevPi Core gleich auch noch Master und Slave Fähigkeit für die beliebten Netzwerkprotokolle Modbus RTU und Modbus TCP verpasst. Externe Gateways sind somit für diese zwei bekannten Netzwerkprotokolle nicht mehr nötig.

Auf der Hannover Messe letzten Monat konnten Besucher unseres Messestands schon live erleben, wie ein RevPi Core ohne zusätzliche Erweiterungsmodule, also nur mit den neuen Modbus Funktionen, mit verschiedenen Geräten kommunizierte. Hierzu hatten wir folgendes Szenario aufgebaut:

Ein RFID Lesegerät war über Modbus RTU an ein RevPi Core angebunden und legte in dessen Prozessabbild seinen Status und die zuletzt erkannte ID einer RFID-Karte ab. Messebesucher durften hierfür aus einem Bündel von Karten mit den Flaggen der EU Länder eine Karte heraussuchen und über den Kartenleser halten. Eine Python Software reagierte dann mit der Anzeige verschiedener Länderdaten und einer Landkarte auf einem 5 Zoll HDMI-Display und dem Abspielen der Nationalhymne über Kopfhörer. Auf einer großen, über Modbus TCP angebundenen Laufschriftanzeige wurde der Name des ausgesuchten Landes für alle sichtbar angezeigt. Wenn gerade mal keine Karte über den Kartenleser gehalten wurde, zeigte die Laufschrift unter anderem die aktuelle Temperatur am Stand an, welche durch ein Modbus TCP Thermometer seinen Messwert ins Prozessabbild sendete.

Modbus TCP arbeitet mit der am RevPi Core vorhandenen Ethernet-Schnittstelle (also über die RJ45 Buchse an der Frontseite) oder jeder anderen hinzugefügten Ethernetverbindung (z.B. USB WLAN Adapter), die das TCP/IP Protokoll zur Verfügung stellt.

Modbus RTU benötigt ein TTY-Device unter Linux. Die vorhandene UART Schnittstelle des Compute Modules ist allerdings für die PiBridge reserviert und steht nicht zur Verfügung. Daher geht das dann nur über separate (Drittanbieter) USB-Seriell-Wandler.

Der Datenaustausch wird dabei immer über das zentrales Prozessabbild des RevPi Cores abgewickelt. Dort werden ankommende Daten hineingeschrieben und abgehende Daten ausgelesen. Das Modbus Protokoll wird von „virtuellen Adaptern“ komplett eigenständig abgewickelt, so dass Du mit Deinen Steuerungsprogrammen oder anderen Applikationen einfach nur die Daten ins Prozessabbild schreibst oder von dort abholst. Das geschieht auf exakt dieselbe Weise, wie Du es mit Daten von einem unserer digitalen I/O-Module (z.B. RevPi DIO) machen würdest.

In unserem browserbasierten Konfigurationsprogramm PiCtory brauchst Du also einfach nur im Bereich der virtuellen Adapter nach dem passenden Modbus-Adapter (Master oder Slave, TCP oder RTU) suchen und diesen dann auf die Arbeitsfläche ziehen. Dann folgt die Konfiguration von dem Adapter, Abspeichern, Neustart der PiBridge und schon läuft der Modbus Datenaustausch unbemerkt im Hintergrund. Dabei kannst Du auch mehrere virtuelle Modbus Adapter verwenden, wenn Dir die 32 Register eines Adapters zum Beispiel nicht ausreichen oder Du bei TCP mehrere Slave-IPs ansprechen möchtest (der Adapter ermöglicht immer nur eine einzelne IP zu konfigurieren).

Was kannst Du nun im Einzelnen konfigurieren? Fangen wir mal mit dem Modbus RTU Master Modul an:

So ein Modul stellt 32 16-Bit-Worte plus 32 1-Bit-Werte im Prozessabbild für Eingangswerte und 32 16-Bit-Worte plus 32 1-Bit-Werte für Ausgangswerte bereit. Wie immer kannst Du diesen Adressen einen symbolischen Namen zuweisen. Außerdem konfigurierst Du pro Adapter eine TTY Schnittstelle (Devicename unter Linux, Bitrate, Parität, etc.). Ein Modbus Master soll ja zyklisch Daten von Slaves abholen oder dorthin bringen. Diese Aufgaben werden in einem eigenen Bereich konfiguriert, den wir gleich näher beschreiben werden. Im Prozessabbild stehen zusätzlich bei einem Master Modul noch Statusbytes, die für jede dieser Aufgaben den möglichen Modbus-Fehlercode anzeigen. Über 32 Boolesche Ausgangswerte können diese Statusbytes zurückgesetzt werden.
Jetzt aber zu der Konfiguration der „Aufgaben“. Um maximal 32 solcher Aufgaben für einen Master zu definieren, gelangst Du über rechten Mausklick und „erweiterte Daten“ auf ein neues Fenster, in dem eine leere Liste erscheint. Diese Liste kann nun durch bis zu 32 Zeilen mit Aufgaben ergänzt werden. Für jede Aufgabe werden die folgenden Felder benötigt:
Modbus Slave Adresse, Modbus Function Code („read coil“ etc.), Modbus Registeradresse, Anzahl der Register, Zeitintervall der Abfrage in Millisekunden. Hier legst Du also fest, alle wieviel ms der Master eine Anfrage an einen bestimmten Slave schickt, der ihm dann den Inhalt der N Register, beginnend ab dem angegebenen Register, zurücksendet. Oder (je nach function code) Du definierst einen Schreibvorgang als Aufgabe. Die Register-Functioncode arbeiten in Modbus mit 16 Bit breiten Registern und deshalb muss dann für jede Aufgabe mit Register-Function aus einer Drop-Down-Liste ein zugehöriges 16-Bit Datenwort vom Prozessabbild ausgewählt werden. Für die Coil-Functioncodes, die mit 1 Bit arbeiten, kann nur aus den 1-Bit-Werten vom Prozessabbild ausgewählt werden. Folgende Functioncodes stehen für Aufgaben zur Verfügung:

READ COILS, READ DISCRETE INPUTS, READ HOLDING REGISTERS, READ INPUT REGISTERS, WRITE SINGLE COIL, WRITE SINGLE REGISTER, WRITE MULTIPLE COILS, WRITE_MULTIPLE_REGISTERS

Für Modbus TCP Master Module geht das alles ziemlich ähnlich. Allerdings wird dort pro virtuellem Modul eine Ziel IP vom Slave festgelegt. Bei den Aufgabendefinitionen entfällt die Slave-Adresse dann (es wird nur eine Unit-ID gemäß der Modbus Spezifikation benötigt).

Wenn Du virtuelle Slave Module einsetzen willst, ist alles noch viel einfacher. Slave Module stellen einfach nur 32 Eingangs- und 32 Ausgangsregister Form von Werten im Prozessabbild zur Verfügung. Wenn ein Master an den RevPi Core eine Anfrage sendet, antwortet dessen virtuelles Slave Modul nur, wenn die konfigurierte Slave Adresse übereinstimmt und sendet dann den Inhalt eines Wertes aus dem Prozessabbild, welcher der Modbus-Registeradresse entspricht. Bei TCP Slaves muss die IP Adresse einer Ethernet-Schnittstelle stimmen und der in der Konfiguration frei einstellbare Port für den Modbus-Dienst. Virtuelle Slave-Module stellen nur die Functions codes „read input registers“, „write single registers“, “write multiple registers” und „read holding registers“ bereit. Coil-Functions sind nicht implementiert.

Noch ein paar abschließende Worte zu den Limits: Während die maximale Anzahl der Aufgaben im Code vorgegeben ist und nur durch Verwendung mehrerer parallel arbeitender Master Module vergrößert werden kann, ist die Anzahl der Register, die ein Master oder Slave verwendet, nur durch die maximale Größe des Prozessabbildes (aktuell 4kb) beschränkt und kann von Dir durch Anpassung der RAP-Datei für das virtuelle Modul angepasst werden. Die Zykluszeiten sind theoretisch minimal 1 ms. Allerdings wird dieser Wert bei umfangreichen RTU Konfigurationen sicher nicht erreicht werden können, da dann alleine die Übertragungszeiten der einzelnen Modbus-Datenpakete nicht mehr in einen Zyklus passen. Daher ist auch die in der Realität erreichbare Zykluszeit schwer vorherzusagen, Sie hängt einfach von zu vielen Parametern ab.

Für wen die Verwendung externe Modbus Gateways immer noch Sinn macht

Generell ist die Verwendung von RevPi Gate Modulen am RevPi Core keine einfache Sache: Das Gateway Modul erledigt einen zyklischen Datenaustausch mit dem Feldbus (in diesem Fall dem Modbus) völlig eigenständig, ist nicht programmierbar und im Falle von Modbus auch nicht einmal konfigurierbar (außer der einstellbaren Slave Adresse gibt es bei Modbus Slaves auch nicht viel zu konfigurieren). Die Daten für diesen zyklischen Datenaustausch stehen in einem Speicherbereich des RevPi Gates. Über die PiBridge findet nun asynchron zum Feldbuszyklus ein weiterer zyklischer Datenaustausch statt, bei dem PiControl die Daten aus dem Prozessabbild mit denen im RevPi Gate Modul zyklisch austauscht. Die Zuordnung von Modbus-Registeradressen zu den Adressoffsets im Speicher des RevPi Gate Moduls sind fest, während die Zuordnung zu Offsets im Prozessabbild des RevPi Core von dessen Gesamtkonfiguration abhängt. Zugegeben, das ist verwirrend und ziemlich umständlich. Aber rufen wir uns in Erinnerung: Die RevPi Gate Module wurden nicht explizit für den RevPi entwickelt, sondern existierten schon vorher als „modulare Gateways“ zur Verwendung ohne RevPi Core und immer als Paar, um einen Feldbus mit einem anderen zu verbinden. Der Einsatz von RevPi Gate Modulen am RevPi Core macht für Modbus RTU Slave dann Sinn, wenn Du generell für Deine Anwendung die Verwendung von USB auf RS485 Konvertern ablehnst. Die Verwendung bei Modbus TCP macht dann Sinn, wenn Du generell zwei getrennte Ethernet Schnittstellen für Modbus und Internet brauchst und die Verwendung von USB-zu-WLAN oder USB-zu-LAN Konvertern ablehnst.