[bq76972] Expose the sensors as a sensor platform (#21006)

This commit is contained in:
J. Nick Koston
2026-10-17 15:09:14 -10:00
committed by GitHub
parent e6f1ed8d51
commit 42e849967a
5 changed files with 142 additions and 104 deletions
+3 -57
View File
@@ -1,18 +1,10 @@
from esphome import automation
import esphome.codegen as cg
from esphome.components import i2c, sensor
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ADDRESS,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_VOLT,
)
from esphome.const import CONF_ADDRESS
from esphome.types import ConfigType
AUTO_LOAD = ["sensor"]
CODEOWNERS = ["@limpkin"]
DEPENDENCIES = ["i2c"]
DOMAIN = "bq76972"
@@ -25,37 +17,7 @@ BQ76972Component = bq76972_ns.class_(
CONF_REG_DISABLED = "reg_disabled"
CONF_CRC_ENABLED = "crc_enabled"
CONF_STACK_VOLTAGE = "stack_voltage"
# Ordered as the chip reports them, starting at command 0x68
CONF_TEMPERATURES = [
"internal_temperature",
"cfetoff_temperature",
"dfetoff_temperature",
"alert_temperature",
"ts1_temperature",
"ts2_temperature",
"ts3_temperature",
"hdq_temperature",
"dchg_temperature",
"ddsg_temperature",
]
CONF_CELL_VOLTAGES = [f"cell_{i}_voltage" for i in range(1, 17)]
voltage_sensor_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=3,
device_class=DEVICE_CLASS_VOLTAGE,
state_class=STATE_CLASS_MEASUREMENT,
)
temp_sensor_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
)
CONF_BQ76972_ID = "bq76972_id"
CONFIG_SCHEMA = (
cv.Schema(
@@ -63,9 +25,6 @@ CONFIG_SCHEMA = (
cv.GenerateID(): cv.declare_id(BQ76972Component),
cv.Optional(CONF_CRC_ENABLED, default=False): cv.boolean,
cv.Optional(CONF_REG_DISABLED, default=False): cv.boolean,
cv.Optional(CONF_STACK_VOLTAGE): voltage_sensor_schema,
**{cv.Optional(key): voltage_sensor_schema for key in CONF_CELL_VOLTAGES},
**{cv.Optional(key): temp_sensor_schema for key in CONF_TEMPERATURES},
}
)
.extend(i2c.i2c_device_schema(0x08))
@@ -79,19 +38,6 @@ async def to_code(config: ConfigType) -> None:
cg.add(var.set_crc_mode(config[CONF_CRC_ENABLED]))
cg.add(var.set_reg_disable(config[CONF_REG_DISABLED]))
sensors = sensor.sub_sensors(config)
await sensors(CONF_STACK_VOLTAGE, var.set_stack_voltage_sensor)
for idx, key in enumerate(CONF_TEMPERATURES):
if (conf := config.get(key)) is not None:
sens = await sensor.new_sensor(conf)
cg.add(var.set_temperature_sensor(sens, idx))
for idx, key in enumerate(CONF_CELL_VOLTAGES):
if (conf := config.get(key)) is not None:
sens = await sensor.new_sensor(conf)
cg.add(var.set_cell_sensor(sens, idx))
BQ76972_PROGRAM_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value(
{
+8
View File
@@ -172,10 +172,12 @@ const LogString *BQ76972Component::configure_() {
const bool write_regs = !regs_disabled;
bool write_thermistors = false;
#ifdef USE_SENSOR
for (size_t i = 1; i < BQ76972_NUM_TEMPERATURES; i++) {
if (i != BQ76972_TS1_INDEX && this->temperature_sensors_[i] != nullptr)
write_thermistors = true;
}
#endif
if (write_regs || write_thermistors) {
if (!this->enter_cfg_update_())
@@ -201,12 +203,14 @@ const LogString *BQ76972Component::write_config_(bool write_regs) {
!this->write_subcommand_(BQ76972_MEM_REG0_CONFIG, &zero, 1))
return LOG_STR("Writing regulator config failed");
}
#ifdef USE_SENSOR
for (size_t i = 1; i < BQ76972_NUM_TEMPERATURES; i++) {
if (i == BQ76972_TS1_INDEX || this->temperature_sensors_[i] == nullptr)
continue;
if (!this->write_subcommand_(BQ76972_MEM_TEMP_PIN_CONFIG_BASE + i, &BQ76972_PIN_CONFIG_THERMISTOR, 1))
return LOG_STR("Writing thermistor pin config failed");
}
#endif
return nullptr;
}
@@ -248,6 +252,7 @@ void BQ76972Component::program_i2c_address(uint8_t address) {
ESP_LOGI(TAG, "I2C address set to 0x%02X", address);
}
#ifdef USE_SENSOR
template<size_t N> static bool any_set(const std::array<sensor::Sensor *, N> &sensors) {
for (auto *sensor : sensors) {
if (sensor != nullptr)
@@ -294,5 +299,8 @@ void BQ76972Component::update() {
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
}
#else
void BQ76972Component::update() {}
#endif
} // namespace esphome::bq76972
+8 -1
View File
@@ -1,8 +1,11 @@
#pragma once
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#ifdef USE_SENSOR
#include "esphome/components/sensor/sensor.h"
#endif
#include <array>
@@ -19,9 +22,11 @@ class BQ76972Component final : public PollingComponent, public i2c::I2CDevice {
void set_crc_mode(bool crc_mode) { this->crc_mode_ = crc_mode; }
void set_reg_disable(bool reg_disable) { this->reg_disable_ = reg_disable; }
#ifdef USE_SENSOR
void set_stack_voltage_sensor(sensor::Sensor *s) { this->stack_voltage_sensor_ = s; }
void set_cell_sensor(sensor::Sensor *s, size_t index) { this->cell_sensors_[index] = s; }
void set_temperature_sensor(sensor::Sensor *s, size_t index) { this->temperature_sensors_[index] = s; }
#endif
void program_i2c_address(uint8_t address);
@@ -43,9 +48,11 @@ class BQ76972Component final : public PollingComponent, public i2c::I2CDevice {
bool reg_disable_{false};
bool crc_mode_{false};
#ifdef USE_SENSOR
sensor::Sensor *stack_voltage_sensor_{nullptr};
std::array<sensor::Sensor *, BQ76972_NUM_CELLS> cell_sensors_{};
std::array<sensor::Sensor *, BQ76972_NUM_TEMPERATURES> temperature_sensors_{};
#endif
};
} // namespace esphome::bq76972
+73
View File
@@ -0,0 +1,73 @@
import esphome.codegen as cg
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_VOLT,
)
from esphome.types import ConfigType
from . import CONF_BQ76972_ID, BQ76972Component
DEPENDENCIES = ["bq76972"]
CONF_STACK_VOLTAGE = "stack_voltage"
# Ordered as the chip reports them, starting at command 0x68
CONF_TEMPERATURES = [
"internal_temperature",
"cfetoff_temperature",
"dfetoff_temperature",
"alert_temperature",
"ts1_temperature",
"ts2_temperature",
"ts3_temperature",
"hdq_temperature",
"dchg_temperature",
"ddsg_temperature",
]
CONF_CELL_VOLTAGES = [f"cell_{i}_voltage" for i in range(1, 17)]
voltage_sensor_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT,
accuracy_decimals=3,
device_class=DEVICE_CLASS_VOLTAGE,
state_class=STATE_CLASS_MEASUREMENT,
)
temp_sensor_schema = sensor.sensor_schema(
unit_of_measurement=UNIT_CELSIUS,
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_BQ76972_ID): cv.use_id(BQ76972Component),
cv.Optional(CONF_STACK_VOLTAGE): voltage_sensor_schema,
**{cv.Optional(key): voltage_sensor_schema for key in CONF_CELL_VOLTAGES},
**{cv.Optional(key): temp_sensor_schema for key in CONF_TEMPERATURES},
}
)
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_BQ76972_ID])
sensors = sensor.sub_sensors(config)
await sensors(CONF_STACK_VOLTAGE, hub.set_stack_voltage_sensor)
for idx, key in enumerate(CONF_TEMPERATURES):
if (conf := config.get(key)) is not None:
sens = await sensor.new_sensor(conf)
cg.add(hub.set_temperature_sensor(sens, idx))
for idx, key in enumerate(CONF_CELL_VOLTAGES):
if (conf := config.get(key)) is not None:
sens = await sensor.new_sensor(conf)
cg.add(hub.set_cell_sensor(sens, idx))
+50 -46
View File
@@ -1,60 +1,64 @@
bq76972:
id: bq76972_id
id: bms
i2c_id: i2c_bus
address: 0x08
crc_enabled: true
reg_disabled: true
update_interval: 10s
stack_voltage:
name: "Pack Total Voltage"
internal_temperature:
name: "Temperature - Internal"
ts1_temperature:
name: "Temperature - Pin TS1"
ts2_temperature:
name: "Temperature - Pin TS2"
ts3_temperature:
name: "Temperature - Pin TS3"
hdq_temperature:
name: "Temperature - Pin HDQ"
cell_1_voltage:
name: "Cell 1 Voltage"
cell_2_voltage:
name: "Cell 2 Voltage"
cell_3_voltage:
name: "Cell 3 Voltage"
cell_4_voltage:
name: "Cell 4 Voltage"
cell_5_voltage:
name: "Cell 5 Voltage"
cell_6_voltage:
name: "Cell 6 Voltage"
cell_7_voltage:
name: "Cell 7 Voltage"
cell_8_voltage:
name: "Cell 8 Voltage"
cell_9_voltage:
name: "Cell 9 Voltage"
cell_10_voltage:
name: "Cell 10 Voltage"
cell_11_voltage:
name: "Cell 11 Voltage"
cell_12_voltage:
name: "Cell 12 Voltage"
cell_13_voltage:
name: "Cell 13 Voltage"
cell_14_voltage:
name: "Cell 14 Voltage"
cell_15_voltage:
name: "Cell 15 Voltage"
cell_16_voltage:
name: "Cell 16 Voltage"
button:
- platform: template
name: "Program BQ I2C Address"
on_press:
- bq76972.program_i2c_address:
id: bq76972_id
id: bms
address: 0x09
- bq76972.program_i2c_address: !lambda "return 0x08;"
sensor:
- platform: bq76972
bq76972_id: bms
stack_voltage:
name: "Pack Total Voltage"
internal_temperature:
name: "Temperature - Internal"
ts1_temperature:
name: "Temperature - Pin TS1"
ts2_temperature:
name: "Temperature - Pin TS2"
ts3_temperature:
name: "Temperature - Pin TS3"
hdq_temperature:
name: "Temperature - Pin HDQ"
cell_1_voltage:
name: "Cell 1 Voltage"
cell_2_voltage:
name: "Cell 2 Voltage"
cell_3_voltage:
name: "Cell 3 Voltage"
cell_4_voltage:
name: "Cell 4 Voltage"
cell_5_voltage:
name: "Cell 5 Voltage"
cell_6_voltage:
name: "Cell 6 Voltage"
cell_7_voltage:
name: "Cell 7 Voltage"
cell_8_voltage:
name: "Cell 8 Voltage"
cell_9_voltage:
name: "Cell 9 Voltage"
cell_10_voltage:
name: "Cell 10 Voltage"
cell_11_voltage:
name: "Cell 11 Voltage"
cell_12_voltage:
name: "Cell 12 Voltage"
cell_13_voltage:
name: "Cell 13 Voltage"
cell_14_voltage:
name: "Cell 14 Voltage"
cell_15_voltage:
name: "Cell 15 Voltage"
cell_16_voltage:
name: "Cell 16 Voltage"