Skip to content

Modbus Serial RTU master mode, Timeouts and Buffers - with solution #385

@vk2tds

Description

@vk2tds

I have been working on code on the STM32 using stm32duino and PlatformIO, however my observations are likely similar on other platforms. I was reading INPUT REGISTERS and getting timeouts. Doing analysis using my BusPirate I saw that the data was being sent correctly in return but was still timing out.

After a heap of debugging I came across two use cases, one of which times out, and the other worked. When I requested 32 input registers as a master, the call timed out. When I requested 28 input registers things worked. Choosing these two values was not a coincidence. With header and CRC, these two use cases would put the packet under and over 64 bytes in length.

Checking ModbusRTU.cpp, the task() code is rather elegant. It uses the Stream.available() function along with its return value. More importantly, it does not even read any bytes from the serial buffer until there is an inter-character timeout. This makes the code elegant and non-blocking.

The only issue is that this only works when the receive packet will fit entirely within the receive buffer. Under many Arduino platforms, the serial transmit and receive buffers are set at 64 bytes. Hence, this is why requesting 28 Input Registers worked, and 32 did not.

The fix is actually quite simple, and does not require any changes to code. Adding the following to the build_flags in platformio.ini fixes the issue, at least for return values up to about 60ish Input Registers. For those not using PlatformIO, you can just use a #define in an appropriate location.

-D SERIAL_RX_BUFFER_SIZE=128

In my case, this allowed my code requesting 42 input registers to run without issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions