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
Exception codes lezen en de juiste function code kiezen
Een Modbus exception code vertelt je precies waar de fout zit. Leer welke function code je stelt, en wat een 0x83 met exception 02 over je startadres zegt.
Wat deze les behandelt
- Welke function code hoort bij welk datablok en welke bitbreedte
- Hoe je 0x83 met exception 02 leest, en waar je dan gaat zoeken
- Waarom een CRC-fout stilte oplevert en geen exception
Lees eerst: Modbus adressering: van 40001 naar het adres
De function code is de vraag die je stelt, en een exception code is het nette antwoord waarin het apparaat zegt welke aanname in die vraag fout was. Zie je een exception, dan is dat goed nieuws: je frame is foutloos aangekomen, dus de bekabeling, de busparameters en het serveradres kloppen allemaal. Na deze les lees je uit twee bytes af wat je vroeg en waar je moet gaan zoeken.
Welke vraag stel je met welke code?
De function code bepaalt welk datablok je aanspreekt en of je leest of schrijft. Kijk eerst naar een echt verzoek aan server 1 op een RS485-bus:
01 03 00 6B 00 03 74 17
| Byte | Waarde | Betekenis |
|---|---|---|
| 1 | 01 | serveradres 1 |
| 2 | 03 | FC03, read holding registers |
| 3 en 4 | 00 6B | startadres, PDU-adres 107 |
| 5 en 6 | 00 03 | aantal registers: 3 |
| 7 en 8 | 74 17 | CRC-16, low byte eerst |
Het apparaat antwoordt hierop met:
01 03 06 02 2B 00 00 00 64 05 7A
| Byte | Waarde | Betekenis |
|---|---|---|
| 1 | 01 | serveradres 1 |
| 2 | 03 | dezelfde function code, dus een normaal antwoord |
| 3 | 06 | byte count: er volgen 6 databytes |
| 4 tot 9 | 02 2B 00 00 00 64 | de waarden 555, 0 en 100 |
| 10 en 11 | 05 7A | CRC-16 |
De regel is kort: byte 2 draagt heen en terug dezelfde function code, en die code zegt tegelijk welk blok je aanspreekt en welke bewerking je doet. Acht codes dekken het dagelijkse werk: FC01 en FC02 lezen bits, FC03 en FC04 lezen registers van 16 bits, FC05 en FC06 schrijven een enkel object, FC15 en FC16 schrijven een blok. De rest van de publieke codes is diagnostiek, file record access of alleen bedoeld voor seriele lijnen. FC05, FC06 en FC16 schrijven en kunnen dus iets stukmaken; de vaste routine daarvoor staat in de les over veilig naar een apparaat schrijven.
De volledige lijst met alle publieke codes staat in de referentietabel met alle Modbus function codes. Deze les gaat verder over de antwoordkant.
Waarom er twee codes zijn om bijna hetzelfde te lezen
FC03 en FC04 lezen allebei registers van 16 bits, maar uit twee blokken: FC03 leest holding registers, die je ook mag beschrijven, FC04 leest input registers, die alleen leesbaar zijn. Het protocol houdt die blokken strikt gescheiden, dus PDU-adres 107 in het ene heeft niets te maken met PDU-adres 107 in het andere.
Een FC04-verzoek heeft precies dezelfde vorm als een FC03-verzoek en verschilt alleen in byte 2. Dit voorbeeld uit de standaard leest een enkel input register op PDU-adres 8:
01 04 00 08 00 01 B0 08
Byte 2 draagt hier 04 in plaats van 03, daarna volgen dezelfde velden: startadres, aantal en CRC. Zet je in het FC03-verzoek hierboven alleen byte 2 op 04, dan vraag je dezelfde adressen op in het andere blok, met een nieuw uitgerekende CRC.
Veel apparaten implementeren maar een van de twee blokken. Een energiemeter zet zijn meetwaarden vaak in input registers, een regelaar alles in holding registers. Welk blok jouw apparaat gebruikt staat alleen in de datasheet, en wat er in die blokken hoort staat in de uitleg over Modbus registers en registertypen.
Hoe je een exception herkent zonder te tellen
Een exception herken je aan de function code in het antwoord: het apparaat stuurt jouw code terug met 0x80 erbij opgeteld. 0x03 wordt 0x83, 0x04 wordt 0x84, 0x10 wordt 0x90. In bits is dat het zetten van bit 7, het hoogste bit van de byte.
Daarna volgt precies een byte: de exception code zelf. De exception-PDU is dus altijd exact twee bytes lang. Krijg je op het FC04-verzoek hierboven 84 02 terug, dan was je vraag een FC04 en wijst het apparaat je adres af. In een RTU-frame komt daar het serveradres voor en komen er twee CRC-bytes achter: vijf bytes, tegen zeven voor een normaal FC04-antwoord op een enkel register. Een kort antwoord in een hex-dump is dus vrijwel altijd een exception.
De negen exception codes, gegroepeerd naar oorzaak
De huidige standaard V1.1b3 kent negen exception codes: 01 tot en met 06, 08, 0A en 0B. Ze vallen uiteen in drie groepen, en de groep vertelt je waar je gaat zoeken.
De eerste groep los je op in je eigen configuratie, de tweede in het apparaat zelf: adres en aantal klopten dan wel, maar de uitvoering lukte niet of loopt nog. De derde groep komt van een gateway en niet van het apparaat erachter. Exception 0B betekent dat de gateway je verzoek wel op de RS485-kant heeft gezet, maar dat dat serveradres niet antwoordde: de TCP-vertaling van een timeout op de bus.
Er is geen exception 07 en geen 09. Kom je 07 tegen in een handleiding, dan is dat oude Modicon-documentatie.
Wat exception 02 je precies vertelt
Exception 02, in het Engels illegal data address, zegt dat de combinatie van startadres en aantal buiten het bereik van het apparaat valt. Niet alleen je startadres telt, ook je aantal.
De standaard rekent dat voor. Bij een apparaat met 100 registers loopt het PDU-adres van 0 tot en met 99. Vraag je 4 registers op vanaf PDU-adres 96, dan gaat dat goed: 96, 97, 98 en 99. Vraag je er 5 op vanaf 96, dan faalt het verzoek met exception 02, want adres 100 bestaat niet.
De tweede bron is de off-by-one tussen twee tellingen. Datasheetnummer 40108 is PDU-adres 107, want de klassieke nummering telt vanaf 1 en het protocol vanaf 0. Wie het datasheetnummer rechtstreeks op de draad zet, valt buiten het bereik. Dat rekenwerk staat in de les over Modbus adressering.
Waarom stilte iets heel anders betekent dan een exception
Een verzoek heeft volgens de standaard vier uitkomsten, en maar een daarvan is een exception:
- Het verzoek komt foutloos aan en het apparaat kan het uitvoeren: normaal antwoord.
- Het verzoek komt niet aan: geen antwoord, jij loopt in een timeout.
- Het verzoek komt aan, maar het apparaat ziet een CRC- of pariteitsfout: geen antwoord, weer een timeout.
- Het verzoek komt foutloos aan maar het apparaat kan het niet uitvoeren: exception.
Uitkomst 3 is de belangrijkste praktijkregel van deze les: een CRC-fout geeft geen foutmelding maar stilte, net als een verzoek aan een leeg serveradres. Een timeout laat kabel, baudrate, pariteit en adres allemaal open.
Hoe je na een timeout een hele bus systematisch afloopt staat in de handleiding om een Modbus-netwerk te scannen.
Wat FC43 je over een onbekend apparaat vertelt
FC43 met MEI type 14, Read Device Identification, vraagt het apparaat zelf naar zijn identiteit. Drie objecten zijn verplicht: VendorName, ProductCode en MajorMinorRevision. De request-PDU is vier bytes, 2B 0E 01 00: de function code, het MEI type, Read Device ID code 01 voor de basisidentificatie en object id 0x00. Terug komen merk, typenummer en revisie.
Dat is goud waard bij een installatie waar niemand meer weet wat er in de kast hangt. Ondersteunt het apparaat de functie niet, dan komt er 0xAB terug met exception 01, en ook dat is informatie: het apparaat leeft en praat.
Een complete identificatie past niet altijd in een PDU van 253 bytes. Het antwoord heeft daarom More Follows en Next Object Id, waarmee je de rest in een tweede verzoek ophaalt.
Veelgemaakte fouten
FC03 en FC04 verwisselen. Je vraagt holding registers op bij een apparaat dat zijn meetwaarden in input registers zet. Je krijgt exception 01 als het apparaat FC03 helemaal niet kent, of exception 02 als het blok kleiner is dan je denkt. Kijk in de datasheet welk blok het apparaat gebruikt en gok niet.
Een exception aanzien voor een bekabelingsprobleem. Deze kost de meeste tijd, want je gaat zoeken op de enige plek die aantoonbaar in orde is. Een exception bewijst dat je frame foutloos is aangekomen, dus fysieke laag, busparameters en serveradres kloppen. Laat de kabel met rust en pak de datasheet.
Denken dat exception 03 over de waarde in het register gaat. De standaard zegt uitdrukkelijk van niet. Exception 03 gaat over de structuur van je verzoek, bijvoorbeeld een aantal buiten het bereik of een byte count die niet bij je aantal past. Een setpoint dat te hoog is voor de applicatie geeft geen exception 03.
Exception 07 of 09 verwachten. Die bestaan niet in V1.1b3. De tabel springt van 06 naar 08 en van 08 naar 0A.
Aan de slag
Een exception uitlokken is de snelste manier om er een te leren herkennen. Dit kost vijf minuten en je hebt er geen hardware voor nodig.
- 1
Start de simulator
Draai
pymodbus.simulator --modbus_server server --modbus_device device. Pymodbus 3.15.0 is gratis te gebruiken, ook zakelijk. De Modbus TCP-server luistert op poort 5020, de webinterface staat ophttp://127.0.0.1:8081/. - 2
Lees een register dat wel bestaat
Lees een register op PDU-adres 3. Je krijgt de waarde 17001, en die staat stil bij elke lezing.
- 3
Lok een exception uit
Lees nu PDU-adres 1. De simulator antwoordt met
function_code=131enexception_code=2. - 4
Reken het antwoord terug
131 is 0x83, en 0x83 min 0x80 is 0x03. Je oorspronkelijke vraag was dus een FC03, en exception 02 wijst je op je startadres.
- 5
Duw tegen de limiet
Vraag met FC03 eens 130 registers op. De standaard staat er maximaal 125 toe, dus dit hoort exception 03 op te leveren. Noteer wat je apparaat werkelijk terugstuurt: sommige apparaten antwoorden in de praktijk met 02.
Een minimale client voor stap 2 en 3:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1", port=5020)
client.connect()
print(client.read_holding_registers(address=3, count=1, device_id=1).registers)
print(client.read_holding_registers(address=1, count=1, device_id=1))
Met hardware. Doe dezelfde oefening tegen je eigen apparaat en vraag een register op dat volgens de datasheet niet bestaat, bijvoorbeeld een adres ver voorbij het laatste blok. Bijna elk apparaat antwoordt dan met 0x83 en exception 02. Het verwachte resultaat is in beide routes hetzelfde: een exception in beeld, plus de zekerheid dat je verbinding op dat moment aantoonbaar werkt.
Samenvatting
- De function code in byte 2 zegt welk blok je aanspreekt en welke bewerking je doet, en komt in een normaal antwoord ongewijzigd terug.
- Een exception-antwoord is precies twee bytes: jouw function code plus 0x80, dus 0x03 wordt 0x83, gevolgd door de exception code.
- V1.1b3 kent negen exception codes (01 tot en met 06, 08, 0A en 0B), en de groep zegt waar je zoekt: je verzoek, het apparaat of de gateway.
- Exception 02 kijkt naar startadres en aantal samen, dus je krijgt hem ook bij een geldig startadres.
- Een CRC-fout geeft geen exception maar stilte: een timeout stuurt je naar de bekabeling, een exception naar de datasheet.
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.