In deze les

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
ByteWaardeBetekenis
101serveradres 1
203FC03, read holding registers
3 en 400 6Bstartadres, PDU-adres 107
5 en 600 03aantal registers: 3
7 en 874 17CRC-16, low byte eerst

Het apparaat antwoordt hierop met:

01 03 06 02 2B 00 00 00 64 05 7A
ByteWaardeBetekenis
101serveradres 1
203dezelfde function code, dus een normaal antwoord
306byte count: er volgen 6 databytes
4 tot 902 2B 00 00 00 64de waarden 555, 0 en 100
10 en 1105 7ACRC-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.

LezenEén schrijvenMeerdere schrijvenCoils0x010x050x0FDiscrete inputs0x02niet schrijfbaarniet schrijfbaarHolding registers0x030x060x10Input registers0x04niet schrijfbaarniet schrijfbaar
Het blok en de bewerking bepalen samen de function code.

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.

MSBLSBJouw verzoek0x030bit 70bit 60bit 50bit 40bit 30bit 21bit 11bit 0Bit 7 gezet, dus plus 0x80Exception-antwoord0x831bit 70bit 60bit 50bit 40bit 30bit 21bit 11bit 0
Een exception houdt de function code en zet het hoogste bit. 0x03 wordt 0x83.

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.

Exception codes en waar je gaat zoekenFout in jouw verzoekHet apparaat leeft en antwoordt netjes. Corrigeer je adres, je functioncode of je aantal.01Illegal function02Illegal data address03Illegal data valueProbleem in het apparaatJe verzoek klopt, maar het apparaat kan het nu niet uitvoeren. Kijk inhet apparaat zelf.04Server device failure05Acknowledge06Server device busy08Memory parity errorProbleem in de gatewayDit antwoord komt van de gateway, niet van het eindapparaat erachter.0AGateway path unavailable0BGateway target device failed to respond
Een exception is goed nieuws: het apparaat antwoordt. De code vertelt of de fout in je verzoek zit, in het apparaat, of in de gateway ertussen.

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:

  1. Het verzoek komt foutloos aan en het apparaat kan het uitvoeren: normaal antwoord.
  2. Het verzoek komt niet aan: geen antwoord, jij loopt in een timeout.
  3. Het verzoek komt aan, maar het apparaat ziet een CRC- of pariteitsfout: geen antwoord, weer een timeout.
  4. 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. 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 op http://127.0.0.1:8081/.

  2. 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. 3

    Lok een exception uit

    Lees nu PDU-adres 1. De simulator antwoordt met function_code=131 en exception_code=2.

  4. 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. 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
Je stuurt een verzoek over RS485 en krijgt dit frame terug: 01 83 02 C0 F1. Wat is er aan de hand?
Je stuurt een FC03-verzoek naar een apparaat dat volgens de datasheet alleen input registers heeft. Wat komt er terug?
Apparaat 1 antwoordt met exception 02. Apparaat 2 op dezelfde bus geeft een timeout. Wat weet je nu?
Hoeveel holding registers mag je in een enkel FC03-verzoek opvragen, en wat gebeurt er als je er meer vraagt?

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