In this lesson

What this lesson covers

  • Three routes for the same data: PLC, Home Assistant or cloud
  • The five facts every route asks for: block, numbering, type, word order, scale
  • An alerting rule that only fires after three failed polls

Read first: Practise Modbus TCP with a free simulator, rtuovertcp explained: what a gateway does to your frame, Word order and floats: same bytes, other value

Modbus integration is not learning the protocol a second time, it is deciding where the data goes and who maintains it afterwards. A PLC, Home Assistant and a cloud platform read exactly the same register from exactly the same device, and still all three ask something different of you. After this lesson you can compare the three routes, fill in the same five facts on whichever one you pick, and write an alerting rule that does not fire on a single hiccup.

Three routes for the same data

Take total system power from an Eastron SDM630 energy meter: input registers, FC04, two registers because it is a 32-bit float. Datasheet number 30053 is PDU address 52, hexadecimal 0x0034. This is the complete RTU request to server address 1, byte for byte.

ByteValueMeaning
101server address 1 on the RS485 bus
204FC04, read input registers
3 to 400 34start address 0x0034, PDU address 52 (datasheet number 30053)
5 to 600 02number of registers: 2
7 to 830 05CRC-16, low byte first (value 0x0530)

And the reply, nine bytes long.

ByteValueMeaning
101the same server address
204the same function code, so no exception
304byte count: 4 data bytes follow
4 to 744 9A 50 00float32, most significant register first: 1234.5 W
8 to 9F3 5BCRC-16 over the reply (value 0x5BF3)

That is the rule of this lesson: the five PDU bytes 04 00 34 00 02 are identical on every route. Only the envelope changes: a server address plus CRC-16 on RTU, a seven byte MBAP header with a unit id on TCP, and above all who maintains the translation from 44 9A 50 00 into 1234.5 W. Behind an RTU to TCP gateway the RTU frame including its CRC even travels on unchanged inside the TCP connection.

What each route asks of you

Technically they do the same thing. The difference is maintenance: who keeps the register map current, and who gets the call at three in the morning.

RoutesModbus deviceMeter, inverter, heat pumpDestinationControl, dashboard, alarm1PLC or SCADAbuilt in2Protocol bridge to the BMSBACnet, KNX3Home AssistantYAML4Modbus to MQTTMQTT5Cloud platformoutbound TLS
1
PLC or SCADA. The controller speaks Modbus itself and acts on the value. Short control loop, but you need the programming environment and the licence of that brand.
2
Protocol bridge to the BMS. Registers become objects or datapoints in the building management system that is already there. Two translation tables to maintain instead of one.
3
Home Assistant. Free and quick to set up, suited to homes and small buildings. You are the one who owns the server, the backup and the updates afterwards.
4
Modbus to MQTT. The gateway polls and publishes to a broker. Useful when the destination is an IoT platform, but you build the data modelling yourself.
5
Cloud platform. The gateway polls locally and opens the connection outwards. No inbound port and no server of your own, but a subscription and a vendor.
The same registers, five possible destinations. The choice sits in maintenance, not in the protocol.
AspectPLC or SCADAHome AssistantCloud platform
Knowledge neededthe vendor programming environmentYAML and Linuxreading a register map
Maintained afterwards byyour programmer, under contractyou, usually without a contractthe vendor, while the contract runs
Works with the internet downyesyespolling continues, sending waits
Handed over throughthe project filesonly to someone with the same knowledgean account

For a home or a small building the Home Assistant Modbus integration is a short path to the first reading. If a building management system is already in place, the question belongs with Modbus in home and building automation. If you have to reach twenty sites from an office, it becomes remote monitoring through the cloud, with the ModbusCloud Gateway or another gateway that connects outbound by itself.

From register to usable measurement

Every route needs the same five facts. Skip one and you get no error message, you get a wrong number. Two devices side by side show why none of them is optional.

FactEastron SDM630, total system powerNIBE S-series, outdoor sensor BT1
Block and function codeinput registers, FC04input registers, FC04
Numberingdatasheet number 30053, PDU address 52input register 1
Data typefloat32 across two registerssigned 16 bit, one register
Word ordermost significant register first, so ABCDnot applicable on a single register
Scaling factornone, the value is already in Wdivide by 10, a raw -47 is -4.7 degrees

The rule behind it is short: these are properties of the device, not of the destination. Move from a PLC to a dashboard and only the place where you type them changes. They differ per manufacturer: NIBE divides temperatures by 10, Daikin by 100, and swapping the divisor puts you out by exactly a factor of ten. Read as an int16, 0x449A yields 17562, which looks like a plausible power reading. The four word order variants live in the lesson on data types and word order.

A minimal home automation configuration

This is everything Home Assistant needs to read the meter from the example above.

modbus:
  - type: rtuovertcp
    host: 192.168.1.50
    port: 502
    sensors:
      - name: Total power
        device_address: 1
        address: 52
        input_type: input
        data_type: float32

Four fields carry the lesson. type is the connection type: rtuovertcp because an RS485 to ethernet gateway sits in between, tcp for a device with its own ethernet port. device_address is the server address on the bus, which behind a gateway also ends up in the unit id of the MBAP header. address is 0-based and goes into the frame unchanged as the PDU start address, so 52 and not 30053. input_type: input picks the block, and data_type: float32 glues the two registers together. If the word order is reversed, swap: word joins them.

tcpnative Modbus TCPHAhubPV inverterEthernetPort 502
For devices with their own ethernet port that speak Modbus TCP themselves, such as most modern solar inverters.
rtuovertcpRTU frames inside a TCP streamHAhubRS485 forwarderEthernetPort 502 (RTU framer)
For serial gateways that forward the RTU frame unchanged. You recognise it by the CRC at the end of the reply.
serialstraight onto RS485HAhubUSB-RS485A/B/GND/dev/ttyUSB0
For a USB to RS485 adapter on the machine running Home Assistant. You supply the port, the baud rate and the parity.
Choose the wrong connection type and you get timeouts, not an error message. tcp and rtuovertcp look alike, but the frame on the wire is different.

The full configuration with sensors, switches and hub options lives in the guide to the Home Assistant Modbus integration.

How often do you read what?

The interval belongs to how fast the quantity moves, not to the project. Measure your cycle time, meaning how long one round past all devices takes, and divide it by the poll interval: that is your bus load. The rule of thumb of this course is to stay under 50 percent, so make the interval at least twice the cycle time. On the worked bus of ten meters at 9600 baud a cycle takes 0.98 seconds. A 1 second interval is then 97.9 percent, 5 seconds is 19.6 percent, 10 seconds is 9.8 percent and 60 seconds is 1.6 percent.

Class of deviceIntervalWhy
SMA inverter10 s or slowerSMA asks for at least ten seconds between two transfers
kWh meter10 s9.8 percent bus load, ample for energy monitoring
Heat pump and BMS60 s1.6 percent bus load, and the flow temperature moves slower anyway
NIBE S-seriescheck the register budget100 registers per second allowed, 60 registers per second is already 60 percent

Two side conditions come with it. SolarEdge closes an idle TCP connection after 2 minutes, so the interval has to stay under that to keep the session open. And behind a gateway the serial sum still applies in full: the ethernet side is fast, the bus behind it still runs at 9600 baud. The complete sum lives in the lesson on poll intervals and bus load.

Alerting without false alarms

A corrupted frame produces no exception but silence, and therefore a timeout. On a long bus that happens now and then with nothing being wrong. So raise an offline alarm only after three consecutive failed polling rounds.

Poll 1OKPoll 2FailedPoll 3FailedPoll 4FailedOffline alarmThree consecutive misses
Never alarm on a single failed poll. On a busy bus one lone timeout is normal.

Three rules keep the night quiet. First, keep "device does not answer" separate from "value out of range", because the first usually explains the second. Second, use a hysteresis pair on thresholds: alarm above 70 degrees and clear below 65. Count on 5 to 10 percent of the threshold; without that gap a value sitting on the limit crosses it dozens of times an hour. Third, let the client skip a dead device after three failed rounds, otherwise it waits out the full timeout every round.

That last one is measurable. One dead device stretches a cycle of 0.98 seconds to 1.88 seconds at a 1 second timeout, and to 3.88 seconds once the client waits out three full timeouts. The guide to automated Modbus alerts works both patterns out.

What you document for the next technician

The installation works now, and in two years someone else is standing there. Record per device: brand and model, server address or unit id, connection type, and per measurement the block, the address in both numberings, the data type, the word order and the scaling factor. Add the poll interval with its reason, and every alarm threshold with its clearing value. The reason is the part everyone leaves out and nobody can reconstruct later: 10 seconds looks arbitrary until it says next to it that the manufacturer does not want to be polled faster.

That is exactly what a preconfigured register map from a template library saves you, and exactly what is missing when someone configured by hand without notes. Check such a map once against the datasheet of your firmware version anyway. Turning this list into a handover checklist is the next lesson.

Common mistakes

Starting in the YAML or the dashboard. You fill in a configuration, the sensor stays empty, and you go hunting for a protocol fault inside a text file. Prove with a command line tool that the register reads first. Only then do you know an empty sensor is down to the configuration.

Filling in tcp where rtuovertcp is needed. Behind an RS485 to ethernet gateway this is a common reason a sensor stays empty. The TCP connection is established, port 502 is open, and still no answer ever comes back. The lesson on choosing between RTU and TCP shows the difference in bytes.

Copying deprecated field names out of an old forum post. In Home Assistant the field is device_address, not slave, and the data types are int16 and float32, not int and float. A deprecated name is ignored or rejected at restart, and the message about it sits in the log you did not have open.

Alarming on a single failed poll. You get notifications when nothing is wrong, and after a week someone switches the whole alerting off. Count three consecutive failures before you report, and keep "does not answer" separate from "value out of range".

Get hands-on

You connect one device to one system and check the value with a second method. Both mbpoll and the pymodbus simulator are free to use, including commercially.

  1. 1

    Prove the register reads first

    Read the value with a command line tool, separate from your system. For a float32 from PDU address 52 at server address 1:

    mbpoll -m rtu -a 1 -b 9600 -P none -t 3:float -r 52 -c 1 -0 -1 /dev/ttyUSB0
    
  2. 2

    Write down the five facts

    Block, numbering, data type, word order and scaling factor. Note the sentinel values as well if the manufacturer publishes them. That note is your only handhold later when a value looks wrong.

  3. 3

    Add the device with a minimal configuration

    Host, port, connection type, unit id, register address, data type and interval only. No naming, no icons, no second sensor.

  4. 4

    Restart and look the value up

    Open the status view of your system and find the new entity. If it stays empty, the cause is in step 3 and not in the connection, because step 1 succeeded.

  5. 5

    Compare the two readings

    If the number differs from step 1, walk the five facts. A factor of 10 or 100 points at the scaling factor, an absurdly large one at the word order.

  6. 6

    Set the alerting rule

    Let the notification fire only after three consecutive failed polling rounds, and give every threshold a clearing value that sits well below it.

No hardware to hand. Start the pymodbus simulator and point your system at 127.0.0.1:5020 with connection type tcp. Every step except the first works identically.

Expected result: one value that reads the same in two independent tools, and an alarm that stays quiet through a single missed poll.

What you record about this route for the next engineer is the subject of the final lesson, the commissioning checklist and handover.

Summary

  • The PDU does not change per destination: every route sends the same 04 00 34 00 02 and gets the same 04 04 44 9A 50 00 back, only the envelope differs.
  • The three routes differ in maintenance and not in technology, so choose on who keeps the register map and who gets the night call.
  • Block, numbering, data type, word order and scaling factor are properties of the device, so every route needs all five.
  • In Home Assistant address counts from 0, so datasheet number 30053 becomes 52, and behind a gateway the connection type is rtuovertcp rather than tcp.
  • Match the poll interval to how fast the quantity moves and keep bus load under 50 percent: at a cycle of 0.98 seconds, 10 seconds is 9.8 percent.
  • Report a device offline only after three consecutive failed polling rounds and give every threshold a clearing value, otherwise you are alarming on noise.

Check yourself

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

Question 1 of 4
Your new sensor stays empty, while mbpoll reads the very same register from the very same device without trouble. Where do you look first?
Why is `scan_interval: 1` usually a poor choice for a heat pump?
You raise an offline alarm as soon as one poll fails. What happens on a long RS485 bus?
Which of the five facts (block, numbering, data type, word order, scaling factor) can you leave out when you connect a device to a cloud platform instead of to a PLC?

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