Bekijk alle lessen
Deel 1
Basis
Deel 2
Modbus RTU
- Les 5RS485 uitgelegd: A, B, common en terminatie20 min
- Les 6Baudrate en pariteit: waarom 8E1 de default is16 min
- Les 7Het Modbus RTU frame byte voor byte, plus CRC18 min
- Les 8Meerdere Modbus apparaten op een bus zetten16 min
- Les 9Je eerste Modbus apparaat uitlezen met mbpoll22 min
- Les 10Modbus RTU storing zoeken: symptoom en oorzaak20 min
Deel 3
Modbus TCP
Deel 4
Gevorderd
- Les 16Veilig naar een Modbus apparaat schrijven18 min
- Les 17Word order en float: dezelfde bytes, andere waarde22 min
- Les 18Pollinterval en busbelasting zelf berekenen18 min
- Les 19Modbus beveiligen: het protocol doet het niet16 min
- Les 20Modbus integreren: PLC, Home Assistant of cloud20 min
- Les 21Modbus checklist voor oplevering en overdracht18 min
Veilig naar een Modbus apparaat schrijven
Naar een Modbus register schrijven kan een installatie stilleggen. Leer het verschil tussen FC05, FC06 en FC16 en werk met een vaste veiligheidsroutine.
Wat deze les behandelt
- FC05, FC06, FC15 en FC16, met de grens van 1968 coils en 123 registers
- Waarom FC05 alleen de waarden 0xFF00 en 0x0000 accepteert
- De routine die de oude waarde bewaart, en wat een echo niet bewijst
Lees eerst: Exception codes lezen en de juiste function code kiezen, Een Modbus registerkaart lezen zonder gokken
Naar een Modbus register schrijven is de enige handeling in dit protocol die iets kan stukmaken: een leesverzoek laat het apparaat precies zoals het was, een schrijfactie verandert de toestand van een installatie die op dat moment draait. Modbus kent geen ongedaan maken. Na deze les kies je bewust tussen FC05, FC06, FC15 en FC16, weet je wat een echo wel en niet bewijst, en volg je een routine die elke schrijfactie terugdraaibaar houdt.
Wat er misgaat als je zomaar schrijft
Het apparaat vraagt niet of je het zeker weet. Een laadpaal die zijn stroomlimiet in een holding register bijhoudt neemt jouw waarde net zo gehoorzaam aan als die van zijn eigen lastbalancering. Modbus kent geen gebruikers, geen rechten en geen logboek.
Daar komt bij dat lezen en schrijven vlak naast elkaar liggen. Bij mbpoll is het verschil precies een getal achter de poortnaam: staat het er niet, dan lees je, staat het er wel, dan schrijf je. Welke function code bij welk datablok hoort, staat in de referentie van alle Modbus function codes; deze les gaat over de vraag daarna.
Welke function code hoort bij welke schrijfactie?
Twee vragen bepalen het antwoord: schrijf je een bit of een register, en schrijf je er een of meer. Neem het spec-voorbeeld dat de waarde 3 schrijft naar het holding register dat op de datasheet register 2 heet (1-gebaseerd), dus naar PDU-adres 0x0001:
01 06 00 01 00 03 98 0B
| Byte | Waarde | Betekenis |
|---|---|---|
| 1 | 01 | serveradres |
| 2 | 06 | function code FC06, write single register |
| 3 en 4 | 00 01 | PDU-adres 1, op de datasheet register 2 |
| 5 en 6 | 00 03 | de waarde die je schrijft, decimaal 3 |
| 7 en 8 | 98 0B | CRC-16, low byte eerst |
Vier function codes doen het dagelijkse schrijfwerk, en hun grenzen volgen uit de maximale PDU van 253 bytes. FC05 zet een enkele coil, FC06 een enkel holding register met een waarde tussen 0x0000 en 0xFFFF, FC15 tot 1968 coils en FC16 tot 123 holding registers per verzoek. Discrete inputs en input registers ontbreken omdat ze per definitie alleen leesbaar zijn: schrijven daarheen levert exception 01 of 02 op.
Waarom FC05 alleen twee waarden accepteert
Omdat de standaard hier geen getal verwacht maar een van twee vaste constanten. 0xFF00 betekent aan, 0x0000 betekent uit, en de spec zegt er letterlijk bij dat alle andere waarden ongeldig zijn en de uitgang niet beïnvloeden. Het spec-voorbeeld zet een coil aan op PDU-adres 0x00AC:
01 05 00 AC FF 00 4C 1B
Verander daar nu een ding aan: zet 00 01 in het waardeveld, omdat 1 toch aan betekent. De PDU wordt 05 00 AC 00 01, en het antwoord is geen echo maar twee bytes:
85 03
0x85 is 0x05 plus 0x80, de vaste opslag die van elke function code een exception maakt, en 03 is de exception code die in het Engels illegal data value heet. De coil staat daarna nog precies zoals hij stond.
Het antwoord op een schrijfactie lezen
FC05 en FC06 sturen je eigen verzoek terug, FC15 en FC16 sturen alleen het startadres en het aantal terug. Op het FC06-frame uit de tweede sectie antwoordt de server dus met exact dezelfde acht bytes:
01 06 00 01 00 03 98 0B
Dat is de regel en niet het toeval van dit voorbeeld: de standaard omschrijft de normale respons op FC05 en FC06 als een echo van het verzoek, teruggestuurd nadat de waarde geschreven is. Bij FC15 en FC16 zou een echo het hele datablok herhalen, dus daar bevestigt de server alleen wat hij waar heeft weggezet. Gaat er iets mis, dan komt in alle vier de gevallen de function code plus 0x80 terug met 1 byte exception code erachter.
En dan het punt dat in de praktijk de meeste tijd kost: een echo bewijst dat de waarde in het register staat, niet dat het apparaat er iets mee doet. Veel apparaten hebben een aparte modusinstelling, een bevestigingsregister of een herstart nodig voordat een setpoint meetelt. Lees dus altijd terug en controleer het effect.
Een blok schrijven zonder halve toestanden
Drie losse FC06-acties zijn drie verzoeken met twee momenten ertussen waarop het apparaat een deel van je nieuwe instelling heeft en een deel van de oude. FC16 haalt die tussenmomenten weg. Dit spec-voorbeeld schrijft twee registers vanaf datasheetnummer 2 (PDU-adres 0x0001) met de waarden 0x000A en 0x0102:
01 10 00 01 00 02 04 00 0A 01 02 92 30
Het verschil met het FC06-frame zit in twee velden: na het startadres staat nu het aantal registers (00 02), en daarna een byte count (04) die altijd twee keer dat aantal is. Klopt die verhouding niet, dan antwoordt de server met exception 03 en gebeurt er niets. Het antwoord is kort: de PDU 10 00 01 00 02.
FC16 schrijft maximaal 123 registers per verzoek, minder dan de 125 die FC03 leest, omdat het verzoek zelf ook een startadres, een aantal en een byte count meedraagt. FC23 combineert schrijven en lezen in een enkel bericht, waarbij het schrijven volgens de standaard voor het lezen gaat: tot 121 schrijven en tot 125 lezen. En om een enkele bit om te zetten zonder de rest van het register aan te raken bestaat FC22, met een And_Mask en een Or_Mask.
De routine die je elke keer volgt
Vier stappen, en alleen de derde raakt het apparaat aan.
- Lees de oude waarde en schrijf hem op. Niet in je hoofd en niet in de scrollback van je terminal.
- Controleer de telling. Een datasheetnummer telt vanaf 1 en het adres op de draad vanaf 0, dus het PDU-adres is het datasheetnummer min 1. Naar het verkeerde adres schrijven kost meer dan van het verkeerde adres lezen.
- Schrijf de nieuwe waarde.
- Lees terug en controleer het effect, niet alleen het register.
Kies ook je moment. Pas je een setpoint aan terwijl een regeling actief stuurt, dan trekken jij en het apparaat aan hetzelfde register en verdwijnt je eigen waarde binnen enkele seconden. Of een register schrijfbaar is, staat in de R/W-kolom van de registerkaart; hoe je die leest staat in de les over het lezen van een registerkaart.
Wanneer je beter niet schrijft
Drie situaties waarin je de hand van de knop houdt. De eerste is broadcast op serveradres 0: elk apparaat op het segment voert de schrijfactie uit en niemand antwoordt, en daarom bestaat broadcast alleen bij schrijven. Je weet achteraf niet of het is aangekomen en niet welk apparaat het niet heeft uitgevoerd:
00 06 00 01 00 03 99 DA
De tweede is een register waarover de datasheet zwijgt. Fabrikanten leggen kalibratiewaarden en fabrieksinstellingen vaak in dezelfde adresruimte als de gewone setpoints, dus een adres dat niet in de tabel staat is geen leeg vakje maar onbekend terrein.
De derde is een apparaat dat elke schrijfactie meteen in niet-vluchtig geheugen vastlegt. Dat geheugen heeft een eindig aantal schrijfcycli, dus schrijven in een pollus van een seconde is geen monitoring maar slijtage. Automatiseer je vanuit Home Assistant met de Modbus integratie, zoek dan eerst op of het apparaat elke waarde vastlegt.
Veelgemaakte fouten
Schrijven zonder de oude waarde te noteren. Je verandert een setpoint, het apparaat gedraagt zich anders dan verwacht, en je kunt niet terug omdat niemand weet wat er stond. Lees eerst, noteer, en pas dan schrijven.
0x0001 sturen om een relais aan te zetten. FC05 kent alleen 0xFF00 en 0x0000. Je krijgt exception 03, de coil verandert niet, en omdat er wel een antwoord komt lijkt de bus in orde. Vervolgens ga je bekabeling controleren die niets mankeert.
Een echo voor bevestiging aanzien. FC05 en FC06 sturen je verzoek terug zodra de waarde is weggeschreven. Dat zegt niets over wat de applicatie in het apparaat ermee doet.
Broadcast gebruiken om tijd te winnen. Op serveradres 0 antwoordt niemand. Je weet niet of het bericht is aangekomen, je weet niet welk apparaat het niet heeft uitgevoerd, en je raakt in een keer alles wat aan de bus hangt. Schrijf per apparaat, ook als dat langer duurt.
Aan de slag
Je voert een keer een volledige schrijfroutine uit en lokt daarna bewust een fout uit. Zowel mbpoll als de pymodbus-simulator zijn gratis te gebruiken, ook zakelijk.
- 1
Kies een register dat niets beweegt
Zoek in de datasheet een register dat als schrijfbaar staat aangemerkt en dat niets aanstuurt wat draait of schakelt. Een displayinstelling is goed, een klepstand niet.
- 2
Lees de oude waarde en noteer hem
Draai het leescommando en schrijf de uitkomst op papier, niet alleen in je terminal.
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 20 -c 1 -1 /dev/ttyUSB0 - 3
Schrijf de nieuwe waarde
Hetzelfde commando met een waarde erachter is een schrijfactie.
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 20 /dev/ttyUSB0 1234 - 4
Lees terug en controleer
Draai het commando uit stap 2 opnieuw en kijk of er nu 1234 staat. Controleer daarna op het apparaat zelf of er iets veranderd is.
- 5
Zet de oude waarde terug
Gebruik het commando uit stap 3 met de genoteerde waarde en lees nog een keer terug.
- 6
Lok een exception uit
Stuur naar een coil bewust
0x0001in plaats van0xFF00en noteer wat je terugkrijgt. Volgens de standaard is dat exception 03.
Zonder hardware. Doe stap 2 tot en met 6 tegen de pymodbus-simulator op poort 5020. Bouw met SimData en SimDevice een server met een schrijfbaar holding register, zoals in de les over oefenen met de simulator.
Verwacht resultaat: een waarde die je hebt veranderd en weer hebt teruggezet, met de oude waarde op papier, plus een exception die je zelf hebt uitgelokt.
Samenvatting
- Lezen verandert niets aan een apparaat, schrijven wel, en Modbus kent geen gebruikers, geen rechten en geen ongedaan maken.
- FC05 schrijft een coil, FC06 een holding register, FC15 tot 1968 coils en FC16 tot 123 registers in een enkel verzoek.
- FC05 accepteert alleen
0xFF00voor aan en0x0000voor uit, en elke andere waarde levert exception 03 op zonder dat de coil verandert. - FC05 en FC06 echoën je verzoek en FC15 en FC16 bevestigen adres en aantal, maar geen echo bewijst dat het apparaat de waarde ook gebruikt.
- De routine is elke keer dezelfde: lees de oude waarde, noteer hem, schrijf, lees terug en controleer het effect.
Controleer jezelf
Vier vragen over deze les. Je krijgt bij elk antwoord uitleg.
Vraag 1 van 4
Zelf zien hoe het werkt?
De ModbusCloud Gateway leest de apparaten uit deze cursus uit zonder dat je registers hoeft te programmeren.