Open RoganDawes opened 7 months ago
Depending on how long it actually takes to configure the UART peripheral, it could be done as part of the tx path, and unlocked automatically after a timeout.
@RoganDawes this is useful, yes, however all the components using UART shall be able to use this feature. I don't believe timeout will work properly for all devices. For example, I have implemented uart lock/unlock for my own custom component to be able to share UART between different electricity meters. Which work with 'sessions'.
So basically I start working with UART by try_lock_session
and then unlock
it manually later.
maybe something like this might be thought trough and implemented in a component like session_uart
, which only can be used after locking the resource.
Yeah, an automatic timeout is probably not a good approach to this. And trying to make all possible users of a UARTComponent lock and unlock the UART is also probably not the right way. Providing a SharedUART type might be one approach, basically extending the UART interface to add a .lock() and .unlock() method.
It does feel like we would need to be very careful with the type hierarchy to make sure that it behaves in a sensible way, though!
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:
This is somewhat analogous to the
modbus:
component'sflow_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).