esphome / esphome/feature-requests
Initial state for output GPIO pins
- 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**
Set initial state (high/low) before configuring a GPIO pin as output.
**Please describe your use case for this integration and alternatives you've tried:**
I use SN74HC595 shift register to extend the number of outputs. For my application it is important that outputs of the shift register are never in high state unless explicitly enabled. When powered, sn74hc595 outputs will be enabled (in undefined state) if OE pin is low, even if the shift register nor latch register were not initialized. To ensure that outputs are not in high state until initialized from the mcu, I pull up the OE pin with external resistor.
Here is the standard configuration I use for sn74hc595 component:
```
sn74hc595:
- id: "sr"
data_pin: GPIO25
clock_pin: GPIO14
latch_pin: GPIO27
oe_pin: GPIO26
```
When the component is being set up, even before the shift register is initialized with defined state, the OE is pin is pulled low for a brief moment.
`components/sn74hc595.cpp`:
```
void SN74HC595Component::pre_setup_() {
ESP_LOGCONFIG(TAG, "Setting up SN74HC595...");
if (this->have_oe_pin_) { // disable output
this->oe_pin_->setup();
this->oe_pin_->digital_write(true);
}
}
```
Calling `setup` on a GPIOPin (and ESP32InternalGPIOPin, one of its implementations) only initializes the mode (input, output, etc), but not the level. The default voltage level, in most cases, is low.
That is, after `this->oe_pin_->setup()`, the OE pin is pulled low until the GPIO is set up to its "initial" state with `digital_write(true)`, causing the outputs of the shift register to enable for a brief moment. This brief moment with undefined output state, in my case, is unacceptable.
**Workaround**
One possible workaround is to first configure the GPIO connected to the OE pin as input, to ensure that it is in high impedance state and not pulling the line down:
```
output:
- platform: gpio
id: "output_enable"
pin:
number: GPIO26
mode: INPUT
```
Enable the output whenever ready:
```
on_boot:
priority: 500
then:
# do some initialization, ensure shift register initialized, etc
# only then configure OE GPIO as output in low state
# mode could be OUTPUT_OPEN_DRAIN or OUTPUT_PUSH_PULL
- lambda: |-
pinMode(26, OUTPUT_OPEN_DRAIN);
digitalWrite(26, LOW);
```
**Additional context**
I don't have experience with other frameworks and microcontrollers like rp2040, but as far as I know, in arduino you can just use `digitalWrite(initialState)` before using `pinMode(OUTPUT)` to ensure that the pin is not initialized to wrong voltage level.
The changes required (such as adding a variable `initial_state` defaulting to `low` in pin schema) are backward compatible.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with components/sn74hc595.cpp and the GPIOPin setup implementation, including ESP32InternalGPIOPin, to trace when pin mode and level are applied. Review the shown YAML pin configuration and schema conventions; the work is done when an output GPIO can establish its requested initial high or low state without a transient unsafe level across the supported implementations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- arduino, cpp
- Domain
- embedded-iot
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100