hlw8012: fix constants for BL0937 (#1973)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Adrián Panella 2021-07-04 18:09:09 -05:00 committed by GitHub
parent 52d19fa43d
commit d31040f5d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 12 deletions

View file

@ -6,15 +6,32 @@ namespace hlw8012 {
static const char *const TAG = "hlw8012"; static const char *const TAG = "hlw8012";
// valid for HLW8012 and CSE7759
static const uint32_t HLW8012_CLOCK_FREQUENCY = 3579000; static const uint32_t HLW8012_CLOCK_FREQUENCY = 3579000;
static const float HLW8012_REFERENCE_VOLTAGE = 2.43f;
void HLW8012Component::setup() { void HLW8012Component::setup() {
float reference_voltage = 0;
ESP_LOGCONFIG(TAG, "Setting up HLW8012..."); ESP_LOGCONFIG(TAG, "Setting up HLW8012...");
this->sel_pin_->setup(); this->sel_pin_->setup();
this->sel_pin_->digital_write(this->current_mode_); this->sel_pin_->digital_write(this->current_mode_);
this->cf_store_.pulse_counter_setup(this->cf_pin_); this->cf_store_.pulse_counter_setup(this->cf_pin_);
this->cf1_store_.pulse_counter_setup(this->cf1_pin_); this->cf1_store_.pulse_counter_setup(this->cf1_pin_);
// Initialize multipliers
if (this->sensor_model_ == HLW8012_SENSOR_MODEL_BL0937) {
reference_voltage = 1.218f;
this->power_multiplier_ =
reference_voltage * reference_voltage * this->voltage_divider_ / this->current_resistor_ / 1721506.0f;
this->current_multiplier_ = reference_voltage / this->current_resistor_ / 94638.0f;
this->voltage_multiplier_ = reference_voltage * this->voltage_divider_ / 15397.0f;
} else {
// HLW8012 and CSE7759 have same reference specs
reference_voltage = 2.43f;
this->power_multiplier_ = reference_voltage * reference_voltage * this->voltage_divider_ / this->current_resistor_ *
64.0f / 24.0f / HLW8012_CLOCK_FREQUENCY;
this->current_multiplier_ = reference_voltage / this->current_resistor_ * 512.0f / 24.0f / HLW8012_CLOCK_FREQUENCY;
this->voltage_multiplier_ = reference_voltage * this->voltage_divider_ * 256.0f / HLW8012_CLOCK_FREQUENCY;
}
} }
void HLW8012Component::dump_config() { void HLW8012Component::dump_config() {
ESP_LOGCONFIG(TAG, "HLW8012:"); ESP_LOGCONFIG(TAG, "HLW8012:");
@ -49,25 +66,18 @@ void HLW8012Component::update() {
return; return;
} }
const float v_ref_squared = HLW8012_REFERENCE_VOLTAGE * HLW8012_REFERENCE_VOLTAGE; float power = cf_hz * this->power_multiplier_;
const float power_multiplier_micros =
64000000.0f * v_ref_squared * this->voltage_divider_ / this->current_resistor_ / 24.0f / HLW8012_CLOCK_FREQUENCY;
float power = cf_hz * power_multiplier_micros / 1000000.0f;
if (this->change_mode_at_ != 0) { if (this->change_mode_at_ != 0) {
// Only read cf1 after one cycle. Apparently it's quite unstable after being changed. // Only read cf1 after one cycle. Apparently it's quite unstable after being changed.
if (this->current_mode_) { if (this->current_mode_) {
const float current_multiplier_micros = float current = cf1_hz * this->current_multiplier_;
512000000.0f * HLW8012_REFERENCE_VOLTAGE / this->current_resistor_ / 24.0f / HLW8012_CLOCK_FREQUENCY;
float current = cf1_hz * current_multiplier_micros / 1000000.0f;
ESP_LOGD(TAG, "Got power=%.1fW, current=%.1fA", power, current); ESP_LOGD(TAG, "Got power=%.1fW, current=%.1fA", power, current);
if (this->current_sensor_ != nullptr) { if (this->current_sensor_ != nullptr) {
this->current_sensor_->publish_state(current); this->current_sensor_->publish_state(current);
} }
} else { } else {
const float voltage_multiplier_micros = float voltage = cf1_hz * this->voltage_multiplier_;
256000000.0f * HLW8012_REFERENCE_VOLTAGE * this->voltage_divider_ / HLW8012_CLOCK_FREQUENCY;
float voltage = cf1_hz * voltage_multiplier_micros / 1000000.0f;
ESP_LOGD(TAG, "Got power=%.1fW, voltage=%.1fV", power, voltage); ESP_LOGD(TAG, "Got power=%.1fW, voltage=%.1fV", power, voltage);
if (this->voltage_sensor_ != nullptr) { if (this->voltage_sensor_ != nullptr) {
this->voltage_sensor_->publish_state(voltage); this->voltage_sensor_->publish_state(voltage);
@ -81,7 +91,7 @@ void HLW8012Component::update() {
if (this->energy_sensor_ != nullptr) { if (this->energy_sensor_ != nullptr) {
cf_total_pulses_ += raw_cf; cf_total_pulses_ += raw_cf;
float energy = cf_total_pulses_ * power_multiplier_micros / 3600 / 1000000.0f; float energy = cf_total_pulses_ * this->power_multiplier_ / 3600;
this->energy_sensor_->publish_state(energy); this->energy_sensor_->publish_state(energy);
} }

View file

@ -10,6 +10,12 @@ namespace hlw8012 {
enum HLW8012InitialMode { HLW8012_INITIAL_MODE_CURRENT = 0, HLW8012_INITIAL_MODE_VOLTAGE }; enum HLW8012InitialMode { HLW8012_INITIAL_MODE_CURRENT = 0, HLW8012_INITIAL_MODE_VOLTAGE };
enum HLW8012SensorModels {
HLW8012_SENSOR_MODEL_HLW8012 = 0,
HLW8012_SENSOR_MODEL_CSE7759,
HLW8012_SENSOR_MODEL_BL0937
};
class HLW8012Component : public PollingComponent { class HLW8012Component : public PollingComponent {
public: public:
void setup() override; void setup() override;
@ -20,6 +26,7 @@ class HLW8012Component : public PollingComponent {
void set_initial_mode(HLW8012InitialMode initial_mode) { void set_initial_mode(HLW8012InitialMode initial_mode) {
current_mode_ = initial_mode == HLW8012_INITIAL_MODE_CURRENT; current_mode_ = initial_mode == HLW8012_INITIAL_MODE_CURRENT;
} }
void set_sensor_model(HLW8012SensorModels sensor_model) { sensor_model_ = sensor_model; }
void set_change_mode_every(uint32_t change_mode_every) { change_mode_every_ = change_mode_every; } void set_change_mode_every(uint32_t change_mode_every) { change_mode_every_ = change_mode_every; }
void set_current_resistor(float current_resistor) { current_resistor_ = current_resistor; } void set_current_resistor(float current_resistor) { current_resistor_ = current_resistor; }
void set_voltage_divider(float voltage_divider) { voltage_divider_ = voltage_divider; } void set_voltage_divider(float voltage_divider) { voltage_divider_ = voltage_divider; }
@ -38,6 +45,7 @@ class HLW8012Component : public PollingComponent {
uint32_t change_mode_every_{8}; uint32_t change_mode_every_{8};
float current_resistor_{0.001}; float current_resistor_{0.001};
float voltage_divider_{2351}; float voltage_divider_{2351};
HLW8012SensorModels sensor_model_{HLW8012_SENSOR_MODEL_HLW8012};
uint64_t cf_total_pulses_{0}; uint64_t cf_total_pulses_{0};
GPIOPin *sel_pin_; GPIOPin *sel_pin_;
GPIOPin *cf_pin_; GPIOPin *cf_pin_;
@ -48,6 +56,10 @@ class HLW8012Component : public PollingComponent {
sensor::Sensor *current_sensor_{nullptr}; sensor::Sensor *current_sensor_{nullptr};
sensor::Sensor *power_sensor_{nullptr}; sensor::Sensor *power_sensor_{nullptr};
sensor::Sensor *energy_sensor_{nullptr}; sensor::Sensor *energy_sensor_{nullptr};
float voltage_multiplier_{0.0f};
float current_multiplier_{0.0f};
float power_multiplier_{0.0f};
}; };
} // namespace hlw8012 } // namespace hlw8012

View file

@ -11,6 +11,7 @@ from esphome.const import (
CONF_POWER, CONF_POWER,
CONF_ENERGY, CONF_ENERGY,
CONF_SEL_PIN, CONF_SEL_PIN,
CONF_MODEL,
CONF_VOLTAGE, CONF_VOLTAGE,
CONF_VOLTAGE_DIVIDER, CONF_VOLTAGE_DIVIDER,
DEVICE_CLASS_CURRENT, DEVICE_CLASS_CURRENT,
@ -31,11 +32,19 @@ AUTO_LOAD = ["pulse_counter"]
hlw8012_ns = cg.esphome_ns.namespace("hlw8012") hlw8012_ns = cg.esphome_ns.namespace("hlw8012")
HLW8012Component = hlw8012_ns.class_("HLW8012Component", cg.PollingComponent) HLW8012Component = hlw8012_ns.class_("HLW8012Component", cg.PollingComponent)
HLW8012InitialMode = hlw8012_ns.enum("HLW8012InitialMode") HLW8012InitialMode = hlw8012_ns.enum("HLW8012InitialMode")
HLW8012SensorModels = hlw8012_ns.enum("HLW8012SensorModels")
INITIAL_MODES = { INITIAL_MODES = {
CONF_CURRENT: HLW8012InitialMode.HLW8012_INITIAL_MODE_CURRENT, CONF_CURRENT: HLW8012InitialMode.HLW8012_INITIAL_MODE_CURRENT,
CONF_VOLTAGE: HLW8012InitialMode.HLW8012_INITIAL_MODE_VOLTAGE, CONF_VOLTAGE: HLW8012InitialMode.HLW8012_INITIAL_MODE_VOLTAGE,
} }
MODELS = {
"HLW8012": HLW8012SensorModels.HLW8012_SENSOR_MODEL_HLW8012,
"CSE7759": HLW8012SensorModels.HLW8012_SENSOR_MODEL_CSE7759,
"BL0937": HLW8012SensorModels.HLW8012_SENSOR_MODEL_BL0937,
}
CONF_CF1_PIN = "cf1_pin" CONF_CF1_PIN = "cf1_pin"
CONF_CF_PIN = "cf_pin" CONF_CF_PIN = "cf_pin"
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
@ -62,6 +71,7 @@ CONFIG_SCHEMA = cv.Schema(
), ),
cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance, cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance,
cv.Optional(CONF_VOLTAGE_DIVIDER, default=2351): cv.positive_float, cv.Optional(CONF_VOLTAGE_DIVIDER, default=2351): cv.positive_float,
cv.Optional(CONF_MODEL, default="HLW8012"): cv.enum(MODELS, upper=True),
cv.Optional(CONF_CHANGE_MODE_EVERY, default=8): cv.All( cv.Optional(CONF_CHANGE_MODE_EVERY, default=8): cv.All(
cv.uint32_t, cv.Range(min=1) cv.uint32_t, cv.Range(min=1)
), ),
@ -99,3 +109,4 @@ async def to_code(config):
cg.add(var.set_voltage_divider(config[CONF_VOLTAGE_DIVIDER])) cg.add(var.set_voltage_divider(config[CONF_VOLTAGE_DIVIDER]))
cg.add(var.set_change_mode_every(config[CONF_CHANGE_MODE_EVERY])) cg.add(var.set_change_mode_every(config[CONF_CHANGE_MODE_EVERY]))
cg.add(var.set_initial_mode(INITIAL_MODES[config[CONF_INITIAL_MODE]])) cg.add(var.set_initial_mode(INITIAL_MODES[config[CONF_INITIAL_MODE]]))
cg.add(var.set_sensor_model(config[CONF_MODEL]))

View file

@ -514,6 +514,7 @@ sensor:
voltage_divider: 2351 voltage_divider: 2351
change_mode_every: 16 change_mode_every: 16
initial_mode: VOLTAGE initial_mode: VOLTAGE
model: hlw8012
- platform: total_daily_energy - platform: total_daily_energy
power_id: hlw8012_power power_id: hlw8012_power
name: 'HLW8012 Total Daily Energy' name: 'HLW8012 Total Daily Energy'