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
Modbus adressering: van 40001 naar het adres
Modbus adressering uitgelegd met een echt frame. Je rekent 40001 om naar het adres op de draad, kent de vier datablokken en herkent de klassieke off-by-one.
Wat deze les behandelt
- De vier datablokken en de function codes die erbij horen
- Van 40108 op het datasheet naar adres 107 op de draad
- Wat jouw tool met address bedoelt, en de test die dat bewijst
Lees eerst: Modbus leren: waarom dit protocol blijft werken
Modbus adressering kent drie tellingen door elkaar: het nummer 40108 op je datasheet, het datamodelnummer 108 en het adres 107 dat werkelijk over de draad gaat. Wie dat verschil niet ziet, leest structureel het buurregister of krijgt exception 02 terug. Na deze les reken je elk datasheetnummer om naar het adres dat jouw tool wil hebben, en bewijs je met een test van dertig seconden dat je het goed hebt.
Waarom je meter 2300 laat zien en je software 0
Omdat je tool een ander getal verstuurt dan jij denkt. Op het display van de energiemeter staat de netspanning, in de datasheet staat de regel "netspanning, 40001, holding register", en je invoerveld heet gewoon "address". Je vult 40001 in en krijgt niets bruikbaars terug.
Wat er dan gebeurt, hangt van het apparaat af. Meestal antwoordt het met exception 02, illegal data address in het Engels, omdat het adres dat jouw tool verstuurde niet bestaat. Op een apparaat met veel registers krijg je wel een waarde terug, alleen niet die van jou. Dat tweede geval is het gevaarlijkste, want niets meldt een fout. Voor de naslag over registerkaarten is er het artikel over Modbus registers en registerkaarten; deze les leert je de omrekening als handeling.
De vier datablokken op een rij
Modbus kent vier gescheiden datablokken, en de function code die je stuurt bepaalt in welk blok je kijkt. Twee blokken zijn 1 bit breed: coils (lezen en schrijven) en discrete inputs (alleen lezen). Twee blokken zijn 16 bits breed: holding registers (lezen en schrijven) en input registers (alleen lezen). Elk blok kan tot 65536 items bevatten.
Gescheiden op papier betekent niet gescheiden in het apparaat. De standaard zegt letterlijk dat het volstrekt aanvaardbaar en heel gebruikelijk is om de vier tabellen over elkaar heen te leggen. Daarom geeft holding register 40001 bij het ene merk dezelfde waarde als input register 30001, en bij het andere merk niet.
Drie tellingen die mensen door elkaar halen
Neem een echte datasheetregel: "40108, Actief vermogen totaal". Zo ziet het verzoek eruit dat een client naar serveradres 1 stuurt om dat register plus de twee erachter te lezen.
| Bytes | Betekenis |
|---|---|
01 | serveradres 1 |
03 | FC03, lees holding registers |
00 6B | startadres, PDU-adres 107 |
00 03 | aantal registers, 3 |
74 17 | CRC-16, low byte eerst |
En zo ziet het antwoord eruit:
| Bytes | Betekenis |
|---|---|
01 | serveradres 1 |
03 | dezelfde function code, dus geen fout |
06 | byte count, 6 databytes |
02 2B | eerste register, 555 |
00 00 | tweede register, 0 |
00 64 | derde register, 100 |
05 7A | CRC-16 |
Het getal 40108 komt nergens in dat frame voor. Dat komt doordat er drie tellingen naast elkaar bestaan.
| Blok | Klassiek, 5 cijfers | Datamodelnummer, 1-gebaseerd | PDU-adres, 0-gebaseerd |
|---|---|---|---|
| Coils | 00001 tot 09999 | 1 tot n | 0 tot 65535 |
| Discrete inputs | 10001 tot 19999 | 1 tot n | 0 tot 65535 |
| Input registers | 30001 tot 39999 | 1 tot n | 0 tot 65535 |
| Holding registers | 40001 tot 49999 | 1 tot n | 0 tot 65535 |
De omrekening in drie regels
Nu pas de regel, in drie stappen die je overal kunt toepassen.
- PDU-adres is datamodelnummer min 1. De standaard zegt het zo: een Modbus-gegeven met nummer X wordt in de PDU geadresseerd als X min 1.
- PDU-adres is klassiek nummer min de blok-offset min 1. Voor 40108: haal 40000 eraf, houd 108 over, trek 1 af, en je hebt 107 oftewel
0x006B. - Het blokcijfer zit niet in het bericht. De 4 in 40108 gaat nooit de draad op. De function code zegt al dat het om holding registers gaat.
Trek het blokcijfer eraf, trek er dan nog 1 af.
Nu een tweede voorbeeld dat op precies een punt afwijkt. Datasheetnummer 30009 is een input register, dus je leest het met FC04 in plaats van FC03. De omrekening blijft identiek: 30009 min 30000 is 9, min 1 is PDU-adres 8, hex 0x0008. Het verzoek voor een register wordt dan 01 04 00 08 00 01 B0 08. Alleen de tweede byte verandert, en daarmee het blok.
Hetzelfde adres, vier betekenissen
Omdat het blok uit de function code volgt, wijst 0x0000 vier dingen tegelijk aan. Met FC01 is het de eerste coil (klassiek 00001), met FC02 de eerste discrete input (10001), met FC03 het eerste holding register (40001) en met FC04 het eerste input register (30001). Vier verschillende grootheden, een identiek adresveld in het frame.
Dat verklaart twee dingen die anders willekeurig lijken. Ten eerste: twee tools die met verschillende function codes hetzelfde adres lezen mogen best verschillende waarden tonen, en dat is geen bug. Ten tweede: gebruik je FC03 op een apparaat dat alleen input registers kent, dan krijg je exception 01 als het apparaat FC03 helemaal niet kent, en exception 02 als het de code wel kent maar het holding-blok leeg is. Welke function code welk blok opent, staat volledig in de referentie van de Modbus function codes en komt terug in de les over function codes en exception codes.
Wat jouw tool bedoelt met "address"
Dat verschilt per tool, en het staat zelden op het invoerveld. mbpoll telt standaard vanaf 1 en schakelt met -0 naar de 0-gebaseerde telling. pymodbus, libmodbus en Home Assistant verwachten altijd het PDU-adres, dus 0-gebaseerd: voor 40001 vul je in Home Assistant address: 0 in met input_type: holding. De volledige opzet staat in de uitleg over Home Assistant met Modbus koppelen.
Fabrikanten helpen soms mee. Fronius schrijft in de handleiding dat het uitgezonden registeradres altijd 1 lager is dan het registernummer, en dat je voor register 40001 dus adres 40000 (0x9C40) gebruikt. SolarEdge zet base 0 en base 1 als twee kolommen naast elkaar. Daikin houdt het op drie woorden: "Register Base 0". Zegt je datasheet er niets over, ga dan uit van het klassieke nummer en maak het af met de test hieronder.
Sommige clients nemen die vraag van je over. In de Register Explorer van ModbusCloud Diagnostics staan het protocoladres en het datamodel-adres van hetzelfde register naast elkaar, dus je ziet welke van de twee je invult. De tool is gratis en draait offline; mbpoll blijft de route die op elk systeem werkt.
De test die je twijfel wegneemt
Raden kost meer tijd dan meten. Lees hetzelfde register twee keer: een keer met de telling vanaf 1 en een keer met de telling vanaf 0, en vergelijk de uitkomsten met wat de datasheet op 40001 belooft. Komen ze overeen, dan weet je welke telling jouw tool hanteert en heb je de off-by-one voorgoed uitgesloten. Vul hieronder het nummer uit je eigen datasheet in en lees af wat je per tool moet invoeren.
Registertype
Notatie van je datasheet
- Klassiek, 5 cijfers
- 40001
- Klassiek, 6 cijfers
- 400001
- 1-gebaseerd
- 1
- 0-gebaseerd, decimaal
- 0
- 0-gebaseerd, hex
- 0x0000
- Function code lezen
- 03
- Function code schrijven
- 06, 16
Wat je per tool invult
| Tool | Invoer |
|---|---|
| mbpoll | -t 4 -r 1-0 -t 4 -r 0 |
| QModMaster | Start Address: 0Base Addr 1: 1 |
| Modbus Poll | Address: 0PLC Base 1: 40001 |
| pymodbus | read_holding_registers(0, count=1) |
| Home Assistant | address: 0input_type: holding |
Tools verschillen in hun standaardnotatie. mbpoll telt vanaf 1, pymodbus vanaf 0.
Zit je er precies 1 naast, dan lees je het register ernaast. Dat geeft een plausibel getal en geen foutmelding.
Veelgemaakte fouten
40001 letterlijk invullen. Een tool dat vanaf 1 telt stuurt dan startadres 40000 (0x9C40) de draad op; een tool dat vanaf 0 telt, zoals Home Assistant en pymodbus, stuurt zelfs 40001 (0x9C41). Op de meeste apparaten bestaat dat adres niet en krijg je exception 02. Op een apparaat met veel registers krijg je iets terug wat er plausibel uitziet, en dat is erger. Vul het omgerekende adres in en noteer erbij welke telling je gebruikt hebt.
Alleen het startadres controleren. Exception 02 gaat over startadres plus aantal. Een blokread die net over de rand van het laatste register loopt, faalt volledig terwijl elk register afzonderlijk gewoon leesbaar is. Verklein eerst het aantal, pas daarna het adres.
Het blokcijfer als deel van het adres zien. De 4 in 40001 zit niet in het bericht. Wie hem meestuurt, telt er 40000 bij op. Het blok volgt uit de function code, en daarom betekent PDU-adres 0x0000 vier verschillende dingen.
De 6-cijferige notatie voor de standaard aanzien. 400001 is een industrieconventie en staat niet in de Modbus-standaard. Noem hem gerust in je documentatie, maar reken hem net zo hard om als de 5-cijferige vorm.
Aan de slag
Je voert dezelfde lezing twee keer uit met een andere telling. Als de uitkomsten identiek zijn, heb je het bewijs in handen in plaats van een vermoeden. Dit gaat met mbpoll, dat gratis te gebruiken is, ook zakelijk. De adapter aansluiten en mbpoll instellen komt uitgebreid terug in de les over je eerste apparaat uitlezen; heb je nog geen hardware, dan draai je dezelfde oefening op de simulator uit de les over oefenen met de simulator.
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 1 -c 2 -1 /dev/ttyUSB0
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 0 -c 2 -0 -1 /dev/ttyUSB0
mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 1 -c 2 -0 -1 /dev/ttyUSB0
- 1
Lees met de standaardtelling
Draai het eerste commando. Zonder
-0telt mbpoll vanaf 1, dus-r 1vraagt om het eerste holding register. Op Windows vervang je de poort doorCOM3, op macOS door/dev/cu.usbserial-XXXXXXXX. Noteer de twee waarden. - 2
Lees met de 0-gebaseerde telling
Draai het tweede commando. Met
-0telt mbpoll vanaf nul, dus-r 0wijst naar hetzelfde register. Noteer de twee waarden opnieuw. - 3
Vergelijk de twee uitvoeren
Ze horen identiek te zijn. Dat is je bewijs dat
-r 1zonder-0en-r 0met-0naar hetzelfde register wijzen, en dat het blokcijfer nooit de draad op is gegaan. - 4
Maak de fout expres
Draai het derde commando:
-r 1samen met-0. Nu vraag je PDU-adres 1 op en schuift het hele blok een register op. Dit is precies de fout die je in de praktijk maakt, en je ziet geen enkele foutmelding. - 5
Leg het naast de datasheet
Zoek op wat er volgens de datasheet op 40001 hoort te staan en vergelijk dat met stap 1. Klopt het, dan weet je nu zeker welke telling jouw tool gebruikt. Schrijf dat op bij de installatiegegevens.
Zonder hardware. Start de simulator van pymodbus, die Modbus TCP op poort 5020 aanbiedt, en doe dezelfde drie lezingen tegen 127.0.0.1 in plaats van tegen de seriële poort. pymodbus is ook gratis te gebruiken, ook zakelijk.
pymodbus.simulator --modbus_server server --modbus_device device
mbpoll -m tcp -p 5020 -a 1 -t 4 -r 1 -c 2 -1 127.0.0.1
mbpoll -m tcp -p 5020 -a 1 -t 4 -r 0 -c 2 -0 -1 127.0.0.1
mbpoll -m tcp -p 5020 -a 1 -t 4 -r 1 -c 2 -0 -1 127.0.0.1
Verwacht resultaat: twee identieke uitvoeren, een derde die een register opschuift, en het inzicht dat de tool niets fout deed.
Samenvatting
- Modbus adressering kent drie tellingen naast elkaar: het klassieke datasheetnummer (40108), het 1-gebaseerde datamodelnummer (108) en het 0-gebaseerde PDU-adres dat werkelijk verstuurd wordt (107, hex
0x006B). - Het PDU-adres is altijd het datamodelnummer min 1, en het blokcijfer uit de klassieke notatie gaat nooit mee in het bericht.
- De function code bepaalt het blok, dus
0x0000betekent met FC01, FC02, FC03 en FC04 vier verschillende dingen. - Tools verschillen in hun standaardtelling: mbpoll telt vanaf 1 tenzij je
-0opgeeft, terwijl pymodbus en Home Assistant altijd het PDU-adres verwachten. - Twee lezingen met een verschillende telling die dezelfde waarde opleveren, sluiten de off-by-one uit in dertig seconden.
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.