Zum Hauptinhalt springen

ModBus smartCORE Modul

Beschreibung​

Das "modbus" Modul ließt primär die ModBus Register von ModBus Teilnehmern aus. Diese Teilnehmer können hierbei

  • über eine serielle Verbindung (ModBus/RTU)
  • über TCP (ModBus/TCP)

verbunden sein.

Verwendete Schnittstellen & Protokolle​

  • ModBus

JSON-Konfiguration​

Im folgenden Abschnitt soll die gesamte JSON-Konfiguration des Moduls beschrieben und die einzelnen Parameter erläutert werden.

Beispielkonfiguration​

Im Folgenden sei eine ModBus/TCP Beispielkonfiguration dargestellt:

{
"module": "ModBus",
"comment": "ModBus/TCP config",
"factory": "modbus",
"config": {
"version": 1,
"type": "modbus",
"enable": true,
"pollCycleInMilliseconds": 1000,
"transport": {
"type": "tcp",
"ipAddress": "192.168.0.1",
"ipPortNumber": 502,
"timeoutInMilliseconds": 200
},
"devices": [
{
"enable": true,
"deviceName": "Device Name",
"deviceAddress": 1,
"readChannels": [
{
"name": "Channel Name",
"address": 49152,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
}
]
}
]
}
}

Globale Modulparameter​

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
versionJAINT1ModBus Protokollversion
typeJASTRING"modbus"Serielle Schnittstelle für Kommunikation
enableJABOOLtrueSchalter für Produktion der Daten in smartCHANNELs
pollCycleInMillisecondsJAINT1 -Abfrageintervall [ms] der ModBus Zugriffe
transportJAJSON ObjektKonfiguration der ModBus Transportschicht (siehe unten)
devicesJAJSON Array von JSON ObjektenListe der ModBus Teilnehmer
pollCycleInNanosecondsNeinINT1 -100000000Abfrageintervall [ns]. Ist der Schlüssel gesetzt, hat er Vorrang vor pollCycleInMilliseconds. Fehlen beide, werden 100 ms verwendet
enableInternalDataReductionNeinBOOLtrue, falsefalseHängt an jeden erzeugten Kanal eine Datenreduktion (absTolerance 0.0, timeoutMs 60000): unveränderte Werte werden nicht geschrieben, spätestens nach 60 s aber wieder
autoGroupNeinBOOLtrue, falsetrueFasst benachbarte Register eines Geräts automatisch zu Registerblöcken zusammen, die in einer Transaktion gelesen werden (siehe Registerblöcke)
autoGroupAllowGapsNeinBOOLtrue, falsefalseErlaubt Lücken innerhalb eines Blocks: nicht benötigte Register werden mitgelesen, statt den Block zu trennen
maxRegisterGroupNeinINT1 - 125125Größte Registeranzahl eines Blocks. Größere Werte werden mit einer Warnung auf 125 begrenzt — mehr lässt ModBus in einer Transaktion nicht zu
useF23withoutOutputsNeinBOOLtrue, falsefalseVerwendet Funktionscode 23 (Read/Write Multiple Registers) auch dann, wenn nichts zu schreiben ist (ab smartCORE 2.12)
minimalChannelAlarmCountNeinINT1 -2Anzahl unmittelbar aufeinanderfolgender Fehlversuche, nach der ein Registerblock abgeschaltet wird (siehe Timeout und Abschaltung)
retryAfterBlockFailSNeinINT0 -0Wartezeit [s], nach der ein abgeschalteter Registerblock erneut versucht wird. 0 = kein erneuter Versuch, der Block bleibt für die Messung aus (ab smartCORE 2.12)
workloadAsChannelNeinBOOLtrue, falsefalseLegt einen Diagnosekanal an, der die Buslast führt
workloadChannelBuffersizeNeinINT1 -100Puffergröße des Buslastkanals in Elementen
workloadChannelNeinSTRING oder JSON ObjektName oder vollständige Kanaldefinition des Buslastkanals

ModBus/TCP spezifische Transportparameter ("transport")​

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
typeJASTRING"tcp"Auswahl ModBus/TCP
ipAddressJASTRINGGültige IP AdresseIP Adresse des ModBus Geräts
ipPortNumberJAINTGültige IP PortnummerIP Portnummer des ModBus Geräts (sollte, falls nicht anders spezifiziert, auf 502 eingestellt werden)
timeoutInMillisecondsJAINT1 -Timeout [ms] für TCP Verbindung (sollte, falls nicht anders spezifiziert, auf 200 eingestellt werden)

ModBus/RTU spezifische Transportparameter ("transport")​

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
typeJASTRING"rtu"Auswahl ModBus/RTU
baudRateJAINTGültige ModBus BaudrateBaudrate der seriellen Schnittstelle
dataBitsJAINT5 - 8Datenbits der seriellen Schnittstelle
parityJASTRING"no", "even", "odd"Parität der seriellen Schnittstelle
stopBitsJADOUBLE1.0, 1.5, 2.0Stoppbits der seriellen Schnittstelle
portNameJASTRINGGültiges Device FileGerätedatei der seriellen Schnittstelle
timeoutInMillisecondsJAINT1 -Antwort-Timeout [ms] der seriellen Verbindung. Er begrenzt, wie lange auf die Antwort eines Teilnehmers gewartet wird, und geht als modbus_set_response_timeout() an libmodbus
deviceTimeoutInMillisecondsNeinINT0 -0Zusätzlicher Timeout [ms] zwischen den Abfragen unterschiedlicher ModBus Teilnehmer
readDelayMsNeinINT0 -Überschreibt die Rahmenstille t3.5 [ms], die vor jeder Anfrage eingehalten wird. Ohne den Schlüssel wird sie aus der Baudrate berechnet (siehe Rahmenstille)

ModBus Geräteparameter ("devices")​

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
enableJABOOLtrueSchalter zur Aktivierung des ModBus Geräts
deviceNameJASTRINGName des ModBus Geräts
deviceAddressJAINT1 -Adresse des ModBus Geräts
readChannelsJAJSON Array von JSON Objektensiehe unten

Die Schlüssel autoGroup, autoGroupAllowGaps, maxRegisterGroup und useF23withoutOutputs dürfen zusätzlich pro Gerät angegeben werden und überschreiben dort den globalen Wert.

ModBus Kanalkonfiguration ("readChannels")​

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
nameJASTRINGName des smartCHANNELs
addressJAINTAdresse des ModBus Registers
registerTypeJASTRINGGültiger ModBus RegistertypTyp des ModBus Registers ("InputReg", "HoldingReg", "Coil", "Status", "0x17" (nur Lesezugriff))
registerFormatJASTRINGGültiges ModBus RegisterformatFormat des ModBus Registers ("I8","I16","I32","I64","UI8","UI16","UI32","UI64","REAL","BOOL")
byteOrderJASTRINGsiehe untenReihenfolge der Bytes des Werts, siehe Byteorder
bitOffsetJAUINTBitoffset des zu interpretierenden Werts
unitJASTRINGEinheit des smartCHANNELs
scaleJADOUBLESkalierung des smartCHANNELs
offsetJADOUBLEOffset des smartCHANNELs
enableNeinBOOLtrue, falsetrueEin Kanal mit false wird weder angelegt noch gelesen
pollingIntervalMultiplicatorNeinINT1 -1Der Registerblock dieses Kanals wird nur in jedem n-ten Abfragezyklus gelesen
registerGroupNeinINT0 -Ordnet den Kanal einem Registerblock von Hand zu. Kanäle mit derselben Nummer bilden einen Block und werden von der automatischen Gruppierung ausgenommen

ModBus Kanalkonfiguration ("readChannelGroups")​

Alternativ können mehrere Kanalkonfigurationen zu einem JSON Array zusammengefasst werden, so dass die dieser Gruppe zugrundeliegenden ModBus Register in einem einzigen Schritt ausgelesen werden können (falls der Register Typ identisch ist). Dieses so zusammengefasste readChannelGroup Array kann dann in dem JSON Array der "readChannelGroups" aufgelistet werden, z.B.

"readChannelGroups": [
[
{
"name": "Channel 1",
"address": 49152,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
},
{
"name": "Channel 2",
"address": 49158,
"registerType": "HoldingReg",
"registerFormat": "REAL",
"byteOrder": "ABCD",
"bitOffset": 0,
"unit": "",
"scale": 1.0,
"offset": 0.0
}
]
]

Es können alternativ "readChannels" bzw. "readChannelGroups" spezifiziert werden.

Registerblöcke​

Die Kanäle eines Geräts werden nicht einzeln gelesen. smartCORE fasst sie zu Registerblöcken zusammen: ein Block ist ein zusammenhängender Adressbereich eines Registertyps und wird in genau einer ModBus Transaktion gelesen. Jeder Kanal wird von genau einem Block versorgt.

Gruppiert wird nach Registertyp und Adresse. Die vier ModBus Adressräume (Coil, Discrete Input, Input Register, Holding Register) sind unabhängig voneinander — Coil 4 und Input Register 4 sind verschiedene Dinge und landen nie im selben Block. Ein neuer Block beginnt, sobald

  • der Bereich mehr als maxRegisterGroup Register umfassen würde, oder
  • das nächste Register nicht unmittelbar an das vorige anschließt und autoGroupAllowGaps auf false steht.

Mit autoGroupAllowGaps: true werden Lücken überbrückt: der Block liest Register mit, die kein Kanal braucht, spart dafür aber eine Transaktion. Das lohnt sich bei kleinen Lücken und teuren Zugriffen, nicht bei weit auseinanderliegenden Adressen.

Wer die Aufteilung selbst bestimmen will, vergibt registerGroup je Kanal: Kanäle mit derselben Nummer bilden einen Block und werden von der automatischen Gruppierung ausgenommen.

Byteorder​

Der Wert eines Kanals wird vom selben Baustein aus dem gelesenen Puffer geschnitten wie beim fmProducer-Modul, dem SimpleBufferPicker. byteOrder kennt deshalb zwei Schreibweisen:

  • Benannt — bigEndian (auch big, be, motorola, msb, network) oder littleEndian (auch little, le, intel, lsb). Ohne Angabe gilt Big Endian.
  • Als Abbildung — eine Folge von Buchstaben, die die Bytes des Werts in die Reihenfolge bringt, in der sie auf dem Bus liegen. Die Länge der Folge sagt, über wie viele Bytes sich der Wert erstreckt, die Reihenfolge der Buchstaben, wie sie zu vertauschen sind.

Damit beantwortet sich auch der Unterschied zwischen "AB" und "BA": beide beschreiben einen Wert aus zwei Bytes. "AB" übernimmt sie in der gelesenen Reihenfolge, "BA" vertauscht sie. Entsprechend bei vier Bytes: "ABCD" unverändert, "CDAB" wortweise getauscht, "DCBA" vollständig umgedreht — die vier Varianten, mit denen ModBus-Geräte 32-Bit-Werte ablegen.

"BIT" ist ein Sonderfall für den Zugriff auf ein einzelnes Bit. Eine Folge, die weder ein bekannter Name noch eine gültige Abbildung ist, schaltet den Kanal ab; die Meldung nennt ihn beim Namen.

Zeitverhalten und Fehlerbehandlung​

Abfragezyklus​

Der Bus wird von einem eigenen Thread bedient, der in jedem Abfragezyklus (pollCycleInMilliseconds bzw. pollCycleInNanoseconds) alle fälligen Registerblöcke nacheinander liest. Ein Block mit pollingIntervalMultiplicator: n ist nur in jedem n-ten Zyklus fällig; Blöcke mit demselben Multiplikator werden dabei auf verschiedene Zyklen verteilt, damit sie nicht alle im selben Zyklus zusammenfallen.

Geändertes Verhalten ab smartCORE 2.12

Ein Block, der in einem Zyklus nicht fällig ist, produziert nichts. Bis smartCORE 2.11 wurde stattdessen der unveränderte Inhalt des Blocks erneut unter der aktuellen Zeit ausgegeben — ein Kanal mit pollingIntervalMultiplicator: 5 lieferte damit fünfmal so viele Werte, wie Messungen stattgefunden hatten.

Zeitstempel der Messwerte​

Jeder Kanal trägt den Zeitstempel der Transaktion, aus der sein Wert stammt: den Zeitpunkt, zu dem die Antwort des Geräts eingetroffen ist. Alle Kanäle eines Registerblocks tragen deshalb denselben Zeitstempel. Der Zeitpunkt, zu dem das Gerät den Wert gebildet oder auf die Leitung gelegt hat, ist über ModBus nicht beobachtbar — die Ankunft der Antwort ist der nächstliegende Zeitpunkt, den das Protokoll hergibt.

Geändertes Verhalten ab smartCORE 2.12

Bis smartCORE 2.11 trugen die Werte den Zeitpunkt ihrer Ausgabe in den smartCHANNEL, nicht den der Messung — also den Zeitpunkt nach der Abfrage aller Geräte am Bus, gegebenenfalls um mehrere Sekunden verzögert.

Rahmenstille bei ModBus/RTU​

Vor jeder Anfrage wird die Leitung für die Dauer der Rahmenstille t3.5 ruhig gehalten — die Pause, die eine RTU Nachricht von der nächsten trennt. Ihre Länge ergibt sich aus:

BedingungStille
readDelayMs ist gesetztder angegebene Wert
Baudrate über 19200 (oder unbekannt)1,75 ms — der feste Wert der MODBUS over Serial Line Specification V1.02; der gerechnete schrumpfte bei 115200 Baud auf 0,33 ms und würde nichts mehr trennen
sonst3,5 Zeichen zu 11 Bit, also 38500000 / Baudrate Mikrosekunden — 4,01 ms bei 9600 Baud
Geändertes Verhalten ab smartCORE 2.12

Die Pause liegt vor der Anfrage. Bis smartCORE 2.11 wurde nach einer erfolgreichen Antwort pausiert — nach einem Timeout also gerade nicht, und damit in dem Fall nicht, in dem die Leitung die Stille am nötigsten braucht.

Zwei Dinge werden dabei mitprotokolliert, weil sie auf eine zu schnell konfigurierte Anlage hindeuten: Bytes der vorigen Anfrage, die beim Start der nächsten noch in der Sendequeue stehen („die Leitung ist langsamer, als der Abfragezyklus annimmt"), und Daten, die unerwartet im Eingangspuffer liegen. Letztere werden gelesen und mit ihren ersten Bytes gemeldet, nicht stillschweigend verworfen.

Timeout und Abschaltung eines Registerblocks​

Bekommt eine Anfrage innerhalb von timeoutInMilliseconds keine Antwort, gilt der Zugriff als fehlgeschlagen. Der Registerblock zählt solche Fehlversuche, und nach minimalChannelAlarmCount Fehlversuchen in Folge wird er abgeschaltet: er wird nicht mehr abgefragt, und seine Kanäle produzieren nichts mehr. Die Meldung nennt Gerät, Registeradresse, Funktionscode, die Länge der Fehlerserie und ob ein neuer Versuch vorgesehen ist.

Nicht jeder Fehler zählt auf diese Schwelle ein:

Antwort des GerätsWirkung
Keine Antwort (Timeout), Illegal Function (01), Illegal Data Address (02), Illegal Data Value (03), Server Failure (04), Negative Acknowledge (07), Memory Parity (08), Gateway Target Failed To Respond (0B)zählt auf die Abschaltung ein — das Gerät oder die Konfiguration ist dauerhaft nicht in Ordnung
Acknowledge (05), Server Busy (06), Gateway Path Unavailable (0A)zählt nicht ein — das Gerät bittet um Geduld
Beschädigter Rahmen, z.B. CRC Fehlerzählt nicht ein — ein Ereignis, kein Zustand; die Anfrage zu wiederholen ist die richtige Antwort darauf

retryAfterBlockFailS entscheidet, ob ein abgeschalteter Block zurückkommt: mit 0 bleibt er für die Dauer der Messung aus, mit einem Wert größer null wird er nach dieser Zeit erneut versucht. Gelingt der Versuch, ist der Block wieder in Betrieb und der Zähler steht auf null; scheitert er, beginnt die Wartezeit von neuem.

tipp

Ein Gerät, das im Feld gelegentlich verschwindet und wiederkommt, braucht retryAfterBlockFailS. Ohne den Schlüssel ist nach minimalChannelAlarmCount Fehlversuchen Schluss, auch wenn das Gerät zwei Minuten später wieder am Bus hängt.

Modul-Informationen​

InformationWert
AutorenoptiMEAS GmbH
seit smartCORE0.1
ModultypProducer
AbhängigkeitenKEINE