4-20ma / ModbusMaster

Enlighten your Arduino to be a Modbus master
http://4-20ma.io/ModbusMaster/
Apache License 2.0
609 stars 354 forks source link

Write Single register to a slave - 226 Timeout error #149

Open rtu-dataframe opened 4 years ago

rtu-dataframe commented 4 years ago

Hi,

I'm using this wonderful library on arduino in order to make it as a Modbus Slave, the slave consists in a ATMEGA328P with a bunch of neopixel leds (8) attached, periodically - every 250ms - , the master (Library: ModbusMaster) will change the led colors, generating some random colors.

The speed is: 57600-8E1

I was experiencing very often a slave timeout on the master (226 error), even if the master timeout limit is not reached (2000ms).

After some experiments, i've found that if i add to the slave a small delay(10) at the end of the write register function, the problem almost disappears (the timeout errors will appear very few times, like one every 100 writes)

This is weird, i mean: is this a normal behavior? i need to slow down the response of my slave in order to get it work?

immagine

t6Jay commented 4 years ago

I had a similar problem, caused by the arduino switching back to RX mode before the last byte has actually left the port, an incomplete frame is then received at the partner.

This problem occurred on a Nano33BLE, but not on a Leonardo.

My guess is that the Nano33BLE is faster than the Leo, but the two byte streams are the same speed, so the Nano switches the TX mode off too soon.

On Fri, 30 Oct 2020 at 17:00, Simone Fardella notifications@github.com wrote:

Hi,

I'm using this wonderful library https://github.com/yaacov/ArduinoModbusSlave on an arduino in order to make it as a Modbus Slave, the slave consists in a ATMEGA328P with a bunch of neopixel leds (8) attached, periodically - every 250ms - , the master (Library: ModbusMaster https://github.com/4-20ma/ModbusMaster) will change the led colors, generating some random colors.

The speed is: 57600-8E1

I was experiencing very often a slave timeout on the master (226 error), even if the timeout limit is not reached (2000ms).

After some experiments, i've found that if i add to the slave a small delay(10) at the end of the write register function, the problem almost disappears (the timeout errors will appear very few times, like one every 100 writes)

This is weird, i mean: is this a normal behavior? i need to slow down the response of my slave in order to get it work?

[image: immagine] https://user-images.githubusercontent.com/5062855/97734367-5e76c700-1ad9-11eb-9809-a6b618656c90.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/4-20ma/ModbusMaster/issues/149, or unsubscribe https://github.com/notifications/unsubscribe-auth/APTO6DPUO543QZODSG7W2SLSNLWK5ANCNFSM4TFGTTFQ .

rtu-dataframe commented 4 years ago

@t6Jay, so, how you managed to solve that?

t6Jay commented 4 years ago

Well, I botched it, I saw that the message frame was one byte short, so I increased the loop counter, now an extra byte must be sent out at the port but it will never reach the data lines.

The increased time for the byte squirt must be enough to keep the TX on for long enough, as the comms works fine now.

Your solution looks better to me, but I guess an ideal fix would be to 'detect' when the UART is finished before resuming RX. I have no Idea if this is possible though, I'm an Arduino noob.

On Fri, 30 Oct 2020 at 18:12, Simone Fardella notifications@github.com wrote:

@t6Jay https://github.com/t6Jay, so, how you managed to solve that?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/4-20ma/ModbusMaster/issues/149#issuecomment-719715810, or unsubscribe https://github.com/notifications/unsubscribe-auth/APTO6DJHHUYHHUHUHREI55TSNL6ZTANCNFSM4TFGTTFQ .

t6Jay commented 4 years ago

See thread #93 for more ideas

rtu-dataframe commented 4 years ago

Thanks, I saw, and actually i've implemented the T3.5 and T1.5 as reported from @yet-another-average-joe in the #126 but nothing changes...without implementing the delay (at slave side) the issue continues to be there

thetintin1000 commented 3 years ago

Hi, I got the same problem with single SDM630 slave, tried 2 different RS485 shields, the response was detected but always returning 226. It's definitely because of available the time to get the response back that is not handle by the library when the baudrate is to low. I changed the baudrate on the slave and the controler : not working for baudrate 19200 and under, working for baudrate 38400 and upper. So if you have access to the baudrate, no need for modification in the library.

rtu-dataframe commented 3 years ago

Thanks, as you know, there is another library that has not this problem? or you're using this one?

thetintin1000 commented 3 years ago

I m using this one, as it's easy to change the baudrate on the slave (the SDM) and I'm using a ATMEGA328P processor based card as master with the SerialSoftware library to set serial communication with same baudrate. I found other libraries, but now using this one as it's working. Should look at the baudrate available for other libraries.

rtu-dataframe commented 3 years ago

I agree with you, in any case, this library is the only that works decently, maybe it will be better if someone will publish a new version/branch that implements a better timing for master awaiting response from slave

yet-another-average-joe commented 3 years ago

Just test this one : https://github.com/yet-another-average-joe/YAAJ_ModbusMaster

rtu-dataframe commented 3 years ago

Thanks @yet-another-average-joe i've already tested it, the issue persists, also with your branch library i need to add the delay in the reported function

DanielDB23 commented 3 years ago

Hi, I got the same problem with single SDM630 slave, tried 2 different RS485 shields, the response was detected but always returning 226. It's definitely because of available the time to get the response back that is not handle by the library when the baudrate is to low. I changed the baudrate on the slave and the controler : not working for baudrate 19200 and under, working for baudrate 38400 and upper. So if you have access to the baudrate, no need for modification in the library.

@thetintin1000 Please could you share your code with me, since I have problems communicating the SDM630

thetintin1000 commented 3 years ago

@DanielDB23 : This is for reading, but you can change it for writting ` / Communication Modbus RTU ( Master ). Communication with 1 slaves SDM630 Libraries externes:: ModbusMaster/SofwareSerial /

include

include

/*****/ / / / /////////////////////////////////////////////////////////////////////////////// / Starting: Parameters/ ///////////////////////////////////////////////////////////////////////////////// / / / / / - Slave call time call_time_s in seconds : ( default = 30 ) /

define call_time_s 3

/ - Slave address addr_cpt_1 : ( default = 1 ) /

define addr_cpt_1 1

/ - Serial Receive pin, for shield RS485 : ( default = 10 ) /

define SSerialRX 10

/ - Serial Transmit pin, for shield RS485 : ( default = 11 ) /

define SSerialTX 11

/ - Baudrate: have to be also configure on slaves interfaces, should be up to 38400 : ( default = 38400 ) /

define baudrate 38400

/ / / / /*****/

ModbusMaster node1;

SoftwareSerial RS485Serial(SSerialRX, SSerialTX);

void setup() {

Serial.begin(baudrate);

RS485Serial.begin(baudrate);

node1.begin(addr_cpt_1, RS485Serial); Serial.println(" Setup done "); Serial.print(" Module initialized with baudrate : "); Serial.print(baudrate); Serial.println(" "); }

void loop() { uint8_t j, result1; uint16_t data1[2]; float x1; unsigned long *p1;

// Address 0x0034 with a length of 2 result1 = node1.readInputRegisters(0x0034, 2);

delay(2000);

if ((result1 == node1.ku8MBSuccess)) { for (j = 0; j < 1; j++) { data1[j] = node1.getResponseBuffer(j); } p1 = (unsigned long)&x1; p1 = (unsigned long)data1[0]<<16 | data1[1]; Serial.println(x1); } delay(1000*call_time_s); } `