Hi, I have the same problem. I also want to use a GPIO primarily as input, but switch to output and drive the pin on occasion. My idea is to define it as a normal binary sensor, so that it servers its main function, but then have a script that changes the pin mode to output, drives it and returns the pin mode back to input. So in practice I was thinking about something like this:
binary_sensor:
- platform: gpio
name: "Power Button State"
id: mcu_kill
icon: mdi:toggle-switch
pin:
number: GPIO19
script:
- id: simulate_button_press
mode: single
then:
- lambda: |-
ESP_LOGW("main", "Simulating Power Button Press");
pinMode(19, OUTPUT);
digitalWrite(19, HIGH);
delay(200);
digitalWrite(19, LOW);
pinMode(19, INPUT);
Unfortunately I never got it to work properly. There are some posts where people claim that this approach works, but I still get the following errors:
power.yaml: In lambda function:
power.yaml:45:19: error: 'OUTPUT' was not declared in this scope
power.yaml:45:7: error: 'pinMode' was not declared in this scope
power.yaml:46:24: error: 'HIGH' was not declared in this scope
power.yaml:46:7: error: 'digitalWrite' was not declared in this scope
power.yaml:48:24: error: 'LOW' was not declared in this scope
power.yaml:49:19: error: 'INPUT' was not declared in this scope
*** [.pioenvs\irrigationsystem\src\main.cpp.o] Error 1
In practice we need to implement the one wire pin, but manually. Here is the setup function fron the esphome components:
void GPIOOneWireBus::setup() {
this->t_pin_->setup();
this->t_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
// clear bus with 480µs high, otherwise initial reset in search might fail
this->pin_.digital_write(true);
this->pin_.pin_mode(gpio::FLAG_OUTPUT);
delayMicroseconds(480);
this->search();
}
It does more or less the same thing, so it must be possible… the question is how to do it in esphome itself. I was also thinnking to use the onewire component itself, but it does not allow custom configuration, because it is setup to work with the protocol only.
Using this approach, the script could possibly look something like this:
script:
- id: simulate_button_press
mode: single
then:
- lambda: |-
ESP_LOGW("main", "Simulating Power Button Press");
auto pin = ??? // I don't know how to get the pin class here
pin->pin_mode(gpio::FLAG_OUTPUT);
pin->digital_wright(true);
delay(200);
pin->digital_wright(false);
pin->pin_mode(gpio::FLAG_INPUT);
bool bit = pin->digital_read();
The GPIOpin class is virtual, so it cannot be used directly