mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
DAC7678 support (#3441)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
29045b0435
commit
fb2467f6f0
6 changed files with 235 additions and 0 deletions
|
@ -52,6 +52,7 @@ esphome/components/cs5460a/* @balrog-kun
|
|||
esphome/components/cse7761/* @berfenger
|
||||
esphome/components/ct_clamp/* @jesserockz
|
||||
esphome/components/current_based/* @djwmarcx
|
||||
esphome/components/dac7678/* @NickB1
|
||||
esphome/components/daly_bms/* @s1lvi0
|
||||
esphome/components/dashboard_import/* @esphome/core
|
||||
esphome/components/debug/* @OttoWinter
|
||||
|
|
32
esphome/components/dac7678/__init__.py
Normal file
32
esphome/components/dac7678/__init__.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ["output"]
|
||||
CODEOWNERS = ["@NickB1"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
MULTI_CONF = True
|
||||
|
||||
dac7678_ns = cg.esphome_ns.namespace("dac7678")
|
||||
DAC7678Output = dac7678_ns.class_("DAC7678Output", cg.Component, i2c.I2CDevice)
|
||||
CONF_INTERNAL_REFERENCE = "internal_reference"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(DAC7678Output),
|
||||
cv.Optional(CONF_INTERNAL_REFERENCE, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x48))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
cg.add(var.set_internal_reference(config[CONF_INTERNAL_REFERENCE]))
|
||||
await i2c.register_i2c_device(var, config)
|
||||
return var
|
83
esphome/components/dac7678/dac7678_output.cpp
Normal file
83
esphome/components/dac7678/dac7678_output.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include "dac7678_output.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace dac7678 {
|
||||
|
||||
static const char *const TAG = "dac7678";
|
||||
|
||||
static const uint8_t DAC7678_REG_INPUT_N = 0x00;
|
||||
static const uint8_t DAC7678_REG_SELECT_UPDATE_N = 0x10;
|
||||
static const uint8_t DAC7678_REG_WRITE_N_UPDATE_ALL = 0x20;
|
||||
static const uint8_t DAC7678_REG_WRITE_N_UPDATE_N = 0x30;
|
||||
static const uint8_t DAC7678_REG_POWER = 0x40;
|
||||
static const uint8_t DAC7678_REG_CLEAR_CODE = 0x50;
|
||||
static const uint8_t DAC7678_REG_LDAC = 0x60;
|
||||
static const uint8_t DAC7678_REG_SOFTWARE_RESET = 0x70;
|
||||
static const uint8_t DAC7678_REG_INTERNAL_REF_0 = 0x80;
|
||||
static const uint8_t DAC7678_REG_INTERNAL_REF_1 = 0x90;
|
||||
|
||||
void DAC7678Output::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up DAC7678OutputComponent...");
|
||||
|
||||
ESP_LOGV(TAG, "Resetting device...");
|
||||
|
||||
// Reset device
|
||||
if (!this->write_byte_16(DAC7678_REG_SOFTWARE_RESET, 0x0000)) {
|
||||
ESP_LOGE(TAG, "Reset failed");
|
||||
this->mark_failed();
|
||||
return;
|
||||
} else
|
||||
ESP_LOGV(TAG, "Reset succeeded");
|
||||
|
||||
delayMicroseconds(1000);
|
||||
|
||||
// Set internal reference
|
||||
if (this->internal_reference_) {
|
||||
if (!this->write_byte_16(DAC7678_REG_INTERNAL_REF_0, 1 << 4)) {
|
||||
ESP_LOGE(TAG, "Set internal reference failed");
|
||||
this->mark_failed();
|
||||
return;
|
||||
} else
|
||||
ESP_LOGV(TAG, "Internal reference enabled");
|
||||
}
|
||||
}
|
||||
|
||||
void DAC7678Output::dump_config() {
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Setting up DAC7678 failed!");
|
||||
} else
|
||||
ESP_LOGCONFIG(TAG, "DAC7678 initialised");
|
||||
}
|
||||
|
||||
void DAC7678Output::register_channel(DAC7678Channel *channel) {
|
||||
auto c = channel->channel_;
|
||||
this->min_channel_ = std::min(this->min_channel_, c);
|
||||
this->max_channel_ = std::max(this->max_channel_, c);
|
||||
channel->set_parent(this);
|
||||
ESP_LOGV(TAG, "Registered channel: %01u", channel->channel_);
|
||||
}
|
||||
|
||||
void DAC7678Output::set_channel_value_(uint8_t channel, uint16_t value) {
|
||||
if (this->dac_input_reg_[channel] != value) {
|
||||
ESP_LOGV(TAG, "Channel %01u: input_reg=%04u ", channel, value);
|
||||
|
||||
if (!this->write_byte_16(DAC7678_REG_WRITE_N_UPDATE_N | channel, value << 4)) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->dac_input_reg_[channel] = value;
|
||||
this->status_clear_warning();
|
||||
}
|
||||
|
||||
void DAC7678Channel::write_state(float state) {
|
||||
const float input_rounded = roundf(state * this->full_scale_);
|
||||
auto input = static_cast<uint16_t>(input_rounded);
|
||||
this->parent_->set_channel_value_(this->channel_, input);
|
||||
}
|
||||
|
||||
} // namespace dac7678
|
||||
} // namespace esphome
|
55
esphome/components/dac7678/dac7678_output.h
Normal file
55
esphome/components/dac7678/dac7678_output.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace dac7678 {
|
||||
|
||||
class DAC7678Output;
|
||||
|
||||
class DAC7678Channel : public output::FloatOutput, public Parented<DAC7678Output> {
|
||||
public:
|
||||
void set_channel(uint8_t channel) { channel_ = channel; }
|
||||
|
||||
protected:
|
||||
friend class DAC7678Output;
|
||||
|
||||
const uint16_t full_scale_ = 0xFFF;
|
||||
|
||||
void write_state(float state) override;
|
||||
|
||||
uint8_t channel_;
|
||||
};
|
||||
|
||||
/// DAC7678 float output component.
|
||||
class DAC7678Output : public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
DAC7678Output() {}
|
||||
|
||||
void register_channel(DAC7678Channel *channel);
|
||||
|
||||
void set_internal_reference(const bool value) { this->internal_reference_ = value; }
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
protected:
|
||||
friend DAC7678Channel;
|
||||
|
||||
bool internal_reference_;
|
||||
|
||||
void set_channel_value_(uint8_t channel, uint16_t value);
|
||||
|
||||
uint8_t min_channel_{0xFF};
|
||||
uint8_t max_channel_{0x00};
|
||||
uint16_t dac_input_reg_[8] = {
|
||||
0,
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace dac7678
|
||||
} // namespace esphome
|
27
esphome/components/dac7678/output.py
Normal file
27
esphome/components/dac7678/output.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
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 DAC7678Output, dac7678_ns
|
||||
|
||||
DEPENDENCIES = ["dac7678"]
|
||||
|
||||
DAC7678Channel = dac7678_ns.class_("DAC7678Channel", output.FloatOutput)
|
||||
CONF_DAC7678_ID = "dac7678_id"
|
||||
|
||||
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(DAC7678Channel),
|
||||
cv.GenerateID(CONF_DAC7678_ID): cv.use_id(DAC7678Output),
|
||||
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
paren = await cg.get_variable(config[CONF_DAC7678_ID])
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||
cg.add(paren.register_channel(var))
|
||||
await output.register_output(var, config)
|
||||
return var
|
|
@ -80,6 +80,11 @@ sx1509:
|
|||
mcp3204:
|
||||
cs_pin: GPIO23
|
||||
|
||||
dac7678:
|
||||
address: 0x4A
|
||||
id: dac7678_hub1
|
||||
internal_reference: true
|
||||
|
||||
sensor:
|
||||
- platform: homeassistant
|
||||
entity_id: sensor.hello_world
|
||||
|
@ -518,6 +523,38 @@ output:
|
|||
pipsolar_id: inverter0
|
||||
battery_recharge_voltage:
|
||||
id: inverter0_battery_recharge_voltage_out
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 0
|
||||
id: 'dac7678_1_ch0'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 1
|
||||
id: 'dac7678_1_ch1'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 2
|
||||
id: 'dac7678_1_ch2'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 3
|
||||
id: 'dac7678_1_ch3'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 4
|
||||
id: 'dac7678_1_ch4'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 5
|
||||
id: 'dac7678_1_ch5'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 6
|
||||
id: 'dac7678_1_ch6'
|
||||
- platform: dac7678
|
||||
dac7678_id: 'dac7678_hub1'
|
||||
channel: 7
|
||||
id: 'dac7678_1_ch7'
|
||||
esp32_camera:
|
||||
name: ESP-32 Camera
|
||||
data_pins: [GPIO17, GPIO35, GPIO34, GPIO5, GPIO39, GPIO18, GPIO36, GPIO19]
|
||||
|
|
Loading…
Reference in a new issue