In deze les

Wat deze les behandelt

  • De bytes die rtuovertcp van echt Modbus TCP onderscheiden
  • Wat een gateway met de unit id en de CRC doet, en wat hij laat staan
  • De keuze tussen RTU en TCP, en de foutbeelden die een gateway toevoegt

Lees eerst: Het Modbus RTU frame byte voor byte, plus CRC, Poort 502, de MBAP header en de unit id, Modbus TCP in je netwerk: IP, VLAN, firewall

rtuovertcp is geen tweede protocol, maar een RTU-frame dat ongewijzigd door een TCP-verbinding wordt geduwd: serveradres vooraan, CRC-16 achteraan, en geen MBAP-header. Echt Modbus TCP doet het precies andersom. Na deze les zie je aan de bytes met welke van de twee je te maken hebt, weet je wat een gateway met je frame en met je unit id doet, en kies je in je client de stand die werkt.

Twee bytestromen die er hetzelfde uitzien

Ze lijken alleen op elkaar zolang je niet naar het begin en het eind kijkt. Dit is het verzoek "lees drie holding registers vanaf PDU-adres 107 bij serveradres 1", zoals echt Modbus TCP het over poort 502 stuurt:

00 01 00 00 00 06 FF 03 00 6B 00 03

Twaalf bytes. En dit is hetzelfde verzoek als RTU-frame, zoals het over RS485 gaat en zoals een eenvoudige seriële server het ongewijzigd door een TCP-verbinding duwt:

01 03 00 6B 00 03 74 17

Acht bytes. In allebei staan in het midden dezelfde vijf bytes: 03 00 6B 00 03. Dat is de PDU (protocol data unit): function code FC03, startadres 0x006B (PDU-adres 107, op een datasheet meestal het 1-gebaseerde nummer 40108) en het aantal 3. Alleen de verpakking verschilt.

OnderdeelEcht Modbus TCPRTU-frame door TCP
Voor de PDUMBAP header, 7 bytesserveradres, 1 byte, hier 01
Na de PDUnietsCRC-16, 2 bytes, hier 74 17, low byte eerst
Totale lengte12 bytes8 bytes
Berichtgrenshet Length-veld in de header3,5 karaktertijden stilte op de seriële kant
Echt Modbus TCPMBAP, 7 bytes00 01 00 00 00 06 FFPDU: FC03, startadres0x006B, 3 registers03 00 6B 00 03CRC-16RTU-frame door een TCP-verbindingServeradres,1 byte01PDU: FC03, startadres0x006B, 3 registers03 00 6B 00 03CRC-16,2 bytes74 17Zelfde PDU, andere envelop

Home Assistant: type tcp tegenover type rtuovertcp

Het verschil zit vooraan en achteraan, niet in de vraag zelf.

Voor de volledige afweging tussen beide transporten is de vergelijking van Modbus RTU en Modbus TCP de naslagpagina; deze les gaat over de bytes.

Wat een gateway precies doet met je frame

Uitpakken en opnieuw inpakken, meer niet. Een gateway die echt vertaalt, doorloopt per verzoek deze route:

  1. Hij accepteert je TCP-verbinding op poort 502, leest de MBAP-header en onthoudt de transaction id.
  2. Hij gooit die header weg en houdt de PDU over: 03 00 6B 00 03.
  3. Hij zet de unit id uit de header ervoor als serveradres, rekent de CRC-16 over adres plus PDU uit en plakt die erachter. Vraag je unit id 1, dan staat er nu 01 03 00 6B 00 03 74 17 op de bus.
  4. Op de RS485-kant is hij zelf de client: hij zet het frame op de bus en wacht op antwoord of op zijn eigen timeout.
  5. Komt het antwoord, dan controleert hij de CRC, haalt adres en CRC eraf en bouwt de MBAP-header terug, met een Length die hij zelf uitrekent.
RS485Meter 1Meter 2Meter 3RTU-naar-TCP-converterRTU ⇄ TCPEthernetClient of cloudRS485RJ45 / Ethernet
De converter pakt elk verzoek uit en opnieuw in, en wordt daarmee de client op de bus.

De unit id is dus geen decoratie. Bij een apparaat dat rechtstreeks aan het netwerk hangt vul je 0xFF in (255), of 0x00, omdat het IP-adres het apparaat al aanwijst. Achter een gateway is de unit id het echte serveradres op de bus, ergens tussen 1 en 247. Hoe je dat aan de kant van het kastje inricht, staat in de handleiding voor het installeren van een Modbus TCP gateway.

Waarom rtuovertcp bestaat

Omdat niet elk kastje met een netwerkpoort protocolvertaling doet. Een deel van de apparaten die je op een RS485-bus tegenkomt zijn seriële servers (in het Engels device server of serial server): ze nemen alles wat op de TCP-verbinding binnenkomt en zetten het byte voor byte op de seriële poort, en andersom. Ze kijken niet in het frame, ze kennen de MBAP-header niet, en ze rekenen geen CRC uit. Dat is goedkoper te bouwen en werkt ook voor protocollen die geen Modbus zijn.

Het gevolg is dat jouw client het werk doet dat de gateway niet doet: je stuurt een compleet RTU-frame met serveradres en CRC-16, zonder MBAP-header eromheen. Dat kost je ook de transaction id, dus je kunt geen twee verzoeken tegelijk laten lopen op die verbinding. Je vraagt, wacht op antwoord of timeout, en gaat pas dan verder, precies zoals op de bus zelf. Hoe die verbinding zich op je netwerk gedraagt, staat in de les over netwerkeisen, firewall en VLAN.

Welke instelling kies je in je client?

De stand die past bij wat er uit het apparaat komt, niet bij de kabel die erin gaat. In Home Assistant is dat het veld type in de modbus-integratie:

modbus:
  - name: gateway
    type: rtuovertcp
    host: 192.168.1.50
    port: 502
tcpecht Modbus TCPHAhubPV-omvormerEthernetPoort 502
Voor apparaten met een eigen netwerkpoort die zelf Modbus TCP spreken, en voor gateways die echt vertalen. Er zit een MBAP-header voor de PDU en geen CRC erachter.
rtuovertcpRTU-frames in een TCP-stroomHAhubseriële serverEthernetPoort 502 (RTU-framing)
Voor seriële servers die het RTU-frame ongewijzigd doorsturen. Herken je aan het serveradres vooraan en de twee CRC-bytes achteraan.
serialrechtstreeks op RS485HAhubUSB-RS485A/B/GND/dev/ttyUSB0
Voor een USB-RS485 adapter aan de machine waar de client op draait. Je geeft poort, baudrate en pariteit op in plaats van een IP-adres.
Kies de verkeerde stand en je krijgt stilte, geen nette foutmelding.

Het symptoom van de verkeerde keuze is herkenbaar: ping werkt, de poorttest slaagt, en toch lukt geen enkele lezing. Niemand klaagt namelijk. Zet je rtuovertcp tegen een apparaat dat echt Modbus TCP spreekt, dan leest dat apparaat jouw 01 03 als transaction id en 00 6B als protocol id. Dat is niet 0x0000, dus gooit het het bericht stilzwijgend weg zonder exception. Andersom zet de seriële server jouw MBAP-header gewoon op de bus, waar geen enkel apparaat er een geldige CRC in herkent.

Wanneer kies je RTU en wanneer TCP?

Zes situaties waarin de keuze zich vanzelf maakt:

SituatieWat dat betekent
Er ligt al een werkende RS485-busRTU houden. Een gateway erbij is goedkoper dan alles opnieuw trekken
Meer dan 1000 m tussen client en apparaat bij 9600 baudTCP. De standaard noemt 1000 m als maximale stamkabellengte bij 9600 baud met AWG26 of dikker
Meer dan 32 apparaten op één segmentTCP, of segmenteren met een repeater. 32 apparaten zonder repeater zijn altijd toegestaan
Het apparaat heeft alleen klemmen voor A, B en commonRTU, eventueel met een gateway ernaast
Er ligt al ethernet tot bij het apparaatTCP, dan heb je geen extra kabel nodig
Meerdere systemen moeten hetzelfde apparaat uitlezenTCP, want op een RS485-bus verdeelt een enkele client het woord

De complete afweging inclusief kosten en beheer staat in de vergelijking van Modbus RTU en Modbus TCP, en welk kastje bij welke situatie past in de koopgids voor Modbus gateways.

Wat je met een gateway erbij krijgt aan foutbeelden

Twee exception codes die je zonder gateway nooit ziet, want ze komen van de gateway zelf. De standaard kent er negen (01 tot en met 06, 08, 0A en 0B), en juist deze twee staan er expliciet in als "specialized use in conjunction with gateways".

  • Exception 0A, Gateway Path Unavailable. De gateway kon intern geen pad van zijn netwerkpoort naar zijn seriële poort vrijmaken. Meestal verkeerd geconfigureerd of overbelast door te veel gelijktijdige polls.
  • Exception 0B, Gateway Target Device Failed To Respond. De gateway heeft je verzoek wel op de bus gezet, maar dat serveradres antwoordde niet. Dit is de TCP-vertaling van een seriële timeout, dus controleer serveradres, bedrading, baudrate en pariteit.

Zo ziet een 0B eruit op unit id 9, opgebouwd volgens de regels van de standaard:

00 01 00 00 00 03 09 83 0B

Length is 0x0003 (1 byte unit id plus 2 bytes PDU), de function code is 0x83 (0x03 plus 0x80) en de laatste byte is exception 0B. Krijg je in plaats daarvan helemaal niets, dan komt je verzoek niet eens tot de bus. Hoe je een frame byte voor byte uit elkaar haalt, staat in de les over het RTU-frame en de CRC.

Veelgemaakte fouten

tcp instellen waar rtuovertcp nodig is. Ping werkt, de poort staat open, en toch lukt geen enkele lezing. Dat is het handtekeningbeeld van deze fout. Wissel de stand om voordat je iets anders aanraakt, en verander verder niets.

Unit id 255 gebruiken achter een gateway. Achter een gateway is de unit id het echte serveradres tussen 1 en 247, geen betekenisloze vulwaarde. Met 255 vraag je naar een gereserveerd adres, en dat levert exception 0B of stilte op. Zoek het adres op de meter zelf op.

De gateway als onzichtbaar beschouwen. Hij is de client op de RS485-bus, met een eigen timeout en een eigen pollgedrag. Zet je er te veel gelijktijdige verzoeken in, dan krijg je exception 0A terug van een kastje dat je niet in je diagnose had staan.

RTU vervangen door TCP en de bus laten liggen. Een gateway lost netwerkbereik op, geen bekabelingsproblemen. Een slecht getermineerde bus blijft na de gateway net zo slecht getermineerd, alleen zie je de fout nu als exception 0B in plaats van als timeout.

Aan de slag

Je legt dezelfde vraag in twee verpakkingen naast elkaar en kijkt welke van de twee jouw gateway wil.

  1. 1

    Schrijf het RTU-frame op

    Noteer het verzoek "lees drie holding registers vanaf PDU-adres 107 bij serveradres 1" in RTU-vorm: 01 03 00 6B 00 03 74 17. Omcirkel de PDU.

  2. 2

    Schrijf hetzelfde verzoek in TCP-vorm

    Dat wordt 00 01 00 00 00 06 FF 03 00 6B 00 03. Omcirkel ook hier de PDU, en leg de twee onder elkaar zodat de omcirkelde delen uitlijnen.

  3. 3

    Tel de bytes

    8 tegen 12. Het verschil is 7 bytes header eraf en 1 byte adres plus 2 bytes CRC erbij, dus 12 min 7 plus 3 is 8. Klopt de som, dan heb je de envelop begrepen.

  4. 4

    Zet je client een keer in elke stand

    Heb je een gateway: configureer je client eerst als tcp, daarna als rtuovertcp, en noteer welke van de twee antwoord geeft. Verander verder niets, want anders weet je achteraf niet waardoor het ging werken.

  5. 5

    Vraag een adres op dat niet bestaat

    Zet de unit id op een adres dat niet op de bus zit en noteer wat je krijgt. Exception 0B betekent dat de gateway meedenkt en het verzoek echt op de bus heeft gezet. Een kale timeout betekent dat hij alleen doorlust.

Zonder gateway. Stap 1 tot 3 hebben geen hardware nodig. Voor stap 4 en 5 kun je in de les over de MBAP header en de unit id hetzelfde frame in de builder zetten en de bytes vergelijken met het RTU-frame hierboven.

Verwacht resultaat: twee frames naast elkaar met in allebei dezelfde vijf PDU-bytes gemarkeerd, en de wetenschap welke verbindingsvorm jouw gateway wil.

Samenvatting

  • Echt Modbus TCP zet een MBAP-header van 7 bytes voor de PDU en heeft geen CRC; een getunneld RTU-frame heeft juist een serveradres van 1 byte ervoor en een CRC-16 van 2 bytes erachter.
  • Hetzelfde leesverzoek is 12 bytes over Modbus TCP en 8 bytes als RTU-frame, met in het midden allebei dezelfde PDU 03 00 6B 00 03.
  • Een gateway verandert niets aan de PDU: hij vervangt alleen de envelop, en de unit id uit de MBAP-header wordt het serveradres op de RS485-bus.
  • Achter een gateway vul je een unit id tussen 1 en 247 in, bij een apparaat dat rechtstreeks aan het netwerk hangt 0xFF of 0x00.
  • Exception 0A en exception 0B komen van de gateway zelf: 0A betekent dat hij intern geen pad vrij kreeg, 0B dat er op de bus niemand antwoordde.

Controleer jezelf

Vier vragen over deze les. Je krijgt bij elk antwoord uitleg.

Vraag 1 van 4
Je capture toont binnen een TCP-verbinding op poort 502 de bytes 01 03 00 6B 00 03 74 17. Wat is hier aan de hand?
Ping naar de gateway werkt, poort 502 staat aantoonbaar open, en toch krijg je op elk register een timeout. Wat probeer je als eerste?
Je vraagt via een gateway naar unit id 9, terwijl op de RS485-bus alleen de serveradressen 1 tot 4 bestaan. Wat is de meest waarschijnlijke uitkomst?
Wat verandert een gateway aan de PDU van je verzoek?

Loopt het vast op een project?

Beschrijf wat je ziet en waar het misgaat. We kijken mee en zeggen wat we zouden doen.

Verder lezen in de kennisbank