esphome / esphome/feature-requests
UART Peripheral timesharing
- Dominant language
- No language data
- Stars
- 450
- Forks
- 29
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the problem you have/What new integration you would like**
Sometimes you need to communicate with more than 3 serial devices. When that communications is purely driven by the ESPHome as a master (e.g. modbusRTU request/response), it should theoretically be possible to "timeshare" one or more of the ESP32's 3 (or even 2) UART peripherals, simply by changing which pins are assigned, and the associated communications parameters, when a particular device needs to be communicated with.
**Please describe your use case for this integration and alternatives you've tried:**
I need to communicate with 5 Growatt inverters using modbus over RS232 (I've tried RS485 with the thought that I could simply daisy chain each one, and got zero response from the inverters). I also need to talk to 4 Narada 48NPFC100 batteries using modbus over RS485. (This part is working fine, fortunately.)
That leaves me needing to talk to 6 UART's in total, which is currently not possible.
In theory, it should be feasible to define a timeshare or interlock object, that governs which pins and communications parameters are in force at any particular time. The real complication lies in deciding which defined uart actually has control over the UART peripheral, either by letting the uart's "client" reserve and release the uart, or by iterating through the defined uarts, and giving each a turn. Alternatively, if the client is a PollingComponent, one could make sure that the uart has been reserved/locked prior to the `loop()` being scheduled, and unlocked automatically some (configurable) time afterwards.
This is kind of analogous to the `power_supply:` component, in a way. (https://esphome.io/components/power_supply)
**Additional context**
There is another feature request for support of an I2C- or SPI-connected UART here (#2355). I imagine this might be an alternative to needing that component, but that also suggests a way to implement this, as a unique platform:
```yaml
uart:
- id: uart1_
tx_pin: GPIO16
rx_pin: GPIO17
baud_rate: 19200
data_bits: 8
parity: none
stop_bits: 2
- id: uart2a
platform: timeshare
timeshare: timeshare_group1
tx_pin: GPIO26
rx_pin: GPIO27
baud_rate: 115200
data_bits: 8
parity: none
stop_bits: 1
- id: uart2b
platform: timeshare
timeshare: timeshare_group1
tx_pin: GPIO14
rx_pin: GPIO15
baud_rate: 57600
data_bits: 8
parity: none
stop_bits: 1
```
This is somewhat analogous to the `modbus:` component's `flow_control_pin:` (https://esphome.io/components/modbus.html), which is asserted prior to transmitting, and de-asserted when receiving. In this case, the UARTComponent would attempt to reserve or lock the timeshare group prior to running a series of modbus queries, or whatever it needs, then unlock it when done. The act of locking the group would configure the UART peripheral to the required pins and parameters, and unlocking it would revert the TX pin to a GPIO set to OUTPUT HIGH (TX idle), and the RX pin to a GPIO set to INPUT LOW (RX idle).
Contributor guide
No contributing guide indexed for this repository
Research direction
The request names no repository files or tests; begin by locating the UART and modbus component entry points and reviewing how ESP32 pins and communication parameters are configured. Define the timesharing ownership and lifecycle requirements before implementation, then add coverage for switching between configurations and verify the proposed YAML shape.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- embedded-iot
- Domain
- embedded-iot
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100