Node-RED + Modbus RTU over wireless RS-485 bridge – timeout and LoRa duty cycle experience

Hi everyone,

I've been using Node-RED to poll Modbus RTU devices over a wireless RS-485 transparent bridge setup. Sharing some notes in case it helps others doing similar industrial IoT work.

Setup:

  • Node-RED running on a Raspberry Pi
  • node-red-contrib-modbus library (Modbus RTU mode)
  • RS-485 wireless transparent bridge between Node-RED server and field devices
  • RF link: LoRa 920MHz for outdoor runs (~1.5km), WiFi 2.4GHz for indoor
  • Field side: 8 Modbus RTU slaves (energy meters, temperature controllers)

Modbus RTU configuration in Node-RED:
Used the Modbus-Flex-Getter node. Key settings:

  • Serial port: /dev/ttyUSB0 (connected to wireless bridge master unit)
  • Baud rate: 9600, 8-N-1
  • Modbus timeout: bumped from default 1000ms to 2000ms for LoRa link
  • Poll interval: 5 seconds per device

LoRa-specific notes:
LoRa 920MHz adds 100-180ms of round-trip latency at default spreading factor (SF7). The wireless bridge handles retransmission internally, so Node-RED just sees a slightly slower serial port.

The key gotcha: LoRa duty cycle. In dense deployments, if you're polling multiple slaves at high rates, you can saturate the RF channel. I found that 5-second poll intervals with 8 devices kept RF utilization comfortable. With faster polling (1s), I saw occasional Modbus CRC errors which were actually from packet collisions on the RF link.

WiFi mode notes:
For the indoor portions, the bridge supports 2.4GHz WiFi transparent mode. Much lower latency (<20ms), so Modbus timeouts of 500ms work fine. Main issue: WiFi channel congestion in offices -- had to set a fixed channel (ch11 in my case) rather than auto.

MQTT bridge mode:
The bridge also supports a Modbus TCP gateway mode, which lets Node-RED use the Modbus TCP node instead of serial RTU. This worked well for the WiFi link -- set up the bridge as a Modbus TCP slave at 192.168.x.x:502, and Node-RED connects over LAN.

Has anyone else done Modbus RTU over LoRa with Node-RED? Curious what timeout values others use and whether there are other node-red-contrib-modbus settings I should tune.

1 Like

Quick update after running this for a few more weeks — wanted to share some additional findings in case others are experimenting with similar setups.

Spreading factor tuning matters more than I expected

I ended up bumping the LoRa spreading factor from SF7 to SF9 on the longer outdoor runs (~1.2km with partial tree cover). The tradeoff: airtime roughly doubles (about 300-350ms round trip instead of 130-180ms), so I adjusted the Modbus timeout to 3000ms. But link reliability improved significantly — dropped from maybe 2-3% CRC errors down to essentially zero over a 2-week period.

For anyone doing this calculation: at SF9, 868/920MHz with 125kHz bandwidth and a typical 20-byte Modbus RTU frame, you're looking at ~330ms airtime. Stack that with processing and you want at least 2x headroom on the timeout.

node-red-contrib-modbus reconnect behavior

One thing I noticed: if the wireless link drops briefly (RF interference, brief obstruction), the Modbus serial node goes into an error state and doesn't always auto-reconnect cleanly. I added a simple error handler that sends a reconnect command to the Modbus-Client node after 3 consecutive timeouts. Something like:

[Modbus-Flex-Getter] --timeout--> [Function: count errors] --if 3x--> [Modbus-Client: reconnect]

This made the overall system much more resilient for unattended operation.

Poll sequencing

Also switched from parallel polling (inject nodes all firing at 5s intervals independently) to a queued sequential approach using node-red-contrib-modbus's built-in queue mode. This eliminates the scenario where multiple poll requests arrive at the bridge simultaneously and collide on the RF channel. CPU load on the Pi actually went down a bit too.

Hope this is useful for anyone building out similar industrial wireless setups. Happy to share the flow JSON if there's interest.

2 Likes