From 44d00562e7201bc6b6ef5463b01bd13c5f977137 Mon Sep 17 00:00:00 2001 From: Ali Essam Date: Sun, 17 Nov 2024 23:38:10 +0100 Subject: [PATCH] [INA219] Add sleep/wake_up actions --- esphome/components/ina219/ina219.cpp | 34 ++++++++++++++++++++++++ esphome/components/ina219/ina219.h | 11 ++++++++ esphome/components/ina219/sensor.py | 39 ++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/esphome/components/ina219/ina219.cpp b/esphome/components/ina219/ina219.cpp index 2fb3bea356..e3846c4c8f 100644 --- a/esphome/components/ina219/ina219.cpp +++ b/esphome/components/ina219/ina219.cpp @@ -129,6 +129,36 @@ void INA219Component::setup() { } } +void INA219Component::sleep() { + // Set operating mode bits to power-down mode (bits 0-2 set to 0) + ESP_LOGD(TAG, "Putting INA219 to sleep"); + this->sleeping_ = true; + uint16_t config; + if (!this->read_byte_16(INA219_REGISTER_CONFIG, &config)) { + ESP_LOGD(TAG, "INA219 did not respond to sleep action, failed to read config register"); + return; + } + config &= ~0b0000000000000111; // Clear last 3 bits + if (!this->write_byte_16(INA219_REGISTER_CONFIG, config)) { + ESP_LOGD(TAG, "INA219 did not respond to sleep action, failed to write config register"); + } +} + +void INA219Component::wake_up() { + // Set operating mode bits to continuous operation of Bus and Shunt ADCs (bits 0-2 set to 1) + ESP_LOGD(TAG, "Waking up INA219"); + this->sleeping_ = false; + uint16_t config; + if (!this->read_byte_16(INA219_REGISTER_CONFIG, &config)) { + ESP_LOGD(TAG, "INA219 did not respond to wake up action, failed to read config register"); + return; + } + config |= 0b0000000000000111; // Set last 3 bits + if (!this->write_byte_16(INA219_REGISTER_CONFIG, config)) { + ESP_LOGD(TAG, "INA219 did not respond to wake up action, failed to write config register"); + } +} + void INA219Component::dump_config() { ESP_LOGCONFIG(TAG, "INA219:"); LOG_I2C_DEVICE(this); @@ -148,6 +178,10 @@ void INA219Component::dump_config() { float INA219Component::get_setup_priority() const { return setup_priority::DATA; } void INA219Component::update() { + if (this->sleeping_) { + return; + } + if (this->bus_voltage_sensor_ != nullptr) { uint16_t raw_bus_voltage; if (!this->read_byte_16(INA219_REGISTER_BUS_VOLTAGE, &raw_bus_voltage)) { diff --git a/esphome/components/ina219/ina219.h b/esphome/components/ina219/ina219.h index a6c0f2bc4c..9e4a9724e6 100644 --- a/esphome/components/ina219/ina219.h +++ b/esphome/components/ina219/ina219.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" +#include "esphome/core/automation.h" #include @@ -15,6 +16,8 @@ class INA219Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; float get_setup_priority() const override; void update() override; + void sleep(); + void wake_up(); void set_shunt_resistance_ohm(float shunt_resistance_ohm) { shunt_resistance_ohm_ = shunt_resistance_ohm; } void set_max_current_a(float max_current_a) { max_current_a_ = max_current_a; } @@ -28,12 +31,20 @@ class INA219Component : public PollingComponent, public i2c::I2CDevice { float shunt_resistance_ohm_; float max_current_a_; float max_voltage_v_; + bool sleeping_{false}; uint32_t calibration_lsb_; sensor::Sensor *bus_voltage_sensor_{nullptr}; sensor::Sensor *shunt_voltage_sensor_{nullptr}; sensor::Sensor *current_sensor_{nullptr}; sensor::Sensor *power_sensor_{nullptr}; }; +template class SleepAction : public Action, public Parented { + void play(Ts... x) override { this->parent_->sleep(); } +}; + +template class WakeUpAction : public Action, public Parented { + void play(Ts... x) override { this->parent_->wake_up(); } +}; } // namespace ina219 } // namespace esphome diff --git a/esphome/components/ina219/sensor.py b/esphome/components/ina219/sensor.py index 020be9bc6e..aa17cca309 100644 --- a/esphome/components/ina219/sensor.py +++ b/esphome/components/ina219/sensor.py @@ -1,6 +1,7 @@ +from esphome import automation import esphome.codegen as cg -import esphome.config_validation as cv from esphome.components import i2c, sensor +import esphome.config_validation as cv from esphome.const import ( CONF_BUS_VOLTAGE, CONF_CURRENT, @@ -14,8 +15,8 @@ from esphome.const import ( DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, - UNIT_VOLT, UNIT_AMPERE, + UNIT_VOLT, UNIT_WATT, ) @@ -70,6 +71,40 @@ CONFIG_SCHEMA = ( ) +SleepAction = ina219_ns.class_("SleepAction", automation.Action) +WakeUpAction = ina219_ns.class_("WakeUpAction", automation.Action) + + +@automation.register_action( + "ina219.sleep", + SleepAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(INA219Component), + } + ), +) +async def ina219_sleep_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + + +@automation.register_action( + "ina219.wake_up", + WakeUpAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(INA219Component), + } + ), +) +async def ina219_wake_up_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config)