Page 2 of 3

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Thu Apr 12, 2018 3:36 pm
by grasvezel
I know it has been a few weeks, but I ran into similar problems, solved them and would like to share. I use a MAX-3485. Basically a 485 but for 3.3v instead of 5v. I couldn't get anyting to work using standard libraries. I used one of the many hardware examples in wich the DE and /RE are connected. DriverEnable is active high, ReceiverEnable is active low. So, why not use one GPIO and use that as a toggle between send and receive, right? After hours of debugging and hooking up a second ESP32/MAX3485 to see what was going on on the RS485 bus, I found that the DE dropped before the transmission of the Modbus frame was complete. My guess is that the library just goes ahead and drops the DE pin after the frame is sent, but at that time the ESP32 still has some data in the transmit buffer. Maybe that is a difference with arduinos, maybe those don't have a transmit buffer?

Anyway: I solved it by modifying my hardware a bit (RE is always low now) and implementing the Modbus protocol myself instead of using a lib. The protocol is quite straightforward. The only thing I had to deal with is reading back my own transmission because the receiver is always on now. But since I know exactly what I sent out, that's not difficult to do.

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Fri Apr 13, 2018 7:21 am
by migbur
Hi, good work
I want to connect a sensor that use RS485, can you share your code?

Thanks for sharing your work.

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Mon Apr 23, 2018 9:37 am
by ffplus
I have come across exact same thing with ModbusMaster library as well. Too many Modbus and Logic analyser tests lead me to editing of the library and found the solution actually.

Problem is according to my guess, when you use Serial.write() function, due to async nature of ESP32 it doesn't wait for the buffer to send all data on serial port. It instantly pass through other command line for disable to Transmit Enable pin.

A solution to this create exact amount of time required to send the byte frame of modbus like this at transaction function on ModbusMaster.cpp:

(For ModbusMaster library)

// flush receive buffer before transmitting request
while (_serial->read() != -1);

// ADD THIS after write
long baud = BAUD_RATE; // Your baudrate
float symbol_time = 1000000 / baud; // Create time for a single symbol
float wait_time = ( ( (1 + 8 + 1) * symbol_time ) * u8ModbusADUSize); // Create exact payload size.

Then after write of payload:
for (i = 0; i < u8ModbusADUSize; i++)
{
_serial->write(u8ModbusADU);
}
// WAIT ENOUGH TIME TO SEND DUE TO ESP32 ASYNC NATURE
delayMicroseconds(wait_time);
delayMicroseconds(1700); // Time for frame ending for modbus standart (I didn't have time to fully implement would be gratefull if someone else can does it)

Of course this is only transmit part. At the receive part also whenever you read serial buffer it starts with 0x00 byte. So I created an ugly workaround

int start = 0; // Put this here
if (_serial->available())
{
// PUT this to here, it reads first byte and do not put into modbus payload
if(start == 0) {
_serial->read();
start = 1;
continue;
}

With this workaround I could able to successfully read modbus response from payload as well.

But I think here with this write and read issues, SDK team should look and create a more understandable and robust solution.

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Wed Apr 25, 2018 9:12 am
by migbur
Thank to much
I will tried it.

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Wed Apr 25, 2018 9:25 am
by migbur
Hi
always is necessary MAX-3485 as interface or I can connect it directly to ESP32 pin?

Thanks....

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Sun Apr 29, 2018 7:50 pm
by grasvezel
RS485 uses a different electrical signal. It is balananced (the signal has a + and - so no ground) in order to make it more resistant against interference. RS485 is designed to work with long cables (up to 1000 meters I beleive).

So yes, you will need a MAX3485 (or equivalent) in oder to connect it to an ESP.

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Thu May 10, 2018 12:44 pm
by greg35
Hey I have something similar type problem in which I need to send digital signal converted from analog PIR sensor (using ADC) and send the signals through ESP32 to make the lightning system work wireless and control the brightness accordingly but not able to find out best way to control lightning system according to digital signals because due to high power circuit might get destroyed, Your suggestion on this will be very helpful

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Sun Jul 29, 2018 9:52 am
by krishna_k
iam using atmega328p as my slave device and esp32 as master device.i wanted to send data from atmega328p to esp32 but in response it is showing invalid slave id and few times it is showing response timeout. but when i have connected atmega328p it was working fine without your changes in library. though i have edited library according to you it is not working.will you send send me the clear modbus master.cpp file so that it would be clear....

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Tue Jul 31, 2018 12:00 pm
by akkaman007
ffplus wrote:I have come across exact same thing with ModbusMaster library as well. Too many Modbus and Logic analyser tests lead me to editing of the library and found the solution actually.

Problem is according to my guess, when you use Serial.write() function, due to async nature of ESP32 it doesn't wait for the buffer to send all data on serial port. It instantly pass through other command line for disable to Transmit Enable pin.

A solution to this create exact amount of time required to send the byte frame of modbus like this at transaction function on ModbusMaster.cpp:

(For ModbusMaster library)

// flush receive buffer before transmitting request
while (_serial->read() != -1);

// ADD THIS after write
long baud = BAUD_RATE; // Your baudrate
float symbol_time = 1000000 / baud; // Create time for a single symbol
float wait_time = ( ( (1 + 8 + 1) * symbol_time ) * u8ModbusADUSize); // Create exact payload size.

Then after write of payload:
for (i = 0; i < u8ModbusADUSize; i++)
{
_serial->write(u8ModbusADU);
}
// WAIT ENOUGH TIME TO SEND DUE TO ESP32 ASYNC NATURE
delayMicroseconds(wait_time);
delayMicroseconds(1700); // Time for frame ending for modbus standart (I didn't have time to fully implement would be gratefull if someone else can does it)

Of course this is only transmit part. At the receive part also whenever you read serial buffer it starts with 0x00 byte. So I created an ugly workaround

int start = 0; // Put this here
if (_serial->available())
{
// PUT this to here, it reads first byte and do not put into modbus payload
if(start == 0) {
_serial->read();
start = 1;
continue;
}

With this workaround I could able to successfully read modbus response from payload as well.

But I think here with this write and read issues, SDK team should look and create a more understandable and robust solution.




hii can you share us complete modbus master library code for esp32. we tried the editings which you have posted but still it was we were not able to receive the data.we have a doubt that we have done mistake while editing.so could you please send the complete code for modbus master library for esp32 which you have edited to make it work.Thanks in advance......

Re: ESP32 RS485driver hardwareserial ModbusMaster

Posted: Thu Feb 21, 2019 1:04 pm
by Warlib
Hi, colleagues,

I made a review on how to use MAX3485 based board with HardwareSerial on the ESP32. Here it is http://www.bizkit.ru/en/2019/02/11/12251/
RS485 board base on MAX485 works perfect with the ESP32.