-
Notifications
You must be signed in to change notification settings - Fork 7.6k
MODBUS communication randomly broken due to misbehaving Serial.flush() function #5877
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@garageeks Serial.printf("Internal Total heap %d, internal Free Heap %d\n", ESP.getHeapSize(), ESP.getFreeHeap());
Serial.printf("SPIRam Total heap %d, SPIRam Free Heap %d\n", ESP.getPsramSize(), ESP.getFreePsram());
Serial.printf("ChipRevision %d, Cpu Freq %d, SDK Version %s\n", ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion());
Serial.printf("Flash Size %d, Flash Speed %d\n", ESP.getFlashChipSize(), ESP.getFlashChipSpeed());
|
Hi @SuGlider , shall I run the code standalone or while running my MODBUS application? I always print the free heap to detect potential memory leaks, so I have already some information from my application: The ESP32 module I'm using is ESP32-WROOM-32E PS: on 2.0.0 free heap and max block value is basically the same when MODBUS is working and when it stops working |
@garageeks |
Sorry, I forgot my programmer at home, I could only flash new firmware by OTA. Here's the results from within my application. 1.0.6 - MODBUS works non-stop for 24+hrs 2.0.0 - MODBUS works but fails after a while 2.0.1 - MODBUS doesn't work at all from the start |
@garageeks Please let me know if #include <ModbusMaster.h>
// necessary to define UART_MODE_RS485_HALF_DUPLEX
#include <driver/uart.h>
// instantiate ModbusMaster object
ModbusMaster node;
void setup()
{
// use Serial (port 0); initialize Modbus communication baud rate
Serial.begin(19200);
// communicate with Modbus slave ID 2 over Serial (port 0)
node.begin(2, Serial);
// Set RS485 half duplex mode on UART_0. This shall force flush to wait up to sending all bits out
ESP_ERROR_CHECK(uart_set_mode(0, UART_MODE_RS485_HALF_DUPLEX));
}
|
Dear @SuGlider ,
It didn't accept an integer as first parameter of the function. I assumed UART_NUM_2 is the valid one for Serial2. However on 2.0.1 it still doesn't communicate with the MODBUS device. |
Hi @ignasurba thank you for your feedback. I have tried it based on @SuGlider suggestion but didn't work. I can give it another try. |
It looks like this:
Seems to work so far without issues. |
I replaced Serial2 for Serial1 and UART_NUM_2 for UART_NUM_1 and it works! So apparently there is some other bug with Serial2 / UART_NUM_2 combination. The previous peripheral on Serial1 is happy to work on Serial2, so I can leave my test bench running for a while and see its stability. This code doesn't work:
|
Not sure if it will get noticed, as both this issue and the PR are now closed. See: #6026 (comment) |
@TD-er Thanks for your comment. We will take a look on your note and consider correctness of this fix. |
This fix doesn't prevent UART to be full-duplex or to force it to be half-duplex. It's just a name of a feature IDF uses in this driver with its own internal RS-485 functionalities - that are not used in ESP32 Arduino implementation. Please read more in #6026 (comment) |
Hmm that could benefit from a comment line explaining what is intended as that setting value is not really descriptive of what it apparently does. Still I do think that it would be a good idea to make the mode configurable, like in the |
Thanks for your suggestions and care. Maybe, as you said, a commentary before the line code in UART HAL layer may avoid misinformation. Thanks you! |
@garageeks @ignasurba @TD-er Thanks for your support! |
Using arduino-esp32 1.0.6, the library ModbusMaster (https://github.com/4-20ma/ModbusMaster) works as intended.
Using arduino-esp32 2.0.0 or 2.0.1 it randomly stops communicating with the slave Modbus device.
I investigated with a scope and these are my findings:
RED LINE = TX signal, BLUE LINE = TX enable signal (tied to DE/NOT RE pins)
Succesful transmission - the device replies as expected (Not seen here as I only have two channels)

First failed transmission - enable signal stays high for a long time, preventing reception of the device answer

Subsequent failed transmission - enable signal is prematurely turned to LOW. The time it stays HIGH varies.



The mentioned library, when a packet is transmitted, turns HIGH the enable signal with preTransmission callback, write data to the serial port, flushes the serial port and then turns the enable signal LOW. Pretty straightforward. I assume Serial TX is buffered, then Serial.flush takes its time until the buffer is empty.
Given the recent big overhaul of HardwareSerial and some other issues, I think there is a bug in the new implementation with 2.0.0 and 2.0.1 releases.
This is similar to #4603
The text was updated successfully, but these errors were encountered: