mirror of
https://github.com/esphome/esphome.git
synced 2025-04-11 05:10:34 +01:00
Add mcp4461 quad i2c digipot/rheostat component
This commit is contained in:
parent
074ac7b25c
commit
f7709e0ae5
42
esphome/components/mcp4461/__init__.py
Normal file
42
esphome/components/mcp4461/__init__.py
Normal file
@ -0,0 +1,42 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ["@p1ngb4ck"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
MULTI_CONF = True
|
||||
CONF_DISABLE_WIPER_0 = "disable_wiper_0"
|
||||
CONF_DISABLE_WIPER_1 = "disable_wiper_1"
|
||||
CONF_DISABLE_WIPER_2 = "disable_wiper_2"
|
||||
CONF_DISABLE_WIPER_3 = "disable_wiper_3"
|
||||
|
||||
mcp4461_ns = cg.esphome_ns.namespace("mcp4461")
|
||||
Mcp4461Component = mcp4461_ns.class_("Mcp4461Component", cg.Component, i2c.I2CDevice)
|
||||
CONF_MCP4461_ID = "mcp4461_id"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(Mcp4461Component),
|
||||
cv.Optional(CONF_DISABLE_WIPER_0, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DISABLE_WIPER_1, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DISABLE_WIPER_2, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DISABLE_WIPER_3, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x2C))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(
|
||||
config[CONF_ID],
|
||||
config[CONF_DISABLE_WIPER_0],
|
||||
config[CONF_DISABLE_WIPER_1],
|
||||
config[CONF_DISABLE_WIPER_2],
|
||||
config[CONF_DISABLE_WIPER_3],
|
||||
)
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
359
esphome/components/mcp4461/mcp4461.cpp
Normal file
359
esphome/components/mcp4461/mcp4461.cpp
Normal file
@ -0,0 +1,359 @@
|
||||
#include "mcp4461.h"
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace mcp4461 {
|
||||
|
||||
static const char *const TAG = "mcp4461";
|
||||
|
||||
void Mcp4461Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up mcp4461 (0x%02X)...", this->address_);
|
||||
auto err = this->write(nullptr, 0);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
this->begin_();
|
||||
}
|
||||
|
||||
void Mcp4461Component::begin_() {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (this->reg_[i].enabled) {
|
||||
this->reg_[i].state = this->get_wiper_level(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mcp4461Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "mcp4461:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Communication with mcp4461 failed!");
|
||||
}
|
||||
}
|
||||
|
||||
void Mcp4461Component::loop() {
|
||||
if (this->update_) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
// set wiper i state if changed
|
||||
if (this->reg_[i].state != this->get_wiper_level(i)) {
|
||||
this->write_wiper_level_(i, this->reg_[i].state);
|
||||
}
|
||||
// terminal register changes only applicable to wipers 0-3 !
|
||||
if (i < 4) {
|
||||
// set terminal register changes
|
||||
if (i == 0 || i == 2) {
|
||||
Mcp4461TerminalIdx terminal_connector = Mcp4461TerminalIdx::MCP4461_TERMINAL_0;
|
||||
if (i > 0) {
|
||||
terminal_connector = Mcp4461TerminalIdx::MCP4461_TERMINAL_1;
|
||||
}
|
||||
uint8_t new_terminal_value = this->calc_terminal_connector_byte_(terminal_connector);
|
||||
if (new_terminal_value != this->get_terminal_register(terminal_connector)) {
|
||||
ESP_LOGV(TAG, "updating terminal %d to new value %d", (uint8_t) terminal_connector, new_terminal_value);
|
||||
this->set_terminal_register(terminal_connector, new_terminal_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this->update_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Mcp4461Component::get_status_register() {
|
||||
uint8_t reg = 0;
|
||||
reg |= (uint8_t) Mcp4461Addresses::MCP4461_STATUS;
|
||||
reg |= (uint8_t) Mcp4461Commands::READ;
|
||||
uint16_t buf;
|
||||
if (!this->read_byte_16(reg, &buf)) {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error fetching status register value");
|
||||
return 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool Mcp4461Component::is_writing_() { return (bool) ((this->get_status_register() >> 4) & 0x01); }
|
||||
|
||||
uint8_t Mcp4461Component::get_wiper_address_(uint8_t wiper) {
|
||||
uint8_t addr;
|
||||
bool nonvolatile = false;
|
||||
if (wiper > 3) {
|
||||
nonvolatile = true;
|
||||
wiper = wiper - 4;
|
||||
}
|
||||
switch (wiper) {
|
||||
case 0:
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_VW0;
|
||||
break;
|
||||
case 1:
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_VW1;
|
||||
break;
|
||||
case 2:
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_VW2;
|
||||
break;
|
||||
case 3:
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_VW3;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "unknown wiper specified");
|
||||
return 0;
|
||||
}
|
||||
if (nonvolatile) {
|
||||
addr = addr + 0x20;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint16_t Mcp4461Component::get_wiper_level(uint8_t wiper) {
|
||||
uint8_t reg = 0;
|
||||
uint16_t buf = 0;
|
||||
reg |= this->get_wiper_address_(wiper);
|
||||
reg |= (uint8_t) Mcp4461Commands::READ;
|
||||
if (wiper > 3) {
|
||||
while (this->is_writing_()) {
|
||||
ESP_LOGV(TAG, "delaying during eeprom write");
|
||||
}
|
||||
}
|
||||
if (!this->read_byte_16(reg, &buf)) {
|
||||
this->status_set_warning();
|
||||
if (wiper > 3) {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error fetching nonvolatile wiper %d value", wiper);
|
||||
} else {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error fetching wiper %d value", wiper);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void Mcp4461Component::update_wiper_level(uint8_t wiper) {
|
||||
uint16_t data;
|
||||
data = this->get_wiper_level(wiper);
|
||||
ESP_LOGV(TAG, "Got value %d from wiper %d", data, wiper);
|
||||
this->reg_[wiper].state = data;
|
||||
}
|
||||
|
||||
void Mcp4461Component::set_wiper_level(uint8_t wiper, uint16_t value) {
|
||||
ESP_LOGV(TAG, "Setting MCP4461 wiper %d to %d!", wiper, value);
|
||||
this->reg_[wiper].state = value;
|
||||
this->update_ = true;
|
||||
}
|
||||
|
||||
void Mcp4461Component::write_wiper_level_(uint8_t wiper, uint16_t value) {
|
||||
if (wiper > 3) {
|
||||
while (this->is_writing_()) {
|
||||
ESP_LOGV(TAG, "delaying during eeprom write");
|
||||
}
|
||||
}
|
||||
this->mcp4461_write_(this->get_wiper_address_(wiper), value);
|
||||
}
|
||||
|
||||
void Mcp4461Component::enable_wiper(uint8_t wiper) {
|
||||
ESP_LOGV(TAG, "Enabling wiper %d", wiper);
|
||||
this->reg_[wiper].terminal_hw = true;
|
||||
this->update_ = true;
|
||||
}
|
||||
|
||||
void Mcp4461Component::disable_wiper(uint8_t wiper) {
|
||||
ESP_LOGV(TAG, "Disabling wiper %d", wiper);
|
||||
this->reg_[wiper].terminal_hw = false;
|
||||
this->update_ = true;
|
||||
}
|
||||
|
||||
void Mcp4461Component::increase_wiper(uint8_t wiper) {
|
||||
ESP_LOGV(TAG, "Increasing wiper %d", wiper);
|
||||
uint8_t reg = 0;
|
||||
uint8_t addr;
|
||||
addr = this->get_wiper_address_(wiper);
|
||||
reg |= addr;
|
||||
reg |= (uint8_t) Mcp4461Commands::INCREMENT;
|
||||
this->write(&this->address_, reg, sizeof(reg));
|
||||
}
|
||||
|
||||
void Mcp4461Component::decrease_wiper(uint8_t wiper) {
|
||||
ESP_LOGV(TAG, "Decreasing wiper %d", wiper);
|
||||
uint8_t reg = 0;
|
||||
uint8_t addr;
|
||||
addr = this->get_wiper_address_(wiper);
|
||||
reg |= addr;
|
||||
reg |= (uint8_t) Mcp4461Commands::DECREMENT;
|
||||
this->write(&this->address_, reg, sizeof(reg));
|
||||
}
|
||||
|
||||
uint8_t Mcp4461Component::calc_terminal_connector_byte_(Mcp4461TerminalIdx terminal_connector) {
|
||||
uint8_t i;
|
||||
if (((uint8_t) terminal_connector == 0 || (uint8_t) terminal_connector == 1)) {
|
||||
i = 0;
|
||||
} else {
|
||||
i = 2;
|
||||
}
|
||||
uint8_t new_value_byte_array[8];
|
||||
new_value_byte_array[0] = (uint8_t) this->reg_[i].terminal_b;
|
||||
new_value_byte_array[1] = (uint8_t) this->reg_[i].terminal_w;
|
||||
new_value_byte_array[2] = (uint8_t) this->reg_[i].terminal_a;
|
||||
new_value_byte_array[3] = (uint8_t) this->reg_[i].terminal_hw;
|
||||
new_value_byte_array[4] = (uint8_t) this->reg_[(i + 1)].terminal_b;
|
||||
new_value_byte_array[5] = (uint8_t) this->reg_[(i + 1)].terminal_w;
|
||||
new_value_byte_array[6] = (uint8_t) this->reg_[(i + 1)].terminal_a;
|
||||
new_value_byte_array[7] = (uint8_t) this->reg_[(i + 1)].terminal_hw;
|
||||
unsigned char new_value_byte = 0;
|
||||
uint8_t b;
|
||||
for (b = 0; b < 8; b++) {
|
||||
new_value_byte += (new_value_byte_array[b] << (7 - b));
|
||||
}
|
||||
return (uint8_t) new_value_byte;
|
||||
}
|
||||
|
||||
uint8_t Mcp4461Component::get_terminal_register(Mcp4461TerminalIdx terminal_connector) {
|
||||
uint8_t reg = 0;
|
||||
if ((uint8_t) terminal_connector == 0) {
|
||||
reg |= (uint8_t) Mcp4461Addresses::MCP4461_TCON0;
|
||||
} else {
|
||||
reg |= (uint8_t) Mcp4461Addresses::MCP4461_TCON1;
|
||||
}
|
||||
reg |= (uint8_t) Mcp4461Commands::READ;
|
||||
uint16_t buf;
|
||||
if (!this->read_byte_16(reg, &buf)) {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error fetching terminal register value");
|
||||
return 0;
|
||||
}
|
||||
return (uint8_t) (buf & 0x00ff);
|
||||
}
|
||||
|
||||
void Mcp4461Component::update_terminal_register(Mcp4461TerminalIdx terminal_connector) {
|
||||
if (((uint8_t) terminal_connector != 0 && (uint8_t) terminal_connector != 1)) {
|
||||
return;
|
||||
}
|
||||
uint8_t terminal_data;
|
||||
terminal_data = this->get_terminal_register(terminal_connector);
|
||||
ESP_LOGV(TAG, "Got terminal register %d data %0xh", (uint8_t) terminal_connector, terminal_data);
|
||||
uint8_t wiper_index = 0;
|
||||
if ((uint8_t) terminal_connector == 1) {
|
||||
wiper_index = 2;
|
||||
}
|
||||
this->reg_[wiper_index].terminal_b = ((terminal_data >> 0) & 0x01);
|
||||
this->reg_[wiper_index].terminal_w = ((terminal_data >> 1) & 0x01);
|
||||
this->reg_[wiper_index].terminal_a = ((terminal_data >> 2) & 0x01);
|
||||
this->reg_[wiper_index].terminal_hw = ((terminal_data >> 3) & 0x01);
|
||||
this->reg_[(wiper_index + 1)].terminal_b = ((terminal_data >> 4) & 0x01);
|
||||
this->reg_[(wiper_index + 1)].terminal_w = ((terminal_data >> 5) & 0x01);
|
||||
this->reg_[(wiper_index + 1)].terminal_a = ((terminal_data >> 6) & 0x01);
|
||||
this->reg_[(wiper_index + 1)].terminal_hw = ((terminal_data >> 7) & 0x01);
|
||||
}
|
||||
|
||||
void Mcp4461Component::set_terminal_register(Mcp4461TerminalIdx terminal_connector, uint8_t data) {
|
||||
uint8_t addr;
|
||||
if ((uint8_t) terminal_connector == 0) {
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_TCON0;
|
||||
} else if ((uint8_t) terminal_connector == 1) {
|
||||
addr = (uint8_t) Mcp4461Addresses::MCP4461_TCON1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
this->mcp4461_write_(addr, data);
|
||||
}
|
||||
|
||||
void Mcp4461Component::enable_terminal(uint8_t wiper, char terminal) {
|
||||
if (wiper > 3) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, "Enabling terminal %c of wiper %d", terminal, wiper);
|
||||
switch (terminal) {
|
||||
case 'h':
|
||||
this->reg_[wiper].terminal_hw = true;
|
||||
break;
|
||||
case 'a':
|
||||
this->reg_[wiper].terminal_a = true;
|
||||
break;
|
||||
case 'b':
|
||||
this->reg_[wiper].terminal_b = true;
|
||||
break;
|
||||
case 'w':
|
||||
this->reg_[wiper].terminal_w = true;
|
||||
break;
|
||||
default:
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Unknown terminal %c specified", terminal);
|
||||
return;
|
||||
}
|
||||
this->update_ = true;
|
||||
}
|
||||
|
||||
void Mcp4461Component::disable_terminal(uint8_t wiper, char terminal) {
|
||||
if (wiper > 3) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, "Disabling terminal %c of wiper %d", terminal, wiper);
|
||||
switch (terminal) {
|
||||
case 'h':
|
||||
this->reg_[wiper].terminal_hw = false;
|
||||
break;
|
||||
case 'a':
|
||||
this->reg_[wiper].terminal_a = false;
|
||||
break;
|
||||
case 'b':
|
||||
this->reg_[wiper].terminal_b = false;
|
||||
break;
|
||||
case 'w':
|
||||
this->reg_[wiper].terminal_w = false;
|
||||
break;
|
||||
default:
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Unknown terminal %c specified", terminal);
|
||||
return;
|
||||
}
|
||||
this->update_ = true;
|
||||
}
|
||||
|
||||
uint16_t Mcp4461Component::get_eeprom_value(MCP4461EEPRomLocation location) {
|
||||
uint8_t reg = 0;
|
||||
reg |= (uint8_t) (MCP4461_EEPROM_1 + ((uint8_t) location * 0x10));
|
||||
reg |= (uint8_t) Mcp4461Commands::READ;
|
||||
uint16_t buf;
|
||||
if (!this->read_byte_16(reg, &buf)) {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error fetching EEPRom location value");
|
||||
return 0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void Mcp4461Component::set_eeprom_value(MCP4461EEPRomLocation location, uint16_t value) {
|
||||
uint8_t addr = 0;
|
||||
if (value > 256) {
|
||||
return;
|
||||
} else if (value == 256) {
|
||||
addr = 1;
|
||||
}
|
||||
uint8_t data;
|
||||
addr |= (uint8_t) (MCP4461_EEPROM_1 + ((uint8_t) location * 0x10));
|
||||
data = (uint8_t) (value & 0x00ff);
|
||||
while (this->is_writing_()) {
|
||||
ESP_LOGV(TAG, "delaying during eeprom write");
|
||||
}
|
||||
this->write_byte(addr, data);
|
||||
}
|
||||
|
||||
void Mcp4461Component::mcp4461_write_(uint8_t addr, uint16_t data) {
|
||||
uint8_t reg = 0;
|
||||
if (data > 0x100) {
|
||||
return;
|
||||
}
|
||||
if (data > 0xFF) {
|
||||
reg = 1;
|
||||
}
|
||||
uint8_t value_byte;
|
||||
value_byte = (uint8_t) (data & 0x00ff);
|
||||
ESP_LOGV(TAG, "Writing value %d", data);
|
||||
reg |= addr;
|
||||
reg |= (uint8_t) Mcp4461Commands::WRITE;
|
||||
this->write_byte(reg, value_byte);
|
||||
}
|
||||
} // namespace mcp4461
|
||||
} // namespace esphome
|
104
esphome/components/mcp4461/mcp4461.h
Normal file
104
esphome/components/mcp4461/mcp4461.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace mcp4461 {
|
||||
|
||||
struct WiperState {
|
||||
bool terminal_a = true;
|
||||
bool terminal_b = true;
|
||||
bool terminal_w = true;
|
||||
bool terminal_hw = true;
|
||||
uint16_t state;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
enum class Mcp4461Defaults { WIPER_VALUE = 0x80 };
|
||||
enum class Mcp4461Commands { WRITE = 0x0, INCREMENT = 0x4, DECREMENT = 0x8, READ = 0xC };
|
||||
|
||||
enum class Mcp4461Addresses {
|
||||
MCP4461_VW0 = 0x00,
|
||||
MCP4461_VW1 = 0x10,
|
||||
MCP4461_VW2 = 0x60,
|
||||
MCP4461_VW3 = 0x70,
|
||||
MCP4461_STATUS = 0x50,
|
||||
MCP4461_TCON0 = 0x40,
|
||||
MCP4461_TCON1 = 0xA0,
|
||||
MCP4461_EEPROM_1 = 0xB0
|
||||
};
|
||||
|
||||
enum MCP4461WiperIdx {
|
||||
MCP4461_WIPER_0 = 0,
|
||||
MCP4461_WIPER_1 = 1,
|
||||
MCP4461_WIPER_2 = 2,
|
||||
MCP4461_WIPER_3 = 3,
|
||||
MCP4461_WIPER_4 = 4,
|
||||
MCP4461_WIPER_5 = 5,
|
||||
MCP4461_WIPER_6 = 6,
|
||||
MCP4461_WIPER_7 = 7
|
||||
};
|
||||
|
||||
enum MCP4461EEPRomLocation {
|
||||
MCP4461_EEPROM_0 = 0,
|
||||
MCP4461_EEPROM_1 = 1,
|
||||
MCP4461_EEPROM_2 = 2,
|
||||
MCP4461_EEPROM_3 = 3,
|
||||
MCP4461_EEPROM_4 = 4
|
||||
};
|
||||
|
||||
enum class Mcp4461TerminalIdx { MCP4461_TERMINAL_0 = 0, MCP4461_TERMINAL_1 = 1 };
|
||||
|
||||
class Mcp4461Wiper;
|
||||
|
||||
// Mcp4461Component
|
||||
class Mcp4461Component : public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
Mcp4461Component(bool disable_wiper_0, bool disable_wiper_1, bool disable_wiper_2, bool disable_wiper_3)
|
||||
: wiper_0_enabled_(false), wiper_1_enabled_(false), wiper_2_enabled_(false), wiper_3_enabled_(false) {
|
||||
this->reg_[0].enabled = this->wiper_0_enabled_;
|
||||
this->reg_[1].enabled = this->wiper_1_enabled_;
|
||||
this->reg_[2].enabled = this->wiper_2_enabled_;
|
||||
this->reg_[3].enabled = this->wiper_3_enabled_;
|
||||
}
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void loop() override;
|
||||
uint16_t get_status_register();
|
||||
uint16_t get_wiper_level(uint8_t wiper);
|
||||
void set_wiper_level(uint8_t wiper, uint16_t value);
|
||||
void update_wiper_level(uint8_t wiper);
|
||||
void enable_wiper(uint8_t wiper);
|
||||
void disable_wiper(uint8_t wiper);
|
||||
void increase_wiper(uint8_t wiper);
|
||||
void decrease_wiper(uint8_t wiper);
|
||||
void enable_terminal(uint8_t wiper, char terminal);
|
||||
void disable_terminal(uint8_t wiper, char terminal);
|
||||
void update_terminal_register(Mcp4461TerminalIdx terminal_connector);
|
||||
uint8_t get_terminal_register(Mcp4461TerminalIdx terminal_connector);
|
||||
void set_terminal_register(Mcp4461TerminalIdx terminal_connector, uint8_t data);
|
||||
uint16_t get_eeprom_value(MCP4461EEPRomLocation location);
|
||||
void set_eeprom_value(MCP4461EEPRomLocation location, uint16_t value);
|
||||
|
||||
protected:
|
||||
friend Mcp4461Wiper;
|
||||
bool is_writing_();
|
||||
uint8_t get_wiper_address_(uint8_t wiper);
|
||||
void write_wiper_level_(uint8_t wiper, uint16_t value);
|
||||
void mcp4461_write_(uint8_t addr, uint16_t data);
|
||||
uint8_t calc_terminal_connector_byte_(Mcp4461TerminalIdx terminal_connector);
|
||||
|
||||
private:
|
||||
WiperState reg_[8];
|
||||
void begin_();
|
||||
bool update_ = false;
|
||||
bool wiper_0_enabled_ = true;
|
||||
bool wiper_1_enabled_ = true;
|
||||
bool wiper_2_enabled_ = true;
|
||||
bool wiper_3_enabled_ = true;
|
||||
};
|
||||
} // namespace mcp4461
|
||||
} // namespace esphome
|
52
esphome/components/mcp4461/output/__init__.py
Normal file
52
esphome/components/mcp4461/output/__init__.py
Normal file
@ -0,0 +1,52 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import output
|
||||
from esphome.const import CONF_CHANNEL, CONF_ID
|
||||
from .. import Mcp4461Component, CONF_MCP4461_ID, mcp4461_ns
|
||||
|
||||
DEPENDENCIES = ["mcp4461"]
|
||||
|
||||
Mcp4461Wiper = mcp4461_ns.class_("Mcp4461Wiper", output.FloatOutput)
|
||||
|
||||
MCP4461WiperIdx = mcp4461_ns.enum("MCP4461WiperIdx")
|
||||
CHANNEL_OPTIONS = {
|
||||
"A": MCP4461WiperIdx.MCP4461_WIPER_0,
|
||||
"B": MCP4461WiperIdx.MCP4461_WIPER_1,
|
||||
"C": MCP4461WiperIdx.MCP4461_WIPER_2,
|
||||
"D": MCP4461WiperIdx.MCP4461_WIPER_3,
|
||||
"E": MCP4461WiperIdx.MCP4461_WIPER_4,
|
||||
"F": MCP4461WiperIdx.MCP4461_WIPER_5,
|
||||
"G": MCP4461WiperIdx.MCP4461_WIPER_6,
|
||||
"H": MCP4461WiperIdx.MCP4461_WIPER_7,
|
||||
}
|
||||
|
||||
CONF_ENABLE = "enable"
|
||||
CONF_TERMINAL_A = "terminal_a"
|
||||
CONF_TERMINAL_B = "terminal_b"
|
||||
CONF_TERMINAL_W = "terminal_w"
|
||||
|
||||
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(Mcp4461Wiper),
|
||||
cv.GenerateID(CONF_MCP4461_ID): cv.use_id(Mcp4461Component),
|
||||
cv.Required(CONF_CHANNEL): cv.enum(CHANNEL_OPTIONS, upper=True),
|
||||
cv.Optional(CONF_ENABLE, default=True): cv.boolean,
|
||||
cv.Optional(CONF_TERMINAL_A, default=True): cv.boolean,
|
||||
cv.Optional(CONF_TERMINAL_B, default=True): cv.boolean,
|
||||
cv.Optional(CONF_TERMINAL_W, default=True): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
parent = await cg.get_variable(config[CONF_MCP4461_ID])
|
||||
var = cg.new_Pvariable(
|
||||
config[CONF_ID],
|
||||
parent,
|
||||
config[CONF_CHANNEL],
|
||||
config[CONF_ENABLE],
|
||||
config[CONF_TERMINAL_A],
|
||||
config[CONF_TERMINAL_B],
|
||||
config[CONF_TERMINAL_W],
|
||||
)
|
||||
await output.register_output(var, config)
|
87
esphome/components/mcp4461/output/mcp4461_output.cpp
Normal file
87
esphome/components/mcp4461/output/mcp4461_output.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "mcp4461_output.h"
|
||||
#include <cmath>
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace mcp4461 {
|
||||
|
||||
static const char *const TAG = "mcp4461";
|
||||
|
||||
void Mcp4461Wiper::write_state(float state) {
|
||||
ESP_LOGV(TAG, "Got value %02f from frontend", state);
|
||||
const float max_taps = 256.0;
|
||||
state = state * 1000.0;
|
||||
if (state > max_taps) {
|
||||
ESP_LOGW(TAG, "Cannot set taps > 0.256 for wiper %d, clamping to 0.256!", this->wiper_);
|
||||
state = 256.0;
|
||||
}
|
||||
uint16_t taps;
|
||||
taps = static_cast<uint16_t>(state);
|
||||
ESP_LOGV(TAG, "Setting wiper %d to value %d", this->wiper_, taps);
|
||||
this->state_ = state;
|
||||
this->parent_->set_wiper_level(this->wiper_, taps);
|
||||
}
|
||||
|
||||
uint16_t Mcp4461Wiper::get_wiper_level() { return this->parent_->get_wiper_level(this->wiper_); }
|
||||
|
||||
void Mcp4461Wiper::save_level() {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot save level for nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
uint8_t nonvolatile_wiper = this->wiper_ + 4;
|
||||
this->parent_->set_wiper_level(nonvolatile_wiper, this->state_);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::enable_wiper() {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot enable nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->enable_wiper(this->wiper_);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::disable_wiper() {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot disable nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->disable_wiper(this->wiper_);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::increase_wiper() {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot increase nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->increase_wiper(this->wiper_);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::decrease_wiper() {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot decrease nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->decrease_wiper(this->wiper_);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::enable_terminal(char terminal) {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot get/set terminals nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->enable_terminal(this->wiper_, terminal);
|
||||
}
|
||||
|
||||
void Mcp4461Wiper::disable_terminal(char terminal) {
|
||||
if (this->wiper_ > 3) {
|
||||
ESP_LOGW(TAG, "Cannot get/set terminals for nonvolatile wiper %d !", this->wiper_);
|
||||
return;
|
||||
}
|
||||
this->parent_->disable_terminal(this->wiper_, terminal);
|
||||
}
|
||||
|
||||
} // namespace mcp4461
|
||||
} // namespace esphome
|
54
esphome/components/mcp4461/output/mcp4461_output.h
Normal file
54
esphome/components/mcp4461/output/mcp4461_output.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "../mcp4461.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace mcp4461 {
|
||||
|
||||
class Mcp4461Wiper : public output::FloatOutput {
|
||||
public:
|
||||
Mcp4461Wiper(Mcp4461Component *parent, MCP4461WiperIdx wiper, bool enable, bool terminal_a, bool terminal_b,
|
||||
bool terminal_w)
|
||||
: parent_(parent),
|
||||
wiper_(wiper),
|
||||
enable_(enable),
|
||||
terminal_a_(terminal_a),
|
||||
terminal_b_(terminal_b),
|
||||
terminal_w_(terminal_w) {
|
||||
// update wiper connection state
|
||||
if (!enable && wiper < 4) {
|
||||
parent->reg_[wiper].enabled = false;
|
||||
parent->disable_terminal(wiper, 'h');
|
||||
}
|
||||
if (!terminal_a && wiper < 4)
|
||||
parent->disable_terminal(wiper, 'a');
|
||||
if (!terminal_b && wiper < 4)
|
||||
parent->disable_terminal(wiper, 'b');
|
||||
if (!terminal_w && wiper < 4)
|
||||
parent->disable_terminal(wiper, 'w');
|
||||
}
|
||||
uint16_t get_wiper_level();
|
||||
void save_level();
|
||||
void enable_wiper();
|
||||
void disable_wiper();
|
||||
void increase_wiper();
|
||||
void decrease_wiper();
|
||||
void enable_terminal(char terminal);
|
||||
void disable_terminal(char terminal);
|
||||
|
||||
protected:
|
||||
void write_state(float state) override;
|
||||
Mcp4461Component *parent_;
|
||||
MCP4461WiperIdx wiper_;
|
||||
bool enable_;
|
||||
uint16_t state_;
|
||||
bool terminal_a_;
|
||||
bool terminal_b_;
|
||||
bool terminal_w_;
|
||||
};
|
||||
|
||||
} // namespace mcp4461
|
||||
} // namespace esphome
|
Loading…
x
Reference in New Issue
Block a user