ArduinoModbus icon indicating copy to clipboard operation
ArduinoModbus copied to clipboard

Larger reads sometimes time out at slower baud rates on RP2040

Open pomplesiegel opened this issue 2 years ago • 10 comments

Hello! I am successfully using this library to implement a sensor device with 24 holding registers which can be read. This all works beautifully at higher baud rates. However, at 9600 baud it times out quite often (about 1/4 of requests).

To be clear, this sometimes times out when reading 24 registers in a single request. However it functions fine at higher baud rates such as 115200.

Device: Adafruit RP2040 Feather Baud: 9600

MVP device code to replicate issue:

#include <Arduino.h>
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include <ArduinoModbus.h>

void setup() 
{
  Serial.begin(115200);

  //slave id 1
  if ( !ModbusRTUServer.begin(1,9600) )
  {
    Serial.println("Failed to start Modbus RTU Server!");
    while (1);
  }

  // configure 24 registers, starting at address 1
  ModbusRTUServer.configureHoldingRegisters(1,24); 
}

void loop() 
{
  // poll for Modbus RTU requests
  if (ModbusRTUServer.poll() )
  {
    Serial.println("Received request!"); 
  }
}

RS485.h timing mod for things to work on RP2040:

#define RS485_DEFAULT_PRE_DELAY 100
#define RS485_DEFAULT_POST_DELAY 5000

BTW: I can replicate the issue when reading fewer registers at once, but it is much easier to replicate when performing larger requests (reading multiple registers).

Looking forward to your thoughts! Thank you, Michael

pomplesiegel avatar Oct 08 '23 20:10 pomplesiegel

Hi @facchinm and @aentinger, I hope you're both doing well! Have either of you seen this in your usage with the library at slower baud rates?

pomplesiegel avatar Oct 12 '23 14:10 pomplesiegel

Unfortunately not using this library at all. Sounds like a timeout?

aentinger avatar Oct 13 '23 03:10 aentinger

Hi @aentinger, thanks for the message! Yes, indeed it's a timeout, but it's not clear why this is happening about 1/4 of the time. The device is available and just sitting there, but there is some issue preventing it from seeing all of the modbus requests when running at certain baud rates.

Any ideas? Thank you!

pomplesiegel avatar Oct 13 '23 22:10 pomplesiegel

Nope, sorry, no ideas. I've looked for obvious timeouts in the code myself, but didn't see any. If you find a bug, please consider sending a PR to fix it 🙏 .

aentinger avatar Oct 16 '23 04:10 aentinger

OK, I'll keep looking into it! Is anyone else able to quickly test / replicate the MVP code above? I think that may help clarify what is going on causing this issue. Thank you!

pomplesiegel avatar Oct 16 '23 09:10 pomplesiegel

Anyone else experiencing timeouts on at these lower baud rates on other hardware? RP2040 it is definitely happening.

pomplesiegel avatar Nov 10 '23 21:11 pomplesiegel

Just checked and with the latest release this (MVP example code above) is still easily replicable with baud rates 9600 and 19200. Anyone else seeing this on RP2040 or other hardware?

@martinez20m your assistance as so helpful on the last issue! Would you be open to testing this on your device to see if you replicate this as well?

pomplesiegel avatar Dec 02 '23 02:12 pomplesiegel

Just tested and I'm seeing many other time-out issues at various baud rates on boards such as the ATSAMD21G18 (Adafruit Metro Express). Anyone else seeing this too?

pomplesiegel avatar Dec 18 '23 21:12 pomplesiegel

@per1234, would you be open to testing this on your side? I have found it is quite easy to replicate on the two sets of hardware I have here, and this would represent a large issue for many people using the library.

pomplesiegel avatar Dec 19 '23 15:12 pomplesiegel

OK! I have found a solution which allows stable operation on the RP2040:

I exposed the libmodbus's flush command via https://github.com/arduino-libraries/ArduinoModbus/pull/133 and call this after each poll, so loop() now looks like:

void loop() 
{
  // poll for Modbus RTU requests
  if (ModbusRTUServer.poll() )
  {
    Serial.println("Received request!"); 
    ModbusRTUServer.flush(); //necessary at lower baud rates
  }
}

Finally, the RS485.h timing needs to be

#define RS485_DEFAULT_PRE_DELAY 100
#define RS485_DEFAULT_POST_DELAY 10000

Both of these changes are necessary for stable operation with large reads. On my side things are now running stable between 9600 and 115200 baud, even with reads as large as 100 bytes.

I'm not sure what the end goal should be here in terms of integrated platform support, but FYI between my PR and the timing changes above this is finally working for me.

pomplesiegel avatar Dec 19 '23 20:12 pomplesiegel