[sensor] Add alternate calibration format for ntc (#15937)

This commit is contained in:
Clyde Stubbs
2026-05-07 06:59:22 +10:00
committed by GitHub
parent 004aa49131
commit 9301f76482
5 changed files with 50 additions and 16 deletions

View File

@@ -2,11 +2,12 @@
CODEOWNERS = ["@esphome/core"]
CONF_BYTE_ORDER = "byte_order"
CONF_CLIMATE_ID = "climate_id"
BYTE_ORDER_LITTLE = "little_endian"
BYTE_ORDER_BIG = "big_endian"
CONF_B_CONSTANT = "b_constant"
CONF_BYTE_ORDER = "byte_order"
CONF_CLIMATE_ID = "climate_id"
CONF_COLOR_DEPTH = "color_depth"
CONF_CRC_ENABLE = "crc_enable"
CONF_DATA_BITS = "data_bits"

View File

@@ -1,5 +1,6 @@
import esphome.codegen as cg
from esphome.components import i2c, sensor
from esphome.components.const import CONF_B_CONSTANT
import esphome.config_validation as cv
from esphome.const import (
CONF_BATTERY_LEVEL,
@@ -22,8 +23,6 @@ DEPENDENCIES = ["i2c"]
lc709203f_ns = cg.esphome_ns.namespace("lc709203f")
CONF_B_CONSTANT = "b_constant"
LC709203FBatteryVoltage = lc709203f_ns.enum("LC709203FBatteryVoltage")
BATTERY_VOLTAGE_OPTIONS = {
"3.7": LC709203FBatteryVoltage.LC709203F_BATTERY_VOLTAGE_3_7,

View File

@@ -2,6 +2,7 @@ from math import log
import esphome.codegen as cg
from esphome.components import sensor
from esphome.components.const import CONF_B_CONSTANT
import esphome.config_validation as cv
from esphome.const import (
CONF_CALIBRATION,
@@ -18,7 +19,6 @@ from esphome.const import (
ntc_ns = cg.esphome_ns.namespace("ntc")
NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
CONF_B_CONSTANT = "b_constant"
CONF_A = "a"
CONF_B = "b"
CONF_C = "c"

View File

@@ -4,6 +4,7 @@ import math
from esphome import automation
import esphome.codegen as cg
from esphome.components import mqtt, web_server, zigbee
from esphome.components.const import CONF_B_CONSTANT
import esphome.config_validation as cv
from esphome.const import (
CONF_ABOVE,
@@ -32,6 +33,8 @@ from esphome.const import (
CONF_OPTIMISTIC,
CONF_PERIOD,
CONF_QUANTILE,
CONF_REFERENCE_RESISTANCE,
CONF_REFERENCE_TEMPERATURE,
CONF_SEND_EVERY,
CONF_SEND_FIRST_AT,
CONF_STATE_CLASS,
@@ -1078,16 +1081,44 @@ def ntc_get_abc(value):
return a, b, c
def ntc_calc_b_constant(value):
beta = value[CONF_B_CONSTANT]
t0 = value[CONF_REFERENCE_TEMPERATURE] + ZERO_POINT
r0 = value[CONF_REFERENCE_RESISTANCE]
a = (1 / t0) - (1 / beta) * math.log(r0)
b = 1 / beta
c = 0
return a, b, c
def ntc_process_calibration(value):
if isinstance(value, dict):
value = cv.Schema(
{
cv.Required(CONF_A): cv.float_,
cv.Required(CONF_B): cv.float_,
cv.Required(CONF_C): cv.float_,
}
)(value)
a, b, c = ntc_get_abc(value)
if CONF_B_CONSTANT in value:
value = cv.Schema(
{
cv.Required(CONF_B_CONSTANT): cv.All(
cv.float_, cv.Range(min=0, min_included=False)
),
cv.Required(CONF_REFERENCE_TEMPERATURE): cv.All(
cv.temperature,
cv.Range(min=-ZERO_POINT, min_included=False),
),
cv.Required(CONF_REFERENCE_RESISTANCE): cv.All(
cv.resistance, cv.Range(min=0, min_included=False)
),
}
)(value)
a, b, c = ntc_calc_b_constant(value)
else:
value = cv.Schema(
{
cv.Required(CONF_A): cv.float_,
cv.Required(CONF_B): cv.float_,
cv.Required(CONF_C): cv.float_,
}
)(value)
a, b, c = ntc_get_abc(value)
elif isinstance(value, list):
if len(value) != 3:
raise cv.Invalid(
@@ -1097,7 +1128,7 @@ def ntc_process_calibration(value):
a, b, c = ntc_calc_steinhart_hart(value)
else:
raise cv.Invalid(
f"Calibration parameter accepts either a list for steinhart-hart calibration, or mapping for b-constant calibration, not {type(value)}"
f"Calibration parameter accepts either a list for steinhart-hart calibration, or mapping for b-constant or precomputed (a, b, c) calibration, not {type(value)}"
)
_LOGGER.info("Coefficient: a:%s, b:%s, c:%s", a, b, c)
return {

View File

@@ -202,6 +202,11 @@ sensor:
value: last
- timeout:
timeout: 1d
- to_ntc_temperature:
calibration:
b_constant: 3950
reference_temperature: 25.0°C
reference_resistance: 10kOhm
- to_ntc_resistance:
calibration:
- 10.0kOhm -> 25°C
@@ -270,8 +275,6 @@ cover:
stop_action:
- logger.log: stop_action
optimistic: true
on_open:
- logger.log: "Cover on_open (deprecated)"
on_opened:
- logger.log: "Cover fully opened"
on_closed: