mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 11:47:30 +01:00
Add cd74hc4067 multiplexer (#2431)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: asoehlke <git@soehlke.de>
This commit is contained in:
parent
ece71a0228
commit
27364ee72c
@ -37,6 +37,7 @@ esphome/components/canbus/* @danielschramm @mvturnho
|
|||||||
esphome/components/cap1188/* @MrEditor97
|
esphome/components/cap1188/* @MrEditor97
|
||||||
esphome/components/captive_portal/* @OttoWinter
|
esphome/components/captive_portal/* @OttoWinter
|
||||||
esphome/components/ccs811/* @habbie
|
esphome/components/ccs811/* @habbie
|
||||||
|
esphome/components/cd74hc4067/* @asoehlke
|
||||||
esphome/components/climate/* @esphome/core
|
esphome/components/climate/* @esphome/core
|
||||||
esphome/components/climate_ir/* @glmnet
|
esphome/components/climate_ir/* @glmnet
|
||||||
esphome/components/color_temperature/* @jesserockz
|
esphome/components/color_temperature/* @jesserockz
|
||||||
|
53
esphome/components/cd74hc4067/__init__.py
Normal file
53
esphome/components/cd74hc4067/__init__.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome import pins
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_DELAY,
|
||||||
|
CONF_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@asoehlke"]
|
||||||
|
AUTO_LOAD = ["sensor", "voltage_sampler"]
|
||||||
|
|
||||||
|
cd74hc4067_ns = cg.esphome_ns.namespace("cd74hc4067")
|
||||||
|
|
||||||
|
CD74HC4067Component = cd74hc4067_ns.class_(
|
||||||
|
"CD74HC4067Component", cg.Component, cg.PollingComponent
|
||||||
|
)
|
||||||
|
|
||||||
|
CONF_PIN_S0 = "pin_s0"
|
||||||
|
CONF_PIN_S1 = "pin_s1"
|
||||||
|
CONF_PIN_S2 = "pin_s2"
|
||||||
|
CONF_PIN_S3 = "pin_s3"
|
||||||
|
|
||||||
|
DEFAULT_DELAY = "2ms"
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(CD74HC4067Component),
|
||||||
|
cv.Required(CONF_PIN_S0): pins.internal_gpio_output_pin_schema,
|
||||||
|
cv.Required(CONF_PIN_S1): pins.internal_gpio_output_pin_schema,
|
||||||
|
cv.Required(CONF_PIN_S2): pins.internal_gpio_output_pin_schema,
|
||||||
|
cv.Required(CONF_PIN_S3): pins.internal_gpio_output_pin_schema,
|
||||||
|
cv.Optional(
|
||||||
|
CONF_DELAY, default=DEFAULT_DELAY
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
pin_s0 = await cg.gpio_pin_expression(config[CONF_PIN_S0])
|
||||||
|
cg.add(var.set_pin_s0(pin_s0))
|
||||||
|
pin_s1 = await cg.gpio_pin_expression(config[CONF_PIN_S1])
|
||||||
|
cg.add(var.set_pin_s1(pin_s1))
|
||||||
|
pin_s2 = await cg.gpio_pin_expression(config[CONF_PIN_S2])
|
||||||
|
cg.add(var.set_pin_s2(pin_s2))
|
||||||
|
pin_s3 = await cg.gpio_pin_expression(config[CONF_PIN_S3])
|
||||||
|
cg.add(var.set_pin_s3(pin_s3))
|
||||||
|
|
||||||
|
cg.add(var.set_switch_delay(config[CONF_DELAY]))
|
86
esphome/components/cd74hc4067/cd74hc4067.cpp
Normal file
86
esphome/components/cd74hc4067/cd74hc4067.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "cd74hc4067.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace cd74hc4067 {
|
||||||
|
|
||||||
|
static const char *const TAG = "cd74hc4067";
|
||||||
|
|
||||||
|
float CD74HC4067Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
void CD74HC4067Component::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up CD74HC4067...");
|
||||||
|
|
||||||
|
this->pin_s0_->setup();
|
||||||
|
this->pin_s1_->setup();
|
||||||
|
this->pin_s2_->setup();
|
||||||
|
this->pin_s3_->setup();
|
||||||
|
|
||||||
|
// set other pin, so that activate_pin will really switch
|
||||||
|
this->active_pin_ = 1;
|
||||||
|
this->activate_pin(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CD74HC4067Component::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "CD74HC4067 Multiplexer:");
|
||||||
|
LOG_PIN(" S0 Pin: ", this->pin_s0_);
|
||||||
|
LOG_PIN(" S1 Pin: ", this->pin_s1_);
|
||||||
|
LOG_PIN(" S2 Pin: ", this->pin_s2_);
|
||||||
|
LOG_PIN(" S3 Pin: ", this->pin_s3_);
|
||||||
|
ESP_LOGCONFIG(TAG, "switch delay: %d", this->switch_delay_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CD74HC4067Component::activate_pin(uint8_t pin) {
|
||||||
|
if (this->active_pin_ != pin) {
|
||||||
|
ESP_LOGD(TAG, "switch to input %d", pin);
|
||||||
|
|
||||||
|
static int mux_channel[16][4] = {
|
||||||
|
{0, 0, 0, 0}, // channel 0
|
||||||
|
{1, 0, 0, 0}, // channel 1
|
||||||
|
{0, 1, 0, 0}, // channel 2
|
||||||
|
{1, 1, 0, 0}, // channel 3
|
||||||
|
{0, 0, 1, 0}, // channel 4
|
||||||
|
{1, 0, 1, 0}, // channel 5
|
||||||
|
{0, 1, 1, 0}, // channel 6
|
||||||
|
{1, 1, 1, 0}, // channel 7
|
||||||
|
{0, 0, 0, 1}, // channel 8
|
||||||
|
{1, 0, 0, 1}, // channel 9
|
||||||
|
{0, 1, 0, 1}, // channel 10
|
||||||
|
{1, 1, 0, 1}, // channel 11
|
||||||
|
{0, 0, 1, 1}, // channel 12
|
||||||
|
{1, 0, 1, 1}, // channel 13
|
||||||
|
{0, 1, 1, 1}, // channel 14
|
||||||
|
{1, 1, 1, 1} // channel 15
|
||||||
|
};
|
||||||
|
this->pin_s0_->digital_write(mux_channel[pin][0]);
|
||||||
|
this->pin_s1_->digital_write(mux_channel[pin][1]);
|
||||||
|
this->pin_s2_->digital_write(mux_channel[pin][2]);
|
||||||
|
this->pin_s3_->digital_write(mux_channel[pin][3]);
|
||||||
|
// small delay is needed to let the multiplexer switch
|
||||||
|
delay(this->switch_delay_);
|
||||||
|
this->active_pin_ = pin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CD74HC4067Sensor::CD74HC4067Sensor(CD74HC4067Component *parent) : parent_(parent) {}
|
||||||
|
|
||||||
|
void CD74HC4067Sensor::update() {
|
||||||
|
float value_v = this->sample();
|
||||||
|
this->publish_state(value_v);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CD74HC4067Sensor::get_setup_priority() const { return this->parent_->get_setup_priority() - 1.0f; }
|
||||||
|
|
||||||
|
float CD74HC4067Sensor::sample() {
|
||||||
|
this->parent_->activate_pin(this->pin_);
|
||||||
|
return this->source_->sample();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CD74HC4067Sensor::dump_config() {
|
||||||
|
LOG_SENSOR(TAG, "CD74HC4067 Sensor", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Pin: %u", this->pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cd74hc4067
|
||||||
|
} // namespace esphome
|
65
esphome/components/cd74hc4067/cd74hc4067.h
Normal file
65
esphome/components/cd74hc4067/cd74hc4067.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace cd74hc4067 {
|
||||||
|
|
||||||
|
class CD74HC4067Component : public Component {
|
||||||
|
public:
|
||||||
|
/// Set up the internal sensor array.
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
/// setting pin active by setting the right combination of the four multiplexer input pins
|
||||||
|
void activate_pin(uint8_t pin);
|
||||||
|
|
||||||
|
/// set the pin connected to multiplexer control pin 0
|
||||||
|
void set_pin_s0(InternalGPIOPin *pin) { this->pin_s0_ = pin; }
|
||||||
|
/// set the pin connected to multiplexer control pin 1
|
||||||
|
void set_pin_s1(InternalGPIOPin *pin) { this->pin_s1_ = pin; }
|
||||||
|
/// set the pin connected to multiplexer control pin 2
|
||||||
|
void set_pin_s2(InternalGPIOPin *pin) { this->pin_s2_ = pin; }
|
||||||
|
/// set the pin connected to multiplexer control pin 3
|
||||||
|
void set_pin_s3(InternalGPIOPin *pin) { this->pin_s3_ = pin; }
|
||||||
|
|
||||||
|
/// set the delay needed after an input switch
|
||||||
|
void set_switch_delay(uint32_t switch_delay) { this->switch_delay_ = switch_delay; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
InternalGPIOPin *pin_s0_;
|
||||||
|
InternalGPIOPin *pin_s1_;
|
||||||
|
InternalGPIOPin *pin_s2_;
|
||||||
|
InternalGPIOPin *pin_s3_;
|
||||||
|
/// the currently active pin
|
||||||
|
uint8_t active_pin_;
|
||||||
|
uint32_t switch_delay_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CD74HC4067Sensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler {
|
||||||
|
public:
|
||||||
|
CD74HC4067Sensor(CD74HC4067Component *parent);
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
/// `HARDWARE_LATE` setup priority.
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
void set_pin(uint8_t pin) { this->pin_ = pin; }
|
||||||
|
void set_source(voltage_sampler::VoltageSampler *source) { this->source_ = source; }
|
||||||
|
|
||||||
|
float sample() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CD74HC4067Component *parent_;
|
||||||
|
/// The sampling source to read values from.
|
||||||
|
voltage_sampler::VoltageSampler *source_;
|
||||||
|
|
||||||
|
uint8_t pin_;
|
||||||
|
};
|
||||||
|
} // namespace cd74hc4067
|
||||||
|
} // namespace esphome
|
55
esphome/components/cd74hc4067/sensor.py
Normal file
55
esphome/components/cd74hc4067/sensor.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor, voltage_sampler
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
CONF_SENSOR,
|
||||||
|
CONF_NUMBER,
|
||||||
|
ICON_FLASH,
|
||||||
|
UNIT_VOLT,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
)
|
||||||
|
from . import cd74hc4067_ns, CD74HC4067Component
|
||||||
|
|
||||||
|
DEPENDENCIES = ["cd74hc4067"]
|
||||||
|
|
||||||
|
CD74HC4067Sensor = cd74hc4067_ns.class_(
|
||||||
|
"CD74HC4067Sensor",
|
||||||
|
sensor.Sensor,
|
||||||
|
cg.PollingComponent,
|
||||||
|
voltage_sampler.VoltageSampler,
|
||||||
|
)
|
||||||
|
|
||||||
|
CONF_CD74HC4067_ID = "cd74hc4067_id"
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT,
|
||||||
|
accuracy_decimals=3,
|
||||||
|
device_class=DEVICE_CLASS_VOLTAGE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
icon=ICON_FLASH,
|
||||||
|
)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(CD74HC4067Sensor),
|
||||||
|
cv.GenerateID(CONF_CD74HC4067_ID): cv.use_id(CD74HC4067Component),
|
||||||
|
cv.Required(CONF_NUMBER): cv.int_range(0, 15),
|
||||||
|
cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
parent = await cg.get_variable(config[CONF_CD74HC4067_ID])
|
||||||
|
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID], parent)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await sensor.register_sensor(var, config)
|
||||||
|
cg.add(var.set_pin(config[CONF_NUMBER]))
|
||||||
|
|
||||||
|
sens = await cg.get_variable(config[CONF_SENSOR])
|
||||||
|
cg.add(var.set_source(sens))
|
@ -378,6 +378,10 @@ sensor:
|
|||||||
- 400 -> 500
|
- 400 -> 500
|
||||||
- -50 -> -1000
|
- -50 -> -1000
|
||||||
- -100 -> -10000
|
- -100 -> -10000
|
||||||
|
- platform: cd74hc4067
|
||||||
|
id: cd74hc4067_0
|
||||||
|
number: 0
|
||||||
|
sensor: my_sensor
|
||||||
- platform: resistance
|
- platform: resistance
|
||||||
sensor: my_sensor
|
sensor: my_sensor
|
||||||
configuration: DOWNSTREAM
|
configuration: DOWNSTREAM
|
||||||
@ -1345,3 +1349,9 @@ dsmr:
|
|||||||
daly_bms:
|
daly_bms:
|
||||||
update_interval: 20s
|
update_interval: 20s
|
||||||
uart_id: uart1
|
uart_id: uart1
|
||||||
|
|
||||||
|
cd74hc4067:
|
||||||
|
pin_s0: GPIO12
|
||||||
|
pin_s1: GPIO13
|
||||||
|
pin_s2: GPIO14
|
||||||
|
pin_s3: GPIO15
|
||||||
|
Loading…
Reference in New Issue
Block a user