In deze les

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.

BlokGrootteToegangFunction codesCoils0xxxx1 bitlezen en schrijven01 / 05, 15Discrete inputs1xxxx1 bitalleen lezen02Input registers3xxxx16 bitalleen lezen04Holding registers4xxxx16 bitlezen en schrijven03 / 06, 16
Vier blokken, twee groottes, twee toegangsrechten. De function code kiest het blok.

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.

BytesBetekenis
01serveradres 1
03FC03, lees holding registers
00 6Bstartadres, PDU-adres 107
00 03aantal registers, 3
74 17CRC-16, low byte eerst

En zo ziet het antwoord eruit:

BytesBetekenis
01serveradres 1
03dezelfde function code, dus geen fout
06byte count, 6 databytes
02 2Beerste register, 555
00 00tweede register, 0
00 64derde register, 100
05 7ACRC-16

Het getal 40108 komt nergens in dat frame voor. Dat komt doordat er drie tellingen naast elkaar bestaan.

BlokKlassiek, 5 cijfersDatamodelnummer, 1-gebaseerdPDU-adres, 0-gebaseerd
Coils00001 tot 099991 tot n0 tot 65535
Discrete inputs10001 tot 199991 tot n0 tot 65535
Input registers30001 tot 399991 tot n0 tot 65535
Holding registers40001 tot 499991 tot n0 tot 65535

De omrekening in drie regels

Nu pas de regel, in drie stappen die je overal kunt toepassen.

  1. 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.
  2. 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.
  3. 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.
40001Datasheet, klassieke notatie0x0000Adres op de draad (PDU)400010x0000400020x0001400030x0002401000x0063499990x270E401080x006B

Trek het blokcijfer eraf, trek er dan nog 1 af.

40001 gaat als 0x0000 over de draad, 40108 als 0x006B. Altijd een lager.

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

ToolInvoer
mbpoll-t 4 -r 1-0 -t 4 -r 0
QModMasterStart Address: 0Base Addr 1: 1
Modbus PollAddress: 0PLC Base 1: 40001
pymodbusread_holding_registers(0, count=1)
Home Assistantaddress: 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.

Typ het adres over uit je datasheet en lees af wat je in jouw tool invult.

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. 1

    Lees met de standaardtelling

    Draai het eerste commando. Zonder -0 telt mbpoll vanaf 1, dus -r 1 vraagt om het eerste holding register. Op Windows vervang je de poort door COM3, op macOS door /dev/cu.usbserial-XXXXXXXX. Noteer de twee waarden.

  2. 2

    Lees met de 0-gebaseerde telling

    Draai het tweede commando. Met -0 telt mbpoll vanaf nul, dus -r 0 wijst naar hetzelfde register. Noteer de twee waarden opnieuw.

  3. 3

    Vergelijk de twee uitvoeren

    Ze horen identiek te zijn. Dat is je bewijs dat -r 1 zonder -0 en -r 0 met -0 naar hetzelfde register wijzen, en dat het blokcijfer nooit de draad op is gegaan.

  4. 4

    Maak de fout expres

    Draai het derde commando: -r 1 samen 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. 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 0x0000 betekent met FC01, FC02, FC03 en FC04 vier verschillende dingen.
  • Tools verschillen in hun standaardtelling: mbpoll telt vanaf 1 tenzij je -0 opgeeft, 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
Je datasheet zegt: "40108, Actief vermogen totaal". Welk startadres staat er in het frame dat je apparaat ontvangt?
Een tool leest met FC03 vanaf startadres 0x0000. Een tweede tool leest op hetzelfde apparaat met FC04 vanaf startadres 0x0000. Wat kun je hierover zeggen?
Je leest een meter uit met Home Assistant. De datasheet zegt dat de netspanning op 40001 staat. Je vult address 40001 in en de sensor blijft leeg. Wat is de eerste ingreep?
Waarom kan hetzelfde PDU-adres 0x0000 vier verschillende dingen betekenen?

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