mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 00:18:11 +01:00
Add spi support for ade7953 (#5439)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
7ac9caa169
commit
defe8ac97b
18 changed files with 834 additions and 241 deletions
|
@ -17,6 +17,9 @@ esphome/components/ac_dimmer/* @glmnet
|
||||||
esphome/components/adc/* @esphome/core
|
esphome/components/adc/* @esphome/core
|
||||||
esphome/components/adc128s102/* @DeerMaximum
|
esphome/components/adc128s102/* @DeerMaximum
|
||||||
esphome/components/addressable_light/* @justfalter
|
esphome/components/addressable_light/* @justfalter
|
||||||
|
esphome/components/ade7953/* @angelnu
|
||||||
|
esphome/components/ade7953_i2c/* @angelnu
|
||||||
|
esphome/components/ade7953_spi/* @angelnu
|
||||||
esphome/components/airthings_ble/* @jeromelaban
|
esphome/components/airthings_ble/* @jeromelaban
|
||||||
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
|
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
|
||||||
esphome/components/airthings_wave_mini/* @ncareau
|
esphome/components/airthings_wave_mini/* @ncareau
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
CODEOWNERS = ["@angelnu"]
|
|
@ -1,53 +0,0 @@
|
||||||
#include "ade7953.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace ade7953 {
|
|
||||||
|
|
||||||
static const char *const TAG = "ade7953";
|
|
||||||
|
|
||||||
void ADE7953::dump_config() {
|
|
||||||
ESP_LOGCONFIG(TAG, "ADE7953:");
|
|
||||||
LOG_PIN(" IRQ Pin: ", irq_pin_);
|
|
||||||
LOG_I2C_DEVICE(this);
|
|
||||||
LOG_UPDATE_INTERVAL(this);
|
|
||||||
LOG_SENSOR(" ", "Voltage Sensor", this->voltage_sensor_);
|
|
||||||
LOG_SENSOR(" ", "Current A Sensor", this->current_a_sensor_);
|
|
||||||
LOG_SENSOR(" ", "Current B Sensor", this->current_b_sensor_);
|
|
||||||
LOG_SENSOR(" ", "Active Power A Sensor", this->active_power_a_sensor_);
|
|
||||||
LOG_SENSOR(" ", "Active Power B Sensor", this->active_power_b_sensor_);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ADE_PUBLISH_(name, val, factor) \
|
|
||||||
if (err == i2c::ERROR_OK && this->name##_sensor_) { \
|
|
||||||
float value = (val) / (factor); \
|
|
||||||
this->name##_sensor_->publish_state(value); \
|
|
||||||
}
|
|
||||||
#define ADE_PUBLISH(name, val, factor) ADE_PUBLISH_(name, val, factor)
|
|
||||||
|
|
||||||
void ADE7953::update() {
|
|
||||||
if (!this->is_setup_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t val;
|
|
||||||
i2c::ErrorCode err = ade_read_32_(0x0312, &val);
|
|
||||||
ADE_PUBLISH(active_power_a, (int32_t) val, 154.0f);
|
|
||||||
err = ade_read_32_(0x0313, &val);
|
|
||||||
ADE_PUBLISH(active_power_b, (int32_t) val, 154.0f);
|
|
||||||
err = ade_read_32_(0x031A, &val);
|
|
||||||
ADE_PUBLISH(current_a, (uint32_t) val, 100000.0f);
|
|
||||||
err = ade_read_32_(0x031B, &val);
|
|
||||||
ADE_PUBLISH(current_b, (uint32_t) val, 100000.0f);
|
|
||||||
err = ade_read_32_(0x031C, &val);
|
|
||||||
ADE_PUBLISH(voltage, (uint32_t) val, 26000.0f);
|
|
||||||
|
|
||||||
// auto apparent_power_a = this->ade_read_<int32_t>(0x0310);
|
|
||||||
// auto apparent_power_b = this->ade_read_<int32_t>(0x0311);
|
|
||||||
// auto reactive_power_a = this->ade_read_<int32_t>(0x0314);
|
|
||||||
// auto reactive_power_b = this->ade_read_<int32_t>(0x0315);
|
|
||||||
// auto power_factor_a = this->ade_read_<int16_t>(0x010A);
|
|
||||||
// auto power_factor_b = this->ade_read_<int16_t>(0x010B);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ade7953
|
|
||||||
} // namespace esphome
|
|
|
@ -1,97 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include "esphome/core/hal.h"
|
|
||||||
#include "esphome/components/i2c/i2c.h"
|
|
||||||
#include "esphome/components/sensor/sensor.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace ade7953 {
|
|
||||||
|
|
||||||
class ADE7953 : public i2c::I2CDevice, public PollingComponent {
|
|
||||||
public:
|
|
||||||
void set_irq_pin(InternalGPIOPin *irq_pin) { irq_pin_ = irq_pin; }
|
|
||||||
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
|
||||||
void set_current_a_sensor(sensor::Sensor *current_a_sensor) { current_a_sensor_ = current_a_sensor; }
|
|
||||||
void set_current_b_sensor(sensor::Sensor *current_b_sensor) { current_b_sensor_ = current_b_sensor; }
|
|
||||||
void set_active_power_a_sensor(sensor::Sensor *active_power_a_sensor) {
|
|
||||||
active_power_a_sensor_ = active_power_a_sensor;
|
|
||||||
}
|
|
||||||
void set_active_power_b_sensor(sensor::Sensor *active_power_b_sensor) {
|
|
||||||
active_power_b_sensor_ = active_power_b_sensor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() override {
|
|
||||||
if (this->irq_pin_ != nullptr) {
|
|
||||||
this->irq_pin_->setup();
|
|
||||||
}
|
|
||||||
this->set_timeout(100, [this]() {
|
|
||||||
this->ade_write_8_(0x0010, 0x04);
|
|
||||||
this->ade_write_8_(0x00FE, 0xAD);
|
|
||||||
this->ade_write_16_(0x0120, 0x0030);
|
|
||||||
this->is_setup_ = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_config() override;
|
|
||||||
|
|
||||||
void update() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
i2c::ErrorCode ade_write_8_(uint16_t reg, uint8_t value) {
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
data.push_back(reg >> 8);
|
|
||||||
data.push_back(reg >> 0);
|
|
||||||
data.push_back(value);
|
|
||||||
return write(data.data(), data.size());
|
|
||||||
}
|
|
||||||
i2c::ErrorCode ade_write_16_(uint16_t reg, uint16_t value) {
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
data.push_back(reg >> 8);
|
|
||||||
data.push_back(reg >> 0);
|
|
||||||
data.push_back(value >> 8);
|
|
||||||
data.push_back(value >> 0);
|
|
||||||
return write(data.data(), data.size());
|
|
||||||
}
|
|
||||||
i2c::ErrorCode ade_write_32_(uint16_t reg, uint32_t value) {
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
data.push_back(reg >> 8);
|
|
||||||
data.push_back(reg >> 0);
|
|
||||||
data.push_back(value >> 24);
|
|
||||||
data.push_back(value >> 16);
|
|
||||||
data.push_back(value >> 8);
|
|
||||||
data.push_back(value >> 0);
|
|
||||||
return write(data.data(), data.size());
|
|
||||||
}
|
|
||||||
i2c::ErrorCode ade_read_32_(uint16_t reg, uint32_t *value) {
|
|
||||||
uint8_t reg_data[2];
|
|
||||||
reg_data[0] = reg >> 8;
|
|
||||||
reg_data[1] = reg >> 0;
|
|
||||||
i2c::ErrorCode err = write(reg_data, 2);
|
|
||||||
if (err != i2c::ERROR_OK)
|
|
||||||
return err;
|
|
||||||
uint8_t recv[4];
|
|
||||||
err = read(recv, 4);
|
|
||||||
if (err != i2c::ERROR_OK)
|
|
||||||
return err;
|
|
||||||
*value = 0;
|
|
||||||
*value |= ((uint32_t) recv[0]) << 24;
|
|
||||||
*value |= ((uint32_t) recv[1]) << 16;
|
|
||||||
*value |= ((uint32_t) recv[2]) << 8;
|
|
||||||
*value |= ((uint32_t) recv[3]);
|
|
||||||
return i2c::ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
InternalGPIOPin *irq_pin_{nullptr};
|
|
||||||
bool is_setup_{false};
|
|
||||||
sensor::Sensor *voltage_sensor_{nullptr};
|
|
||||||
sensor::Sensor *current_a_sensor_{nullptr};
|
|
||||||
sensor::Sensor *current_b_sensor_{nullptr};
|
|
||||||
sensor::Sensor *active_power_a_sensor_{nullptr};
|
|
||||||
sensor::Sensor *active_power_b_sensor_{nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ade7953
|
|
||||||
} // namespace esphome
|
|
|
@ -1,90 +1,5 @@
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import sensor, i2c
|
|
||||||
from esphome import pins
|
CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid(
|
||||||
from esphome.const import (
|
"The ade7953 sensor component has been renamed to ade7953_i2c."
|
||||||
CONF_ID,
|
|
||||||
CONF_IRQ_PIN,
|
|
||||||
CONF_VOLTAGE,
|
|
||||||
DEVICE_CLASS_CURRENT,
|
|
||||||
DEVICE_CLASS_POWER,
|
|
||||||
DEVICE_CLASS_VOLTAGE,
|
|
||||||
STATE_CLASS_MEASUREMENT,
|
|
||||||
UNIT_AMPERE,
|
|
||||||
UNIT_VOLT,
|
|
||||||
UNIT_WATT,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
DEPENDENCIES = ["i2c"]
|
|
||||||
|
|
||||||
ade7953_ns = cg.esphome_ns.namespace("ade7953")
|
|
||||||
ADE7953 = ade7953_ns.class_("ADE7953", cg.PollingComponent, i2c.I2CDevice)
|
|
||||||
|
|
||||||
CONF_CURRENT_A = "current_a"
|
|
||||||
CONF_CURRENT_B = "current_b"
|
|
||||||
CONF_ACTIVE_POWER_A = "active_power_a"
|
|
||||||
CONF_ACTIVE_POWER_B = "active_power_b"
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
|
||||||
cv.Schema(
|
|
||||||
{
|
|
||||||
cv.GenerateID(): cv.declare_id(ADE7953),
|
|
||||||
cv.Optional(CONF_IRQ_PIN): pins.internal_gpio_input_pin_schema,
|
|
||||||
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
|
|
||||||
unit_of_measurement=UNIT_VOLT,
|
|
||||||
accuracy_decimals=1,
|
|
||||||
device_class=DEVICE_CLASS_VOLTAGE,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(
|
|
||||||
unit_of_measurement=UNIT_AMPERE,
|
|
||||||
accuracy_decimals=2,
|
|
||||||
device_class=DEVICE_CLASS_CURRENT,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(
|
|
||||||
unit_of_measurement=UNIT_AMPERE,
|
|
||||||
accuracy_decimals=2,
|
|
||||||
device_class=DEVICE_CLASS_CURRENT,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(
|
|
||||||
unit_of_measurement=UNIT_WATT,
|
|
||||||
accuracy_decimals=1,
|
|
||||||
device_class=DEVICE_CLASS_POWER,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(
|
|
||||||
unit_of_measurement=UNIT_WATT,
|
|
||||||
accuracy_decimals=1,
|
|
||||||
device_class=DEVICE_CLASS_POWER,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.extend(cv.polling_component_schema("60s"))
|
|
||||||
.extend(i2c.i2c_device_schema(0x38))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
|
||||||
await cg.register_component(var, config)
|
|
||||||
await i2c.register_i2c_device(var, config)
|
|
||||||
|
|
||||||
if irq_pin_config := config.get(CONF_IRQ_PIN):
|
|
||||||
irq_pin = await cg.gpio_pin_expression(irq_pin_config)
|
|
||||||
cg.add(var.set_irq_pin(irq_pin))
|
|
||||||
|
|
||||||
for key in [
|
|
||||||
CONF_VOLTAGE,
|
|
||||||
CONF_CURRENT_A,
|
|
||||||
CONF_CURRENT_B,
|
|
||||||
CONF_ACTIVE_POWER_A,
|
|
||||||
CONF_ACTIVE_POWER_B,
|
|
||||||
]:
|
|
||||||
if key not in config:
|
|
||||||
continue
|
|
||||||
conf = config[key]
|
|
||||||
sens = await sensor.new_sensor(conf)
|
|
||||||
cg.add(getattr(var, f"set_{key}_sensor")(sens))
|
|
||||||
|
|
196
esphome/components/ade7953_base/__init__.py
Normal file
196
esphome/components/ade7953_base/__init__.py
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome import pins
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_IRQ_PIN,
|
||||||
|
CONF_VOLTAGE,
|
||||||
|
CONF_FREQUENCY,
|
||||||
|
DEVICE_CLASS_CURRENT,
|
||||||
|
DEVICE_CLASS_APPARENT_POWER,
|
||||||
|
DEVICE_CLASS_POWER,
|
||||||
|
DEVICE_CLASS_REACTIVE_POWER,
|
||||||
|
DEVICE_CLASS_POWER_FACTOR,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
DEVICE_CLASS_FREQUENCY,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_VOLT,
|
||||||
|
UNIT_HERTZ,
|
||||||
|
UNIT_AMPERE,
|
||||||
|
UNIT_VOLT_AMPS,
|
||||||
|
UNIT_WATT,
|
||||||
|
UNIT_VOLT_AMPS_REACTIVE,
|
||||||
|
UNIT_PERCENT,
|
||||||
|
)
|
||||||
|
|
||||||
|
CONF_CURRENT_A = "current_a"
|
||||||
|
CONF_CURRENT_B = "current_b"
|
||||||
|
CONF_ACTIVE_POWER_A = "active_power_a"
|
||||||
|
CONF_ACTIVE_POWER_B = "active_power_b"
|
||||||
|
CONF_APPARENT_POWER_A = "apparent_power_a"
|
||||||
|
CONF_APPARENT_POWER_B = "apparent_power_b"
|
||||||
|
CONF_REACTIVE_POWER_A = "reactive_power_a"
|
||||||
|
CONF_REACTIVE_POWER_B = "reactive_power_b"
|
||||||
|
CONF_POWER_FACTOR_A = "power_factor_a"
|
||||||
|
CONF_POWER_FACTOR_B = "power_factor_b"
|
||||||
|
CONF_VOLTAGE_PGA_GAIN = "voltage_pga_gain"
|
||||||
|
CONF_CURRENT_PGA_GAIN_A = "current_pga_gain_a"
|
||||||
|
CONF_CURRENT_PGA_GAIN_B = "current_pga_gain_b"
|
||||||
|
CONF_VOLTAGE_GAIN = "voltage_gain"
|
||||||
|
CONF_CURRENT_GAIN_A = "current_gain_a"
|
||||||
|
CONF_CURRENT_GAIN_B = "current_gain_b"
|
||||||
|
CONF_ACTIVE_POWER_GAIN_A = "active_power_gain_a"
|
||||||
|
CONF_ACTIVE_POWER_GAIN_B = "active_power_gain_b"
|
||||||
|
PGA_GAINS = {
|
||||||
|
"1x": 0b000,
|
||||||
|
"2x": 0b001,
|
||||||
|
"4x": 0b010,
|
||||||
|
"8x": 0b011,
|
||||||
|
"16x": 0b100,
|
||||||
|
"22x": 0b101,
|
||||||
|
}
|
||||||
|
|
||||||
|
ade7953_base_ns = cg.esphome_ns.namespace("ade7953_base")
|
||||||
|
ADE7953 = ade7953_base_ns.class_("ADE7953", cg.PollingComponent)
|
||||||
|
|
||||||
|
ADE7953_CONFIG_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_IRQ_PIN): pins.internal_gpio_input_pin_schema,
|
||||||
|
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_VOLTAGE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_HERTZ,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_FREQUENCY,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_AMPERE,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_CURRENT,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_AMPERE,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_CURRENT,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_WATT,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_WATT,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_APPARENT_POWER_A): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT_AMPS,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_APPARENT_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_APPARENT_POWER_B): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT_AMPS,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_APPARENT_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_REACTIVE_POWER_A): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_REACTIVE_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_REACTIVE_POWER_B): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_REACTIVE_POWER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_POWER_FACTOR_A): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_PERCENT,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_POWER_FACTOR,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_POWER_FACTOR_B): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_PERCENT,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_POWER_FACTOR,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_VOLTAGE_PGA_GAIN,
|
||||||
|
default="1x",
|
||||||
|
): cv.one_of(*PGA_GAINS, lower=True),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_CURRENT_PGA_GAIN_A,
|
||||||
|
default="1x",
|
||||||
|
): cv.one_of(*PGA_GAINS, lower=True),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_CURRENT_PGA_GAIN_B,
|
||||||
|
default="1x",
|
||||||
|
): cv.one_of(*PGA_GAINS, lower=True),
|
||||||
|
cv.Optional(CONF_VOLTAGE_GAIN, default=0x400000): cv.hex_int_range(
|
||||||
|
min=0x100000, max=0x800000
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CURRENT_GAIN_A, default=0x400000): cv.hex_int_range(
|
||||||
|
min=0x100000, max=0x800000
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CURRENT_GAIN_B, default=0x400000): cv.hex_int_range(
|
||||||
|
min=0x100000, max=0x800000
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ACTIVE_POWER_GAIN_A, default=0x400000): cv.hex_int_range(
|
||||||
|
min=0x100000, max=0x800000
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ACTIVE_POWER_GAIN_B, default=0x400000): cv.hex_int_range(
|
||||||
|
min=0x100000, max=0x800000
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(cv.polling_component_schema("60s"))
|
||||||
|
|
||||||
|
|
||||||
|
async def register_ade7953(var, config):
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
if irq_pin_config := config.get(CONF_IRQ_PIN):
|
||||||
|
irq_pin = await cg.gpio_pin_expression(irq_pin_config)
|
||||||
|
cg.add(var.set_irq_pin(irq_pin))
|
||||||
|
|
||||||
|
cg.add(var.set_pga_v(PGA_GAINS[config.get(CONF_VOLTAGE_PGA_GAIN)]))
|
||||||
|
cg.add(var.set_pga_ia(PGA_GAINS[config.get(CONF_CURRENT_PGA_GAIN_A)]))
|
||||||
|
cg.add(var.set_pga_ib(PGA_GAINS[config.get(CONF_CURRENT_PGA_GAIN_B)]))
|
||||||
|
cg.add(var.set_vgain(config.get(CONF_VOLTAGE_GAIN)))
|
||||||
|
cg.add(var.set_aigain(config.get(CONF_CURRENT_GAIN_A)))
|
||||||
|
cg.add(var.set_bigain(config.get(CONF_CURRENT_GAIN_B)))
|
||||||
|
cg.add(var.set_awgain(config.get(CONF_ACTIVE_POWER_GAIN_A)))
|
||||||
|
cg.add(var.set_bwgain(config.get(CONF_ACTIVE_POWER_GAIN_B)))
|
||||||
|
|
||||||
|
for key in [
|
||||||
|
CONF_VOLTAGE,
|
||||||
|
CONF_FREQUENCY,
|
||||||
|
CONF_CURRENT_A,
|
||||||
|
CONF_CURRENT_B,
|
||||||
|
CONF_POWER_FACTOR_A,
|
||||||
|
CONF_POWER_FACTOR_B,
|
||||||
|
CONF_APPARENT_POWER_A,
|
||||||
|
CONF_APPARENT_POWER_B,
|
||||||
|
CONF_ACTIVE_POWER_A,
|
||||||
|
CONF_ACTIVE_POWER_B,
|
||||||
|
CONF_REACTIVE_POWER_A,
|
||||||
|
CONF_REACTIVE_POWER_B,
|
||||||
|
]:
|
||||||
|
if key not in config:
|
||||||
|
continue
|
||||||
|
conf = config[key]
|
||||||
|
sens = await sensor.new_sensor(conf)
|
||||||
|
cg.add(getattr(var, f"set_{key}_sensor")(sens))
|
129
esphome/components/ade7953_base/ade7953_base.cpp
Normal file
129
esphome/components/ade7953_base/ade7953_base.cpp
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#include "ade7953_base.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_base {
|
||||||
|
|
||||||
|
static const char *const TAG = "ade7953";
|
||||||
|
|
||||||
|
void ADE7953::setup() {
|
||||||
|
if (this->irq_pin_ != nullptr) {
|
||||||
|
this->irq_pin_->setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The chip might take up to 100ms to initialise
|
||||||
|
this->set_timeout(100, [this]() {
|
||||||
|
// this->ade_write_8(0x0010, 0x04);
|
||||||
|
this->ade_write_8(0x00FE, 0xAD);
|
||||||
|
this->ade_write_16(0x0120, 0x0030);
|
||||||
|
// Set gains
|
||||||
|
this->ade_write_8(PGA_V_8, pga_v_);
|
||||||
|
this->ade_write_8(PGA_IA_8, pga_ia_);
|
||||||
|
this->ade_write_8(PGA_IB_8, pga_ib_);
|
||||||
|
this->ade_write_32(AVGAIN_32, vgain_);
|
||||||
|
this->ade_write_32(AIGAIN_32, aigain_);
|
||||||
|
this->ade_write_32(BIGAIN_32, bigain_);
|
||||||
|
this->ade_write_32(AWGAIN_32, awgain_);
|
||||||
|
this->ade_write_32(BWGAIN_32, bwgain_);
|
||||||
|
// Read back gains for debugging
|
||||||
|
this->ade_read_8(PGA_V_8, &pga_v_);
|
||||||
|
this->ade_read_8(PGA_IA_8, &pga_ia_);
|
||||||
|
this->ade_read_8(PGA_IB_8, &pga_ib_);
|
||||||
|
this->ade_read_32(AVGAIN_32, &vgain_);
|
||||||
|
this->ade_read_32(AIGAIN_32, &aigain_);
|
||||||
|
this->ade_read_32(BIGAIN_32, &bigain_);
|
||||||
|
this->ade_read_32(AWGAIN_32, &awgain_);
|
||||||
|
this->ade_read_32(BWGAIN_32, &bwgain_);
|
||||||
|
this->is_setup_ = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADE7953::dump_config() {
|
||||||
|
LOG_PIN(" IRQ Pin: ", irq_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
LOG_SENSOR(" ", "Voltage Sensor", this->voltage_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Current A Sensor", this->current_a_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Current B Sensor", this->current_b_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Power Factor A Sensor", this->power_factor_a_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Power Factor B Sensor", this->power_factor_b_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Apparent Power A Sensor", this->apparent_power_a_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Apparent Power B Sensor", this->apparent_power_b_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Active Power A Sensor", this->active_power_a_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Active Power B Sensor", this->active_power_b_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Rective Power A Sensor", this->reactive_power_a_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Reactive Power B Sensor", this->reactive_power_b_sensor_);
|
||||||
|
ESP_LOGCONFIG(TAG, " PGA_V_8: 0x%X", pga_v_);
|
||||||
|
ESP_LOGCONFIG(TAG, " PGA_IA_8: 0x%X", pga_ia_);
|
||||||
|
ESP_LOGCONFIG(TAG, " PGA_IB_8: 0x%X", pga_ib_);
|
||||||
|
ESP_LOGCONFIG(TAG, " VGAIN_32: 0x%08jX", (uintmax_t) vgain_);
|
||||||
|
ESP_LOGCONFIG(TAG, " AIGAIN_32: 0x%08jX", (uintmax_t) aigain_);
|
||||||
|
ESP_LOGCONFIG(TAG, " BIGAIN_32: 0x%08jX", (uintmax_t) bigain_);
|
||||||
|
ESP_LOGCONFIG(TAG, " AWGAIN_32: 0x%08jX", (uintmax_t) awgain_);
|
||||||
|
ESP_LOGCONFIG(TAG, " BWGAIN_32: 0x%08jX", (uintmax_t) bwgain_);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADE_PUBLISH_(name, val, factor) \
|
||||||
|
if (err == 0 && this->name##_sensor_) { \
|
||||||
|
float value = (val) / (factor); \
|
||||||
|
this->name##_sensor_->publish_state(value); \
|
||||||
|
}
|
||||||
|
#define ADE_PUBLISH(name, val, factor) ADE_PUBLISH_(name, val, factor)
|
||||||
|
|
||||||
|
void ADE7953::update() {
|
||||||
|
if (!this->is_setup_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool err;
|
||||||
|
|
||||||
|
uint32_t interrupts_a = 0;
|
||||||
|
uint32_t interrupts_b = 0;
|
||||||
|
if (this->irq_pin_ != nullptr) {
|
||||||
|
// Read and reset interrupts
|
||||||
|
this->ade_read_32(0x032E, &interrupts_a);
|
||||||
|
this->ade_read_32(0x0331, &interrupts_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t val;
|
||||||
|
uint16_t val_16;
|
||||||
|
|
||||||
|
// Power factor
|
||||||
|
err = this->ade_read_16(0x010A, &val_16);
|
||||||
|
ADE_PUBLISH(power_factor_a, (int16_t) val_16, (0x7FFF / 100.0f));
|
||||||
|
err = this->ade_read_16(0x010B, &val_16);
|
||||||
|
ADE_PUBLISH(power_factor_b, (int16_t) val_16, (0x7FFF / 100.0f));
|
||||||
|
|
||||||
|
// Apparent power
|
||||||
|
err = this->ade_read_32(0x0310, &val);
|
||||||
|
ADE_PUBLISH(apparent_power_a, (int32_t) val, 154.0f);
|
||||||
|
err = this->ade_read_32(0x0311, &val);
|
||||||
|
ADE_PUBLISH(apparent_power_b, (int32_t) val, 154.0f);
|
||||||
|
|
||||||
|
// Active power
|
||||||
|
err = this->ade_read_32(0x0312, &val);
|
||||||
|
ADE_PUBLISH(active_power_a, (int32_t) val, 154.0f);
|
||||||
|
err = this->ade_read_32(0x0313, &val);
|
||||||
|
ADE_PUBLISH(active_power_b, (int32_t) val, 154.0f);
|
||||||
|
|
||||||
|
// Reactive power
|
||||||
|
err = this->ade_read_32(0x0314, &val);
|
||||||
|
ADE_PUBLISH(reactive_power_a, (int32_t) val, 154.0f);
|
||||||
|
err = this->ade_read_32(0x0315, &val);
|
||||||
|
ADE_PUBLISH(reactive_power_b, (int32_t) val, 154.0f);
|
||||||
|
|
||||||
|
// Current
|
||||||
|
err = this->ade_read_32(0x031A, &val);
|
||||||
|
ADE_PUBLISH(current_a, (uint32_t) val, 100000.0f);
|
||||||
|
err = this->ade_read_32(0x031B, &val);
|
||||||
|
ADE_PUBLISH(current_b, (uint32_t) val, 100000.0f);
|
||||||
|
|
||||||
|
// Voltage
|
||||||
|
err = this->ade_read_32(0x031C, &val);
|
||||||
|
ADE_PUBLISH(voltage, (uint32_t) val, 26000.0f);
|
||||||
|
|
||||||
|
// Frequency
|
||||||
|
err = this->ade_read_16(0x010E, &val_16);
|
||||||
|
ADE_PUBLISH(frequency, 223750.0f, 1 + val_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ade7953_base
|
||||||
|
} // namespace esphome
|
121
esphome/components/ade7953_base/ade7953_base.h
Normal file
121
esphome/components/ade7953_base/ade7953_base.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_base {
|
||||||
|
|
||||||
|
static const uint8_t PGA_V_8 =
|
||||||
|
0x007; // PGA_V, (R/W) Default: 0x00, Unsigned, Voltage channel gain configuration (Bits[2:0])
|
||||||
|
static const uint8_t PGA_IA_8 =
|
||||||
|
0x008; // PGA_IA, (R/W) Default: 0x00, Unsigned, Current Channel A gain configuration (Bits[2:0])
|
||||||
|
static const uint8_t PGA_IB_8 =
|
||||||
|
0x009; // PGA_IB, (R/W) Default: 0x00, Unsigned, Current Channel B gain configuration (Bits[2:0])
|
||||||
|
|
||||||
|
static const uint32_t AIGAIN_32 =
|
||||||
|
0x380; // AIGAIN, (R/W) Default: 0x400000, Unsigned,Current channel gain (Current Channel A)(32 bit)
|
||||||
|
static const uint32_t AVGAIN_32 = 0x381; // AVGAIN, (R/W) Default: 0x400000, Unsigned,Voltage channel gain(32 bit)
|
||||||
|
static const uint32_t AWGAIN_32 =
|
||||||
|
0x382; // AWGAIN, (R/W) Default: 0x400000, Unsigned,Active power gain (Current Channel A)(32 bit)
|
||||||
|
static const uint32_t AVARGAIN_32 =
|
||||||
|
0x383; // AVARGAIN, (R/W) Default: 0x400000, Unsigned, Reactive power gain (Current Channel A)(32 bit)
|
||||||
|
static const uint32_t AVAGAIN_32 =
|
||||||
|
0x384; // AVAGAIN, (R/W) Default: 0x400000, Unsigned,Apparent power gain (Current Channel A)(32 bit)
|
||||||
|
|
||||||
|
static const uint32_t BIGAIN_32 =
|
||||||
|
0x38C; // BIGAIN, (R/W) Default: 0x400000, Unsigned,Current channel gain (Current Channel B)(32 bit)
|
||||||
|
static const uint32_t BVGAIN_32 = 0x38D; // BVGAIN, (R/W) Default: 0x400000, Unsigned,Voltage channel gain(32 bit)
|
||||||
|
static const uint32_t BWGAIN_32 =
|
||||||
|
0x38E; // BWGAIN, (R/W) Default: 0x400000, Unsigned,Active power gain (Current Channel B)(32 bit)
|
||||||
|
static const uint32_t BVARGAIN_32 =
|
||||||
|
0x38F; // BVARGAIN, (R/W) Default: 0x400000, Unsigned, Reactive power gain (Current Channel B)(32 bit)
|
||||||
|
static const uint32_t BVAGAIN_32 =
|
||||||
|
0x390; // BVAGAIN, (R/W) Default: 0x400000, Unsigned,Apparent power gain (Current Channel B)(32 bit)
|
||||||
|
|
||||||
|
class ADE7953 : public PollingComponent, public sensor::Sensor {
|
||||||
|
public:
|
||||||
|
void set_irq_pin(InternalGPIOPin *irq_pin) { irq_pin_ = irq_pin; }
|
||||||
|
|
||||||
|
// Set PGA input gains: 0 1x, 1 2x, 0b10 4x
|
||||||
|
void set_pga_v(uint8_t pga_v) { pga_v_ = pga_v; }
|
||||||
|
void set_pga_ia(uint8_t pga_ia) { pga_ia_ = pga_ia; }
|
||||||
|
void set_pga_ib(uint8_t pga_ib) { pga_ib_ = pga_ib; }
|
||||||
|
|
||||||
|
// Set input gains
|
||||||
|
void set_vgain(uint32_t vgain) { vgain_ = vgain; }
|
||||||
|
void set_aigain(uint32_t aigain) { aigain_ = aigain; }
|
||||||
|
void set_bigain(uint32_t bigain) { bigain_ = bigain; }
|
||||||
|
void set_awgain(uint32_t awgain) { awgain_ = awgain; }
|
||||||
|
void set_bwgain(uint32_t bwgain) { bwgain_ = bwgain; }
|
||||||
|
|
||||||
|
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||||
|
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
|
||||||
|
|
||||||
|
void set_power_factor_a_sensor(sensor::Sensor *power_factor_a) { power_factor_a_sensor_ = power_factor_a; }
|
||||||
|
void set_power_factor_b_sensor(sensor::Sensor *power_factor_b) { power_factor_b_sensor_ = power_factor_b; }
|
||||||
|
|
||||||
|
void set_current_a_sensor(sensor::Sensor *current_a_sensor) { current_a_sensor_ = current_a_sensor; }
|
||||||
|
void set_current_b_sensor(sensor::Sensor *current_b_sensor) { current_b_sensor_ = current_b_sensor; }
|
||||||
|
|
||||||
|
void set_apparent_power_a_sensor(sensor::Sensor *apparent_power_a) { apparent_power_a_sensor_ = apparent_power_a; }
|
||||||
|
void set_apparent_power_b_sensor(sensor::Sensor *apparent_power_b) { apparent_power_b_sensor_ = apparent_power_b; }
|
||||||
|
|
||||||
|
void set_active_power_a_sensor(sensor::Sensor *active_power_a_sensor) {
|
||||||
|
active_power_a_sensor_ = active_power_a_sensor;
|
||||||
|
}
|
||||||
|
void set_active_power_b_sensor(sensor::Sensor *active_power_b_sensor) {
|
||||||
|
active_power_b_sensor_ = active_power_b_sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_reactive_power_a_sensor(sensor::Sensor *reactive_power_a) { reactive_power_a_sensor_ = reactive_power_a; }
|
||||||
|
void set_reactive_power_b_sensor(sensor::Sensor *reactive_power_b) { reactive_power_b_sensor_ = reactive_power_b; }
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
InternalGPIOPin *irq_pin_{nullptr};
|
||||||
|
bool is_setup_{false};
|
||||||
|
sensor::Sensor *voltage_sensor_{nullptr};
|
||||||
|
sensor::Sensor *frequency_sensor_{nullptr};
|
||||||
|
sensor::Sensor *current_a_sensor_{nullptr};
|
||||||
|
sensor::Sensor *current_b_sensor_{nullptr};
|
||||||
|
sensor::Sensor *apparent_power_a_sensor_{nullptr};
|
||||||
|
sensor::Sensor *apparent_power_b_sensor_{nullptr};
|
||||||
|
sensor::Sensor *active_power_a_sensor_{nullptr};
|
||||||
|
sensor::Sensor *active_power_b_sensor_{nullptr};
|
||||||
|
sensor::Sensor *reactive_power_a_sensor_{nullptr};
|
||||||
|
sensor::Sensor *reactive_power_b_sensor_{nullptr};
|
||||||
|
sensor::Sensor *power_factor_a_sensor_{nullptr};
|
||||||
|
sensor::Sensor *power_factor_b_sensor_{nullptr};
|
||||||
|
uint8_t pga_v_;
|
||||||
|
uint8_t pga_ia_;
|
||||||
|
uint8_t pga_ib_;
|
||||||
|
uint32_t vgain_;
|
||||||
|
uint32_t aigain_;
|
||||||
|
uint32_t bigain_;
|
||||||
|
uint32_t awgain_;
|
||||||
|
uint32_t bwgain_;
|
||||||
|
|
||||||
|
virtual bool ade_write_8(uint16_t reg, uint8_t value) = 0;
|
||||||
|
|
||||||
|
virtual bool ade_write_16(uint16_t reg, uint16_t value) = 0;
|
||||||
|
|
||||||
|
virtual bool ade_write_32(uint16_t reg, uint32_t value) = 0;
|
||||||
|
|
||||||
|
virtual bool ade_read_8(uint16_t reg, uint8_t *value) = 0;
|
||||||
|
|
||||||
|
virtual bool ade_read_16(uint16_t reg, uint16_t *value) = 0;
|
||||||
|
|
||||||
|
virtual bool ade_read_32(uint16_t reg, uint32_t *value) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ade7953_base
|
||||||
|
} // namespace esphome
|
1
esphome/components/ade7953_i2c/__init__.py
Normal file
1
esphome/components/ade7953_i2c/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CODEOWNERS = ["@angelnu"]
|
80
esphome/components/ade7953_i2c/ade7953_i2c.cpp
Normal file
80
esphome/components/ade7953_i2c/ade7953_i2c.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include "ade7953_i2c.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_i2c {
|
||||||
|
|
||||||
|
static const char *const TAG = "ade7953";
|
||||||
|
|
||||||
|
void AdE7953I2c::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "ADE7953_i2c:");
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
ade7953_base::ADE7953::dump_config();
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_write_8(uint16_t reg, uint8_t value) {
|
||||||
|
std::vector<uint8_t> data(3);
|
||||||
|
data.push_back(reg >> 8);
|
||||||
|
data.push_back(reg >> 0);
|
||||||
|
data.push_back(value);
|
||||||
|
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_write_16(uint16_t reg, uint16_t value) {
|
||||||
|
std::vector<uint8_t> data(4);
|
||||||
|
data.push_back(reg >> 8);
|
||||||
|
data.push_back(reg >> 0);
|
||||||
|
data.push_back(value >> 8);
|
||||||
|
data.push_back(value >> 0);
|
||||||
|
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_write_32(uint16_t reg, uint32_t value) {
|
||||||
|
std::vector<uint8_t> data(6);
|
||||||
|
data.push_back(reg >> 8);
|
||||||
|
data.push_back(reg >> 0);
|
||||||
|
data.push_back(value >> 24);
|
||||||
|
data.push_back(value >> 16);
|
||||||
|
data.push_back(value >> 8);
|
||||||
|
data.push_back(value >> 0);
|
||||||
|
return this->write(data.data(), data.size()) != i2c::ERROR_OK;
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_read_8(uint16_t reg, uint8_t *value) {
|
||||||
|
uint8_t reg_data[2];
|
||||||
|
reg_data[0] = reg >> 8;
|
||||||
|
reg_data[1] = reg >> 0;
|
||||||
|
i2c::ErrorCode err = this->write(reg_data, 2);
|
||||||
|
if (err != i2c::ERROR_OK)
|
||||||
|
return true;
|
||||||
|
err = this->read(value, 1);
|
||||||
|
return (err != i2c::ERROR_OK);
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_read_16(uint16_t reg, uint16_t *value) {
|
||||||
|
uint8_t reg_data[2];
|
||||||
|
reg_data[0] = reg >> 8;
|
||||||
|
reg_data[1] = reg >> 0;
|
||||||
|
i2c::ErrorCode err = this->write(reg_data, 2);
|
||||||
|
if (err != i2c::ERROR_OK)
|
||||||
|
return true;
|
||||||
|
uint8_t recv[2];
|
||||||
|
err = this->read(recv, 2);
|
||||||
|
if (err != i2c::ERROR_OK)
|
||||||
|
return true;
|
||||||
|
*value = encode_uint16(recv[0], recv[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool AdE7953I2c::ade_read_32(uint16_t reg, uint32_t *value) {
|
||||||
|
uint8_t reg_data[2];
|
||||||
|
reg_data[0] = reg >> 8;
|
||||||
|
reg_data[1] = reg >> 0;
|
||||||
|
i2c::ErrorCode err = this->write(reg_data, 2);
|
||||||
|
if (err != i2c::ERROR_OK)
|
||||||
|
return true;
|
||||||
|
uint8_t recv[4];
|
||||||
|
err = this->read(recv, 4);
|
||||||
|
if (err != i2c::ERROR_OK)
|
||||||
|
return true;
|
||||||
|
*value = encode_uint32(recv[0], recv[1], recv[2], recv[3]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ade7953_i2c
|
||||||
|
} // namespace esphome
|
28
esphome/components/ade7953_i2c/ade7953_i2c.h
Normal file
28
esphome/components/ade7953_i2c/ade7953_i2c.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/ade7953_base/ade7953_base.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_i2c {
|
||||||
|
|
||||||
|
class AdE7953I2c : public ade7953_base::ADE7953, public i2c::I2CDevice {
|
||||||
|
public:
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ade_write_8(uint16_t reg, uint8_t value) override;
|
||||||
|
bool ade_write_16(uint16_t reg, uint16_t value) override;
|
||||||
|
bool ade_write_32(uint16_t reg, uint32_t value) override;
|
||||||
|
bool ade_read_8(uint16_t reg, uint8_t *value) override;
|
||||||
|
bool ade_read_16(uint16_t reg, uint16_t *value) override;
|
||||||
|
bool ade_read_32(uint16_t reg, uint32_t *value) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ade7953_i2c
|
||||||
|
} // namespace esphome
|
27
esphome/components/ade7953_i2c/sensor.py
Normal file
27
esphome/components/ade7953_i2c/sensor.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c, ade7953_base
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
|
||||||
|
DEPENDENCIES = ["i2c"]
|
||||||
|
AUTO_LOAD = ["ade7953_base"]
|
||||||
|
|
||||||
|
ade7953_ns = cg.esphome_ns.namespace("ade7953_i2c")
|
||||||
|
ADE7953 = ade7953_ns.class_("AdE7953I2c", ade7953_base.ADE7953, i2c.I2CDevice)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(ADE7953),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(ade7953_base.ADE7953_CONFIG_SCHEMA)
|
||||||
|
.extend(i2c.i2c_device_schema(0x38))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await i2c.register_i2c_device(var, config)
|
||||||
|
await ade7953_base.register_ade7953(var, config)
|
1
esphome/components/ade7953_spi/__init__.py
Normal file
1
esphome/components/ade7953_spi/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CODEOWNERS = ["@angelnu"]
|
81
esphome/components/ade7953_spi/ade7953_spi.cpp
Normal file
81
esphome/components/ade7953_spi/ade7953_spi.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "ade7953_spi.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_spi {
|
||||||
|
|
||||||
|
static const char *const TAG = "ade7953";
|
||||||
|
|
||||||
|
void AdE7953Spi::setup() {
|
||||||
|
this->spi_setup();
|
||||||
|
ade7953_base::ADE7953::setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdE7953Spi::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "ADE7953_spi:");
|
||||||
|
LOG_PIN(" CS Pin: ", this->cs_);
|
||||||
|
ade7953_base::ADE7953::dump_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_write_8(uint16_t reg, uint8_t value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0);
|
||||||
|
this->transfer_byte(value);
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_write_16(uint16_t reg, uint16_t value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0);
|
||||||
|
this->write_byte16(value);
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_write_32(uint16_t reg, uint32_t value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0);
|
||||||
|
this->write_byte16(value >> 16);
|
||||||
|
this->write_byte16(value & 0xFFFF);
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_read_8(uint16_t reg, uint8_t *value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0x80);
|
||||||
|
*value = this->read_byte();
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_read_16(uint16_t reg, uint16_t *value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0x80);
|
||||||
|
uint8_t recv[2];
|
||||||
|
this->read_array(recv, 4);
|
||||||
|
*value = encode_uint16(recv[0], recv[1]);
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdE7953Spi::ade_read_32(uint16_t reg, uint32_t *value) {
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(reg);
|
||||||
|
this->transfer_byte(0x80);
|
||||||
|
uint8_t recv[4];
|
||||||
|
this->read_array(recv, 4);
|
||||||
|
*value = encode_uint32(recv[0], recv[1], recv[2], recv[3]);
|
||||||
|
this->disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ade7953_spi
|
||||||
|
} // namespace esphome
|
32
esphome/components/ade7953_spi/ade7953_spi.h
Normal file
32
esphome/components/ade7953_spi/ade7953_spi.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/components/spi/spi.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/ade7953_base/ade7953_base.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ade7953_spi {
|
||||||
|
|
||||||
|
class AdE7953Spi : public ade7953_base::ADE7953,
|
||||||
|
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_LEADING,
|
||||||
|
spi::DATA_RATE_1MHZ> {
|
||||||
|
public:
|
||||||
|
void setup() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ade_write_8(uint16_t reg, uint8_t value) override;
|
||||||
|
bool ade_write_16(uint16_t reg, uint16_t value) override;
|
||||||
|
bool ade_write_32(uint16_t reg, uint32_t value) override;
|
||||||
|
bool ade_read_8(uint16_t reg, uint8_t *value) override;
|
||||||
|
bool ade_read_16(uint16_t reg, uint16_t *value) override;
|
||||||
|
bool ade_read_32(uint16_t reg, uint32_t *value) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ade7953_spi
|
||||||
|
} // namespace esphome
|
27
esphome/components/ade7953_spi/sensor.py
Normal file
27
esphome/components/ade7953_spi/sensor.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import spi, ade7953_base
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
|
||||||
|
DEPENDENCIES = ["spi"]
|
||||||
|
AUTO_LOAD = ["ade7953_base"]
|
||||||
|
|
||||||
|
ade7953_ns = cg.esphome_ns.namespace("ade7953_spi")
|
||||||
|
ADE7953 = ade7953_ns.class_("AdE7953Spi", ade7953_base.ADE7953, spi.SPIDevice)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(ADE7953),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(ade7953_base.ADE7953_CONFIG_SCHEMA)
|
||||||
|
.extend(spi.spi_device_schema())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await spi.register_spi_device(var, config)
|
||||||
|
await ade7953_base.register_ade7953(var, config)
|
|
@ -51,6 +51,15 @@ uart:
|
||||||
i2c:
|
i2c:
|
||||||
frequency: 100khz
|
frequency: 100khz
|
||||||
|
|
||||||
|
spi:
|
||||||
|
- id: spi_1
|
||||||
|
clk_pin: 12
|
||||||
|
mosi_pin: 13
|
||||||
|
miso_pin: 14
|
||||||
|
- id: spi_2
|
||||||
|
clk_pin: 32
|
||||||
|
mosi_pin: 33
|
||||||
|
|
||||||
modbus:
|
modbus:
|
||||||
uart_id: uart_1
|
uart_id: uart_1
|
||||||
flow_control_pin: 5
|
flow_control_pin: 5
|
||||||
|
@ -574,6 +583,60 @@ sensor:
|
||||||
temperature:
|
temperature:
|
||||||
name: Kuntze temperature
|
name: Kuntze temperature
|
||||||
|
|
||||||
|
- platform: ade7953_i2c
|
||||||
|
irq_pin: 16
|
||||||
|
voltage:
|
||||||
|
name: ADE7953 Voltage
|
||||||
|
current_a:
|
||||||
|
name: ADE7953 Current A
|
||||||
|
current_b:
|
||||||
|
name: ADE7953 Current B
|
||||||
|
power_factor_a:
|
||||||
|
name: "ADE7953 Power Factor A"
|
||||||
|
power_factor_b:
|
||||||
|
name: "ADE7953 Power Factor B"
|
||||||
|
apparent_power_a:
|
||||||
|
name: "ADE7953 Apparent Power A"
|
||||||
|
apparent_power_b:
|
||||||
|
name: "ADE7953 Apparent Power B"
|
||||||
|
active_power_a:
|
||||||
|
name: ADE7953 Active Power A
|
||||||
|
active_power_b:
|
||||||
|
name: ADE7953 Active Power B
|
||||||
|
reactive_power_a:
|
||||||
|
name: "ADE7953 Reactive Power A"
|
||||||
|
reactive_power_b:
|
||||||
|
name: "ADE7953 Reactive Power B"
|
||||||
|
update_interval: 1s
|
||||||
|
|
||||||
|
- platform: ade7953_spi
|
||||||
|
spi_id: spi_1
|
||||||
|
cs_pin: 04
|
||||||
|
irq_pin: 16
|
||||||
|
voltage:
|
||||||
|
name: ADE7953 Voltage
|
||||||
|
current_a:
|
||||||
|
name: ADE7953 Current A
|
||||||
|
current_b:
|
||||||
|
name: ADE7953 Current B
|
||||||
|
power_factor_a:
|
||||||
|
name: "ADE7953 Power Factor A"
|
||||||
|
power_factor_b:
|
||||||
|
name: "ADE7953 Power Factor B"
|
||||||
|
apparent_power_a:
|
||||||
|
name: "ADE7953 Apparent Power A"
|
||||||
|
apparent_power_b:
|
||||||
|
name: "ADE7953 Apparent Power B"
|
||||||
|
active_power_a:
|
||||||
|
name: ADE7953 Active Power A
|
||||||
|
active_power_b:
|
||||||
|
name: ADE7953 Active Power B
|
||||||
|
reactive_power_a:
|
||||||
|
name: "ADE7953 Reactive Power A"
|
||||||
|
reactive_power_b:
|
||||||
|
name: "ADE7953 Reactive Power B"
|
||||||
|
update_interval: 1s
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: automation_test
|
- id: automation_test
|
||||||
then:
|
then:
|
||||||
|
|
|
@ -169,7 +169,7 @@ sensor:
|
||||||
- id: custom_sensor
|
- id: custom_sensor
|
||||||
name: Custom Sensor
|
name: Custom Sensor
|
||||||
|
|
||||||
- platform: ade7953
|
- platform: ade7953_i2c
|
||||||
irq_pin: GPIO16
|
irq_pin: GPIO16
|
||||||
voltage:
|
voltage:
|
||||||
name: ADE7953 Voltage
|
name: ADE7953 Voltage
|
||||||
|
@ -180,12 +180,50 @@ sensor:
|
||||||
current_b:
|
current_b:
|
||||||
name: ADE7953 Current B
|
name: ADE7953 Current B
|
||||||
id: ade7953_current_b
|
id: ade7953_current_b
|
||||||
|
power_factor_a:
|
||||||
|
name: "ADE7953 Power Factor A"
|
||||||
|
power_factor_b:
|
||||||
|
name: "ADE7953 Power Factor B"
|
||||||
|
apparent_power_a:
|
||||||
|
name: "ADE7953 Apparent Power A"
|
||||||
|
apparent_power_b:
|
||||||
|
name: "ADE7953 Apparent Power B"
|
||||||
active_power_a:
|
active_power_a:
|
||||||
name: ADE7953 Active Power A
|
name: ADE7953 Active Power A
|
||||||
id: ade7953_active_power_a
|
|
||||||
active_power_b:
|
active_power_b:
|
||||||
name: ADE7953 Active Power B
|
name: ADE7953 Active Power B
|
||||||
id: ade7953_active_power_b
|
reactive_power_a:
|
||||||
|
name: "ADE7953 Reactive Power A"
|
||||||
|
reactive_power_b:
|
||||||
|
name: "ADE7953 Reactive Power B"
|
||||||
|
update_interval: 1s
|
||||||
|
|
||||||
|
- platform: ade7953_spi
|
||||||
|
cs_pin: GPIO04
|
||||||
|
irq_pin: GPIO16
|
||||||
|
voltage:
|
||||||
|
name: ADE7953 Voltage
|
||||||
|
current_a:
|
||||||
|
name: ADE7953 Current A
|
||||||
|
current_b:
|
||||||
|
name: ADE7953 Current B
|
||||||
|
power_factor_a:
|
||||||
|
name: "ADE7953 Power Factor A"
|
||||||
|
power_factor_b:
|
||||||
|
name: "ADE7953 Power Factor B"
|
||||||
|
apparent_power_a:
|
||||||
|
name: "ADE7953 Apparent Power A"
|
||||||
|
apparent_power_b:
|
||||||
|
name: "ADE7953 Apparent Power B"
|
||||||
|
active_power_a:
|
||||||
|
name: ADE7953 Active Power A
|
||||||
|
active_power_b:
|
||||||
|
name: ADE7953 Active Power B
|
||||||
|
reactive_power_a:
|
||||||
|
name: "ADE7953 Reactive Power A"
|
||||||
|
reactive_power_b:
|
||||||
|
name: "ADE7953 Reactive Power B"
|
||||||
|
update_interval: 1s
|
||||||
|
|
||||||
- platform: tmp102
|
- platform: tmp102
|
||||||
name: TMP102 Temperature
|
name: TMP102 Temperature
|
||||||
|
|
Loading…
Reference in a new issue