feature-requests icon indicating copy to clipboard operation
feature-requests copied to clipboard

RS485 serial support / tx enable pin control

Open nebulous opened this issue 6 years ago • 16 comments

Describe the problem you have/What new integration you would like

I would like to have a RS485 serial component available which extends the serial component with a half-duplex tx pin enable option. In order to use a shared bus, rs485 requires setting a tx enable pin when transmitting.

Please describe your use case for this integration and alternatives you've tried:

My particular use case is integration with Carrier thermostats which use a custom protocol over RS485(toy C implementation here https://github.com/nebulous/infinitude/tree/master/contrib/cardump), but this would be applicable to any half-duplex serial system. While modbus doesn't particularly interest me, an rs485 component would also form a standard base for those who wish to implement modbus components.

Additional context

Most cheap rs485 interfaces based on the MAX485 break out DE and RE pins, which typically are shorted together into one "I'm currently transmitting" pin. Bonus points to an implementation which accounts for disablement of rx interrupts while transmitting. That is, independent monitoring/driving of DE/RE.

Here's a reference patch to a similar implementation for mongooseOS https://github.com/cesanta/mongoose-os/commit/a71bfbade5964601b004bc3f1de8d75616e46137

nebulous avatar Oct 08 '19 15:10 nebulous

I would like to use RS485 for long-span serial communication and for communication with my Invertek variable frequency driver.

lwqcz avatar Nov 17 '19 22:11 lwqcz

I am using stm32 controller for sending a sequence of Modbus structure to (uart to rs485) converter but I am not getting the response from energy_meter, I am having doubt on using RE DE pin in the converter.????????

xzsfd2457 avatar Jan 13 '20 12:01 xzsfd2457

Have you guys found a method for implementing 485 comms with ESP home?

poldim avatar Jun 06 '20 20:06 poldim

@nagyrobi would it be possible to clarify where the alternative was offered? It's not obvious to me in the thread above or the documentation or the linked issues how one could control a tx_enable pin for half-duplex comms using chips like the ubiquitous MAX485.

nebulous avatar Oct 20 '22 19:10 nebulous

The undocumented modbus: component has a direction control pin option, but it would be better if it was at the uart level instead. Or else we need an RS485 component above the uart.

ssieb avatar Oct 24 '22 22:10 ssieb

I second the need for a flow_control_pin for half-duplex comms (RS485). The modbus alternative is not possible as we are not and can not use modbus.

Can the same "flow_control_pin" solution used for modus be duplicated for the uart like:?

uart:
  id: uart_0
  baud_rate: 115200
  rx_buffer_size: 384
  flow_control_pin: 23
  tx_pin: 22
  rx_pin: 21

Uksa007 avatar Jun 08 '23 11:06 Uksa007

Besides adding the flow_control_pin, there also needs to be a "polarity" set, since some chips would transmit on high and others would receive on high. Some chips like the MAX485 have 2 enable pins, one for transmit, and one for receive, although they are usually tied together, some circuits could have them separate, so there might also need to be two flow control pins, one for transmit, and one for receive. But this is a good idea, since a lot of RS485 interfaces are half-duplex only.

rarroyo6 avatar Jul 25 '24 17:07 rarroyo6

I've linked a PR that adds the necessary support, but only if you're using ESP-IDF. ESP-IDF has native support for this, so implementation was quite simple. However, said support isn't very configurable - I can't invert the polarity, nor can I configure separate DE and RE pins. It's working just fine for me to have full half-duplex communications between two MAX485 devices.

ccutrer avatar Sep 15 '25 18:09 ccutrer

There's already a pull request for it where more things are being added. It includes both Arduino and the ESP-IDF framework for ESP32.

brambo123 avatar Sep 16 '25 11:09 brambo123

Hi,

I stumbled across this issue and I am not sure now if this is already possible: I have a board here wheer RS485 tranceiver Pins RE_N (receive enable inverted) and DE (transmit enable) are seperated and NOT tied together. So I need to drive DE high when sending and RE_N high when sending, and vice versa.

I tried just setting RE_N to always receiving (low) through a lamba but then I cannot properly receive anymore because I'm listening to my own transmissions. There is no receive pin setting that I can find anywhere, so how can I make this work? Is ESPHome really assuming those pins are always tied together? Seems like a bad limitation.

markusdd avatar Nov 04 '25 19:11 markusdd

Hi,

I stumbled across this issue and I am not sure now if this is already possible: I have a board here wheer RS485 tranceiver Pins RE_N (receive enable inverted) and DE (transmit enable) are seperated and NOT tied together. So I need to drive DE high when sending and RE_N high when sending, and vice versa.

I tried just setting RE_N to always receiving (low) through a lamba but then I cannot properly receive anymore because I'm listening to my own transmissions. There is no receive pin setting that I can find anywhere, so how can I make this work? Is ESPHome really assuming those pins are always tied together? Seems like a bad limitation.

I think the UART_RS485_CONF_REG.UART_RS485TX_RX_EN bit needs to be set. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/uart.html#overview-of-rs485-specific-communication-0ptions

brambo123 avatar Nov 04 '25 19:11 brambo123

I think the UART_RS485_CONF_REG.UART_RS485TX_RX_EN bit needs to be set. https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/uart.html#overview-of-rs485-specific-communication-0ptions

very good hint. How can I do that in ESPHome?

markusdd avatar Nov 04 '25 19:11 markusdd

Ok, in case anyone comes across this:

I made myself a rs485_flow.h:

// this is to support RS485 on boards that have TX and RX enable pins seperated
// ESP Home assumes just transmit enable must be controlled, but that is not true

#pragma once
#include "soc/uart_reg.h"
#include "soc/uart_struct.h"

static inline void confrs485(void)
{
    gpio_set_direction(GPIO_NUM_15, GPIO_MODE_OUTPUT);
    gpio_set_level(GPIO_NUM_15, 0);
    
    // For UART0
    #define UART_NUM 0

    // Enable RS-485 mode
    SET_PERI_REG_MASK(UART_RS485_CONF_REG(UART_NUM), UART_RS485_EN);

    // Enable automatic TX/RX control (DE/~RE driven by UART)
    SET_PERI_REG_MASK(UART_CONF1_REG(UART_NUM), UART_RS485TX_RX_EN);
}

and included it in the yaml:

esphome:
  ...
  # this is to pull the RE_N pin of the RS485 tranceiver low and enable collision detect
  includes: 
    - rs485_flow.h
  on_boot: 
    then:
      - lambda: |-
          confrs485();

...

modbus_controller:
  - id: earu_ea777
    address: 0x1              # Adjust device address
    modbus_id: modbus_server
    setup_priority: -10
    update_interval: 5s
    on_online: 
      then:
        - lambda: |-
            confrs485();

With this it is working. So I pull RE_N low permanently and tell the UART to ignore the shouting into it's own ear. If you have a chip where RE is high active you of course want to invert this and pin it to 1.

Still, this should probably be an option in the yaml. We have to be able to give the RX enable pin and then half-dupley should also be enabled in the background. This isn't a workaroud a more unexperienced user will be able to handle.

markusdd avatar Nov 04 '25 20:11 markusdd

@markusdd by the way, would you be so kind to share your ESPHome modbus config for EARU EA777?

nagyrobi avatar Nov 04 '25 21:11 nagyrobi

@markusdd by the way, would you be so kind to share your ESPHome modbus config for EARU EA777?

it's literally in the device repository, I also only have it from here haha

markusdd avatar Nov 04 '25 21:11 markusdd

Oh

nagyrobi avatar Nov 04 '25 22:11 nagyrobi