Description
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
Activity
SuGlider commentedon Nov 12, 2021
@garageeks
In order to assist you could you please run this code in order to get more information about your board and development environment. If possible, run this code using core 1.0.6, 2.0.0 and 2.0.1 from your main development environment and report the result back here.
garageeks commentedon Nov 12, 2021
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:
on 1.0.6 I get Free heap: 247744 - Max block: 113792
on 2.0.0 I get Free heap: 181063 - Max block: 65524
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
PS2: the code is not exactly identical, but the code compiled on 1.0.6 has more features compared to 2.0.0. I can compare same code and report.
SuGlider commentedon Nov 12, 2021
@garageeks
You can run it stand alone with 2.0.x.
garageeks commentedon Nov 12, 2021
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
Internal Total heap 347228, internal Free Heap 249100
SPIRam Total heap 0, SPIRam Free Heap 0
ChipRevision 3, Cpu Freq 240, SDK Version v3.3.5-1-g85c43024c
Flash Size 16777216, Flash Speed 40000000
2.0.0 - MODBUS works but fails after a while
Internal Total heap 347091, internal Free Heap 283303
SPIRam Total heap 0, SPIRam Free Heap 0
ChipRevision 3, Cpu Freq 240, SDK Version v4.4-dev-2313-gc69f0ec32
Flash Size 16777216, Flash Speed 40000000
2.0.1 - MODBUS doesn't work at all from the start
Internal Total heap 310792, internal Free Heap 225908
SPIRam Total heap 0, SPIRam Free Heap 0
ChipRevision 3, Cpu Freq 240, SDK Version v4.4-dev-3569-g6a7d83af19-dirty
Flash Size 16777216, Flash Speed 40000000
SuGlider commentedon Nov 13, 2021
@garageeks
Please try this example with Core 2.0.0+
You can change UART port or Modbus slave ID as needed.
Please let me know if
uart_set_mode(UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX)
solves this issue.garageeks commentedon Nov 16, 2021
Dear @SuGlider ,
In my application I added your suggestion as follows
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.
ignasurba commentedon Dec 3, 2021
I can confirm this is an issue.
Part of the packet is sent after the flush returns and DE is disabled.
This worked for me:
ESP_ERROR_CHECK(uart_set_mode(UART_NUM_1, UART_MODE_RS485_HALF_DUPLEX));
(using Serial1)
garageeks commentedon Dec 3, 2021
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.
Where did you place this instruction? After the
node.begin
instruction?ignasurba commentedon Dec 5, 2021
It looks like this:
Seems to work so far without issues.
garageeks commentedon Dec 6, 2021
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:
mfriedlvaricon commentedon Dec 7, 2021
Hello!
We have the same issue... using Serial2.flush randomly returns inb4 all the information has been sent. This results in a massive loss of data and a non working product...

In the first picture you can see a valid output (Red line is basically when Serial.flush completes)
In the second picture flush gets called way to early and actually destroys the message.
All of this happens totally randomly. Sometimes it works, sometimes it keeps failing.

(EO = EnableOutput, DO = DisableOutput)
Hope this gets fixed soon, as our products are relying on this...
Thanks!
Markus
8 remaining items