RS485: ESP32 not relinquishing control of the bus

WildPointer
Posts: 4
Joined: Sat May 04, 2024 4:24 pm

RS485: ESP32 not relinquishing control of the bus

Postby WildPointer » Wed Jun 19, 2024 9:32 pm

I have been struggling with a particular RS485 device because sporadically the ESP32 receives less bytes from it than expected. For a while I thought it was a problem with this device because I have used exactly the same setup and code to communicate with other devices with 100% success rate (slower baud rate is the only difference; 9600 baud/s vs 115200 baud/s). But I have now discovered that it is a problem on my side.

Specifically, the `RTS` signal from the ESP32 is sometimes going low a too long while (~300 micro-seconds) after the master's/ESP32's transmission has ended. This causes the RS485 driver chip in my board (Texas Instruments SN65176BDR) to hold control of the bus even when it is the slave's turn to respond. The slave device responds either way and its response gets attenuated enough for the ESP32 to loose the first few bytes received. See the attached images of the Bus Contention in the oscilloscope and my schematic.

My UART setup code is the one below.
I have to note that the `flow_control` member of the `uart_config_t ` typed variable is set to `UART_HW_FLOWCTRL_DISABLE` and that using `UART_HW_FLOWCTRL_RTS` causes errors in the communication.
I must say that I do not understand why this is happening. My code is heavily based on the code for the UART RS485 Echo Example by Espressif https://github.com/espressif/esp-idf/tr ... echo_rs485

Has anyone had problems like this? What am I doing wrong? Why is this behavior occurring only some times

My guess is that this is not an issue with slower (reduced baud rates) devices because of the increased time between messages but I might be wrong.
  1. void uart_rs485_init(uint32_t baud_rate){
  2.     int intr_alloc_flags = 0;
  3.     uart_driver_install(RS485_UART_PORT, RS485_UART_BUFFER_SIZE * 2, 0, 0, NULL, intr_alloc_flags);
  4.  
  5.     uart_config_t uart_config = {
  6.         .baud_rate  =   baud_rate,
  7.         .data_bits  =   UART_DATA_8_BITS,
  8.         .parity     =   UART_PARITY_DISABLE,
  9.         .stop_bits  =   UART_STOP_BITS_1,
  10.         .flow_ctrl  =   UART_HW_FLOWCTRL_DISABLE,
  11.         .source_clk =   UART_SCLK_APB,
  12.     };
  13.     uart_param_config(RS485_UART_PORT, &uart_config);
  14.  
  15.     uart_set_pin(RS485_UART_PORT, RS485_UART_TXD_PIN, RS485_UART_RXD_PIN, RS485_UART_RTS_PIN, UART_PIN_NO_CHANGE);
  16.  
  17.     uart_set_mode(RS485_UART_PORT, UART_HW_FLOWCTRL_RTS);
  18.  
  19.     return;
  20. }
Attachments
RS485 - Driver.png
Schematic of my implementation. RTS_ISO_b signal is obtained through an optocouple.
RS485 - Driver.png (43.27 KiB) Viewed 415 times
RS485 - healthy.png
Healthy RS485 communication.
- Yellow trace is the RS485-A line
- Violet trace is the RTS signal at the Drive Enable (DE) pin of the bus driver chip.

The RTS signal goes low on time to allow the response without Bus Contention

The master's request and slave's response can be recognized.
RS485 - healthy.png (34.26 KiB) Viewed 415 times
RS485 - bus contention.png
Bus Contention event in the RS485 communication channel.
- Yellow trace is the RS485-A line with respect to GND_ISO
- Violet trace is the RTS signal at the Drive Enable (DE) pin of the bus driver chip with respect to GND_ISO

You can see RTS remaining high even during the slave device's response causing an attenuation of the latter.
RS485 - bus contention.png (33.37 KiB) Viewed 415 times

Who is online

Users browsing this forum: Google [Bot] and 91 guests