mirror of
https://github.com/esphome/esphome.git
synced 2024-12-04 13:44:40 +01:00
Add H-Bridge switch component (#7421)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
parent
edd847ea40
commit
fb96e3588d
@ -179,6 +179,7 @@ esphome/components/haier/text_sensor/* @paveldn
|
|||||||
esphome/components/havells_solar/* @sourabhjaiswal
|
esphome/components/havells_solar/* @sourabhjaiswal
|
||||||
esphome/components/hbridge/fan/* @WeekendWarrior
|
esphome/components/hbridge/fan/* @WeekendWarrior
|
||||||
esphome/components/hbridge/light/* @DotNetDann
|
esphome/components/hbridge/light/* @DotNetDann
|
||||||
|
esphome/components/hbridge/switch/* @dwmw2
|
||||||
esphome/components/he60r/* @clydebarrow
|
esphome/components/he60r/* @clydebarrow
|
||||||
esphome/components/heatpumpir/* @rob-deutsch
|
esphome/components/heatpumpir/* @rob-deutsch
|
||||||
esphome/components/hitachi_ac424/* @sourabhjaiswal
|
esphome/components/hitachi_ac424/* @sourabhjaiswal
|
||||||
|
44
esphome/components/hbridge/switch/__init__.py
Normal file
44
esphome/components/hbridge/switch/__init__.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from esphome import pins
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import switch
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import CONF_OPTIMISTIC, CONF_PULSE_LENGTH, CONF_WAIT_TIME
|
||||||
|
|
||||||
|
from .. import hbridge_ns
|
||||||
|
|
||||||
|
HBridgeSwitch = hbridge_ns.class_("HBridgeSwitch", switch.Switch, cg.Component)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@dwmw2"]
|
||||||
|
|
||||||
|
CONF_OFF_PIN = "off_pin"
|
||||||
|
CONF_ON_PIN = "on_pin"
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
switch.switch_schema(HBridgeSwitch)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_ON_PIN): pins.gpio_output_pin_schema,
|
||||||
|
cv.Required(CONF_OFF_PIN): pins.gpio_output_pin_schema,
|
||||||
|
cv.Optional(
|
||||||
|
CONF_PULSE_LENGTH, default="100ms"
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(CONF_WAIT_TIME): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.COMPONENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = await switch.new_switch(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
on_pin = await cg.gpio_pin_expression(config[CONF_ON_PIN])
|
||||||
|
cg.add(var.set_on_pin(on_pin))
|
||||||
|
off_pin = await cg.gpio_pin_expression(config[CONF_OFF_PIN])
|
||||||
|
cg.add(var.set_off_pin(off_pin))
|
||||||
|
cg.add(var.set_pulse_length(config[CONF_PULSE_LENGTH]))
|
||||||
|
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
|
||||||
|
if wait_time := config.get(CONF_WAIT_TIME):
|
||||||
|
cg.add(var.set_wait_time(wait_time))
|
95
esphome/components/hbridge/switch/hbridge_switch.cpp
Normal file
95
esphome/components/hbridge/switch/hbridge_switch.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include "hbridge_switch.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace hbridge {
|
||||||
|
|
||||||
|
static const char *const TAG = "switch.hbridge";
|
||||||
|
|
||||||
|
float HBridgeSwitch::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||||
|
void HBridgeSwitch::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up H-Bridge Switch '%s'...", this->name_.c_str());
|
||||||
|
|
||||||
|
optional<bool> initial_state = this->get_initial_state_with_restore_mode().value_or(false);
|
||||||
|
|
||||||
|
// Like GPIOSwitch does, set the pin state both before and after pin setup()
|
||||||
|
this->on_pin_->digital_write(false);
|
||||||
|
this->on_pin_->setup();
|
||||||
|
this->on_pin_->digital_write(false);
|
||||||
|
|
||||||
|
this->off_pin_->digital_write(false);
|
||||||
|
this->off_pin_->setup();
|
||||||
|
this->off_pin_->digital_write(false);
|
||||||
|
|
||||||
|
if (initial_state.has_value())
|
||||||
|
this->write_state(initial_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HBridgeSwitch::dump_config() {
|
||||||
|
LOG_SWITCH("", "H-Bridge Switch", this);
|
||||||
|
LOG_PIN(" On Pin: ", this->on_pin_);
|
||||||
|
LOG_PIN(" Off Pin: ", this->off_pin_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Pulse length: %" PRId32 " ms", this->pulse_length_);
|
||||||
|
if (this->wait_time_)
|
||||||
|
ESP_LOGCONFIG(TAG, " Wait time %" PRId32 " ms", this->wait_time_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HBridgeSwitch::write_state(bool state) {
|
||||||
|
this->desired_state_ = state;
|
||||||
|
if (!this->timer_running_)
|
||||||
|
this->timer_fn_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HBridgeSwitch::timer_fn_() {
|
||||||
|
uint32_t next_timeout = 0;
|
||||||
|
|
||||||
|
while ((uint8_t) this->desired_state_ != this->relay_state_) {
|
||||||
|
switch (this->relay_state_) {
|
||||||
|
case RELAY_STATE_ON:
|
||||||
|
case RELAY_STATE_OFF:
|
||||||
|
case RELAY_STATE_UNKNOWN:
|
||||||
|
if (this->desired_state_) {
|
||||||
|
this->on_pin_->digital_write(true);
|
||||||
|
this->relay_state_ = RELAY_STATE_SWITCHING_ON;
|
||||||
|
} else {
|
||||||
|
this->off_pin_->digital_write(true);
|
||||||
|
this->relay_state_ = RELAY_STATE_SWITCHING_OFF;
|
||||||
|
}
|
||||||
|
next_timeout = this->pulse_length_;
|
||||||
|
if (!this->optimistic_)
|
||||||
|
this->publish_state(this->desired_state_);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RELAY_STATE_SWITCHING_ON:
|
||||||
|
this->on_pin_->digital_write(false);
|
||||||
|
this->relay_state_ = RELAY_STATE_ON;
|
||||||
|
if (this->optimistic_)
|
||||||
|
this->publish_state(true);
|
||||||
|
next_timeout = this->wait_time_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RELAY_STATE_SWITCHING_OFF:
|
||||||
|
this->off_pin_->digital_write(false);
|
||||||
|
this->relay_state_ = RELAY_STATE_OFF;
|
||||||
|
if (this->optimistic_)
|
||||||
|
this->publish_state(false);
|
||||||
|
next_timeout = this->wait_time_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_timeout) {
|
||||||
|
this->timer_running_ = true;
|
||||||
|
this->set_timeout(next_timeout, [this]() { this->timer_fn_(); });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the case where ON/OFF state has been reached but we need to
|
||||||
|
// immediately change back again to reach desired_state_, we loop.
|
||||||
|
}
|
||||||
|
this->timer_running_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace hbridge
|
||||||
|
} // namespace esphome
|
50
esphome/components/hbridge/switch/hbridge_switch.h
Normal file
50
esphome/components/hbridge/switch/hbridge_switch.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace hbridge {
|
||||||
|
|
||||||
|
enum RelayState : uint8_t {
|
||||||
|
RELAY_STATE_OFF = 0,
|
||||||
|
RELAY_STATE_ON = 1,
|
||||||
|
RELAY_STATE_SWITCHING_ON = 2,
|
||||||
|
RELAY_STATE_SWITCHING_OFF = 3,
|
||||||
|
RELAY_STATE_UNKNOWN = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
class HBridgeSwitch : public switch_::Switch, public Component {
|
||||||
|
public:
|
||||||
|
void set_on_pin(GPIOPin *pin) { this->on_pin_ = pin; }
|
||||||
|
void set_off_pin(GPIOPin *pin) { this->off_pin_ = pin; }
|
||||||
|
void set_pulse_length(uint32_t pulse_length) { this->pulse_length_ = pulse_length; }
|
||||||
|
void set_wait_time(uint32_t wait_time) { this->wait_time_ = wait_time; }
|
||||||
|
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
||||||
|
|
||||||
|
// ========== INTERNAL METHODS ==========
|
||||||
|
// (In most use cases you won't need these)
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void write_state(bool state) override;
|
||||||
|
void timer_fn_();
|
||||||
|
|
||||||
|
bool timer_running_{false};
|
||||||
|
bool desired_state_{false};
|
||||||
|
RelayState relay_state_{RELAY_STATE_UNKNOWN};
|
||||||
|
GPIOPin *on_pin_{nullptr};
|
||||||
|
GPIOPin *off_pin_{nullptr};
|
||||||
|
uint32_t pulse_length_{0};
|
||||||
|
uint32_t wait_time_{0};
|
||||||
|
bool optimistic_{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace hbridge
|
||||||
|
} // namespace esphome
|
39
tests/components/hbridge/common.yaml
Normal file
39
tests/components/hbridge/common.yaml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
output:
|
||||||
|
- platform: ${pwm_platform}
|
||||||
|
pin: ${output1_pin}
|
||||||
|
id: gpio_output1
|
||||||
|
- platform: ${pwm_platform}
|
||||||
|
pin: ${output2_pin}
|
||||||
|
id: gpio_output2
|
||||||
|
- platform: ${pwm_platform}
|
||||||
|
pin: ${output3_pin}
|
||||||
|
id: gpio_output3
|
||||||
|
- platform: ${pwm_platform}
|
||||||
|
pin: ${output4_pin}
|
||||||
|
id: gpio_output4
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: hbridge
|
||||||
|
name: Icicle Lights
|
||||||
|
pin_a: gpio_output3
|
||||||
|
pin_b: gpio_output4
|
||||||
|
|
||||||
|
fan:
|
||||||
|
- platform: hbridge
|
||||||
|
id: fan_hbridge
|
||||||
|
speed_count: 4
|
||||||
|
name: H-bridge Fan with Presets
|
||||||
|
pin_a: gpio_output1
|
||||||
|
pin_b: gpio_output2
|
||||||
|
preset_modes:
|
||||||
|
- Preset 1
|
||||||
|
- Preset 2
|
||||||
|
on_preset_set:
|
||||||
|
then:
|
||||||
|
- logger.log: Preset mode was changed!
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: hbridge
|
||||||
|
id: switch_hbridge
|
||||||
|
on_pin: ${hbridge_on_pin}
|
||||||
|
off_pin: ${hbridge_off_pin}
|
@ -1,33 +1,17 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: ledc
|
pwm_platform: ledc
|
||||||
pin: 14
|
output1_pin: "14"
|
||||||
id: gpio_output1
|
output2_pin: "15"
|
||||||
- platform: ledc
|
output3_pin: "12"
|
||||||
pin: 15
|
output4_pin: "13"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "4"
|
||||||
- platform: ledc
|
hbridge_off_pin: "5"
|
||||||
pin: 12
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: ledc
|
|
||||||
pin: 13
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
pulse_length: 60ms
|
||||||
speed_count: 4
|
wait_time: 10ms
|
||||||
name: H-bridge Fan with Presets
|
optimistic: false
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: ledc
|
pwm_platform: "ledc"
|
||||||
pin: 4
|
output1_pin: "4"
|
||||||
id: gpio_output1
|
output2_pin: "5"
|
||||||
- platform: ledc
|
output3_pin: "6"
|
||||||
pin: 5
|
output4_pin: "7"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "2"
|
||||||
- platform: ledc
|
hbridge_off_pin: "3"
|
||||||
pin: 6
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: ledc
|
|
||||||
pin: 7
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
wait_time: 10ms
|
||||||
speed_count: 4
|
optimistic: true
|
||||||
name: H-bridge Fan with Presets
|
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
@ -1,33 +1,15 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: ledc
|
pwm_platform: "ledc"
|
||||||
pin: 4
|
output1_pin: "4"
|
||||||
id: gpio_output1
|
output2_pin: "5"
|
||||||
- platform: ledc
|
output3_pin: "6"
|
||||||
pin: 5
|
output4_pin: "7"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "2"
|
||||||
- platform: ledc
|
hbridge_off_pin: "3"
|
||||||
pin: 6
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: ledc
|
|
||||||
pin: 7
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
pulse_length: 60ms
|
||||||
speed_count: 4
|
|
||||||
name: H-bridge Fan with Presets
|
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: ledc
|
pwm_platform: "ledc"
|
||||||
pin: 14
|
output1_pin: "14"
|
||||||
id: gpio_output1
|
output2_pin: "15"
|
||||||
- platform: ledc
|
output3_pin: "12"
|
||||||
pin: 15
|
output4_pin: "13"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "4"
|
||||||
- platform: ledc
|
hbridge_off_pin: "5"
|
||||||
pin: 12
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: ledc
|
|
||||||
pin: 13
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
pulse_length: 60ms
|
||||||
speed_count: 4
|
wait_time: 10ms
|
||||||
name: H-bridge Fan with Presets
|
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: esp8266_pwm
|
pwm_platform: "esp8266_pwm"
|
||||||
pin: 4
|
output1_pin: "4"
|
||||||
id: gpio_output1
|
output2_pin: "5"
|
||||||
- platform: esp8266_pwm
|
output3_pin: "12"
|
||||||
pin: 5
|
output4_pin: "13"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "14"
|
||||||
- platform: esp8266_pwm
|
hbridge_off_pin: "15"
|
||||||
pin: 12
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: esp8266_pwm
|
|
||||||
pin: 13
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
pulse_length: 60ms
|
||||||
speed_count: 4
|
wait_time: 10ms
|
||||||
name: H-bridge Fan with Presets
|
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
output:
|
substitutions:
|
||||||
- platform: rp2040_pwm
|
pwm_platform: "rp2040_pwm"
|
||||||
pin: 4
|
output1_pin: "4"
|
||||||
id: gpio_output1
|
output2_pin: "5"
|
||||||
- platform: rp2040_pwm
|
output3_pin: "6"
|
||||||
pin: 5
|
output4_pin: "7"
|
||||||
id: gpio_output2
|
hbridge_on_pin: "2"
|
||||||
- platform: rp2040_pwm
|
hbridge_off_pin: "3"
|
||||||
pin: 6
|
|
||||||
id: gpio_output3
|
|
||||||
- platform: rp2040_pwm
|
|
||||||
pin: 7
|
|
||||||
id: gpio_output4
|
|
||||||
|
|
||||||
light:
|
packages:
|
||||||
- platform: hbridge
|
common: !include common.yaml
|
||||||
name: Icicle Lights
|
|
||||||
pin_a: gpio_output3
|
|
||||||
pin_b: gpio_output4
|
|
||||||
|
|
||||||
fan:
|
switch:
|
||||||
- platform: hbridge
|
- id: !extend switch_hbridge
|
||||||
id: fan_hbridge
|
wait_time: 10ms
|
||||||
speed_count: 4
|
optimistic: true
|
||||||
name: H-bridge Fan with Presets
|
|
||||||
pin_a: gpio_output1
|
|
||||||
pin_b: gpio_output2
|
|
||||||
preset_modes:
|
|
||||||
- Preset 1
|
|
||||||
- Preset 2
|
|
||||||
on_preset_set:
|
|
||||||
then:
|
|
||||||
- logger.log: Preset mode was changed!
|
|
||||||
|
Loading…
Reference in New Issue
Block a user