In this lesson

What this lesson covers

  • Connecting the USB to RS485 adapter and finding the port name
  • The mbpoll command line, argument by argument
  • A check after each step, and back to volts or amps

Read first: How to read a Modbus datasheet, step by step, RS485 explained: A, B, common and termination, Baud rate and parity: why 8E1 is the default

Reading a Modbus device comes down to one command whose arguments are the four facts from the datasheet plus the port your adapter turned up on. Everything from the first eight lessons meets here, in a procedure that takes about half an hour on a cold panel. After this lesson you can go from an unopened cabinet to a register value in a real unit, with a check after each step that rules out exactly one source of error.

What you need before you start

A USB to RS485 adapter, a length of shielded twisted pair with a third conductor for the common, a device with power on it, and four facts off the datasheet. Without those four you are guessing, because the Modbus RTU transport negotiates none of them for you.

FactTypical valueWhere it bites
Server address1 to 247, default usually 10 is broadcast, 248 to 255 reserved
Baud rate9600 or 19200the only two the standard makes mandatory
Parity and stop bitsnone or even, 1 stop bitspec default is 19200 with even parity, devices often ship on something else
Register and function codeholding register 1 in datasheet numberinginput registers need FC04, holding registers FC03

An Eastron SDM630 energy meter ships on 9600 baud, no parity, one stop bit, address 1. Try that first on anything unknown. Getting the four facts off a datasheet is reading a Modbus register map; if the address is unknown, scanning a Modbus network is faster.

Connecting the adapter and finding the port

Your adapter turns up as a serial port, and the name depends on the operating system.

SystemPort nameHow to find it
Linux/dev/ttyUSB0ls /dev/ttyUSB* before and after plugging in
WindowsCOM3Device Manager, under Ports (COM and LPT)
macOS/dev/cu.usbserial-XXXXXXXXls /dev/cu.*

On macOS the same adapter appears twice, as tty.* and as cu.*. Use cu.*: the tty.* variant waits for a carrier detect that an RS485 adapter never produces, so the command sits there looking like a dead bus.

You wire three conductors, not two: D0, D1 and the common. Leaving the common out is a classic source of intermittent faults, as RS485 explained covers.

The first command, argument by argument

Here is the whole thing: two holding registers from server 1, at 9600 baud with no parity.

mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 1 -c 2 -1 /dev/ttyUSB0
ArgumentWhat it does
-m rtuModbus RTU over a serial port
-a 1server address 1
-b 9600baud rate 9600
-P noneno parity
-t 4holding registers, FC03 on the wire
-r 1start at register 1 in datasheet numbering
-c 2read two registers
-1poll once and stop
/dev/ttyUSB0the serial port

Change one argument and you cover the other common case. The measurements on an SDM630 sit in input registers, so -t 4 becomes -t 3, which puts FC04 on the wire instead of FC03. Grid frequency has PDU address 0x0046, decimal 70, so in the 1-based counting mbpoll uses that is -r 71.

mbpoll -m rtu -a 1 -b 9600 -P none -t 3 -r 71 -c 2 -1 /dev/ttyUSB0

Eastron requires an even number of registers per request on this meter, so -c 2 here is a condition and not a choice.

If you would rather have a window than a command line, the Register Explorer in ModbusCloud Diagnostics does the same read with fields for server address, port and register. This lesson stays on mbpoll, because the arguments show you exactly what goes out on the wire.

What you see when it works

Numbers, and a small statistic underneath them. mbpoll echoes the settings it will use, prints each register it read with its number in front, and on exit reports how many frames it sent and how many came back.

That statistic is the instrument you lean on in the next lesson: frames transmitted counts what went out, received what came back, and the gap between them is most of the diagnosis. Two values on screen prove the wiring, the baud rate, the parity, the address and the register in one go. Keep the request small while testing: FC03 and FC04 allow up to 125 registers, but many devices set a lower limit.

What you see when it does not

One of three pictures, and each points at a different part of the chain.

What you seeWhat it meansWhere to look
Silence, then a timeoutThe frame never arrived, or was dropped unreadWiring, baud rate, parity, address
An exception responseThe frame arrived intact and was refusedFunction code, register address, quantity
A value, but the wrong oneCommunication is fine, interpretation is notData type, word order, scaling factor

A response timeout of one second up to several seconds is normal at 9600 baud, so give the tool a moment. If you do not know the serial settings at all, sweep baud rate against framing and stop at the first combination that answers.

Finding unknown serial settings8N18E18O1115200384001920096002400Data bits, parity, stop bitsBaud rateValid CRC
Work through the combinations in a fixed order, changing one thing at a time, until one of them returns a frame with a valid CRC.

Working through the three in order is what Modbus RTU troubleshooting does next.

From register value to real unit

A register is 16 bits, so the number on your screen means whatever the datasheet says it means. An SMA inverter follows SunSpec and puts grid frequency in register 40202 as an integer, with the power of ten sitting in a scale register next to it. That scale register holds -2, so a raw 5001 is 5001 times 10 to the power -2, which is 50.01 Hz.

The same mechanism runs the other way. The same inverter publishes DC power with a scale factor of 2, so a raw value of 57 is 57 times 10 to the power 2, which is 5700 W and not 57 W.

An SDM630 solves it differently. Grid frequency arrives as an IEEE 754 float32 across two input registers, most significant register first. Read 42 48 in the first and 00 00 in the second, put them in that order, and the float is exactly 50.0 Hz. Swap the two registers and the number stops resembling a grid frequency at all. Why the same four bytes can yield four different numbers is worked out later in the course, in the lesson on word order and floats.

Then run the plausibility check. Mains voltage belongs roughly between 207 and 253 V, which is 230 V plus or minus 10 percent under EN 50160, and grid frequency sits around 50 Hz. A raw 5001 in a frequency field flags a missing factor instantly.

What to record before you close the panel

Four lines on a label at the terminal block, written the moment the reading works: baud rate, parity with stop bits, the server address, and which registers you read with which function code. The next engineer then skips the sweep you just did.

Once mbpoll reads the register, any other client will. That is the right order for connecting Modbus to Home Assistant too: prove the register on the command line, then write the configuration.

Common mistakes

Not knowing the tool's defaults. mbpoll starts from Modbus TCP at 19200 baud with even parity. Leave out -m rtu and you get a connection error that has nothing to do with the bus, after which people swap wires that were fine.

Choosing the tty.* port on macOS. The command looks hung, because it is waiting for a carrier detect that never comes. Use the cu.* name for the same adapter and it works.

Polling without -1 and assuming it crashed. Without that flag mbpoll keeps polling until you press Ctrl-C. That is the documented default, and the running counter is useful while you wiggle a terminal.

Changing several things at once. Swap the data pair, change the parity and try another address in one go, and you learn nothing from either outcome. One change, one attempt, one note.

Get hands-on

Eight steps, each with a check that rules out exactly one source of error.

  1. 1

    Install mbpoll

    Debian and Ubuntu: sudo apt install mbpoll. macOS: brew install mbpoll. Check: mbpoll --help prints the help text.

  2. 2

    Plug in the adapter

    Check: the port appears, via ls /dev/ttyUSB* or under Ports in Device Manager.

  3. 3

    Wire D0, D1 and the common

    Check: measure the idle voltage across D0 and D1. D1 should sit positive, as RS485 explained describes.

  4. 4

    Look up the four facts

    Address, baud rate, parity with stop bits, register with function code. Check: you can write all four down.

  5. 5

    Read two registers

    Run the command below. Check: two numbers come back.

  6. 6

    If nothing comes back, change one thing

    Address first, then parity, then baud rate, then swap the data pair. Check: note what you changed each time.

  7. 7

    Convert the value to its unit

    Apply the scaling factor from the datasheet. Check: the order of magnitude is what you expected.

  8. 8

    Label the terminal block

    Check: someone else can read this device without phoning you.

mbpoll -m rtu -a 1 -b 9600 -P none -t 4 -r 1 -c 2 -1 /dev/ttyUSB0

Fill this in for your own device first:

server address ......  ____
baud rate ...........  ____
parity, stop bits ...  ____
register + FC .......  ____

raw value ____  x 10^____  =  ____   unit: ____

No hardware. Install the simulator with python -m pip install "pymodbus[serial,simulator]==3.15.0" and start it with pymodbus.simulator --modbus_server server --modbus_device device. It listens on port 5020, so you need no root rights. Replace the serial arguments with -m tcp -p 5020 127.0.0.1 and take the same steps, without steps 2, 3 and 8.

mbpoll -m tcp -p 5020 -a 1 -t 4 -r 3 -c 1 -0 -1 127.0.0.1

The -0 switch makes mbpoll count from zero, so -r 3 is PDU address 3. The bundled dataset is built so you can practise all three pictures: PDU address 3 holds 17001 and returns it unchanged on every read, the float32 across PDU addresses 6 and 7 starts at 404.17 and climbs each time you ask, and PDU address 1 is configured as invalid and answers with a real exception. pymodbus is BSD-3 licensed and free to use, including commercially. On Linux and macOS, socat gives you a virtual serial pair so you can walk the RTU route end to end.

Expected result: two register values on screen, converted into a plausible unit, and a label on the panel.

Summary

  • Reading a Modbus device needs four facts from the datasheet: server address, baud rate, parity with stop bits, and the register with its function code.
  • mbpoll defaults to Modbus TCP at 19200 baud with even parity, so pass -m rtu, -b and -P explicitly rather than trusting the defaults.
  • One value on screen proves the wiring, the serial parameters, the address and the register at once.
  • Silence points at the physical layer or the address, an exception points at the request, and a wrong number points at the data type or the scaling factor.
  • Change one thing per attempt and note what you changed, because a fix you cannot reproduce is not a fix.

Check yourself

Four questions about this lesson. Every answer comes with an explanation.

Question 1 of 4
You run mbpoll -a 1 -b 9600 -t 4 -r 1 /dev/ttyUSB0 and get a connection error straight away, without anything happening on the bus. What is the cause?
You read two registers with -t 4 -r 1 -c 2 and get two believable numbers, but both are about a factor 10 too low. What is the most likely cause?
Why do you read every device on its own before you daisy chain the whole bus together?
The poll statistic on exit says frames transmitted 20, received 0. What does that tell you?

Stuck on a project?

Describe what you see and where it goes wrong. We will look at it and tell you what we would do.

Further reading in the knowledge base