components/ads131m08/sensor/__init__.py

92 lines
3.5 KiB
Python

import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, voltage_sampler
from esphome.const import CONF_ID, CONF_GAIN, CONF_CHANNEL
from .. import CONF_ADS131M08_ID, ADS131M08Hub, ads131m08_ns
from ..sensor_rms import CONFIG_SCHEMA_RMS_SENSORS, to_code_ac, to_code_dc
AUTO_LOAD = [
"sensor", "voltage_sampler",
]
MAX_CHANNELS = 15
CONF_OFFSET_CALIBRATION = "offset_calibration"
CONF_GAIN_CALIBRATION = "gain_calibration"
CONF_PHASE_CALIBRATION = "phase_calibration"
CONF_INPUT_SELECT = "input_select"
ICON_CURRENT_DC = "mdi:current-dc"
DEPENDENCIES = ["ads131m08"]
GAIN = ads131m08_ns.enum("ADC_PGA_GAIN")
ALLOWED_GAINS = {
"1": GAIN.PGA_1,
"2": GAIN.PGA_2,
"4": GAIN.PGA_4,
"8": GAIN.PGA_8,
"16": GAIN.PGA_16,
"32": GAIN.PGA_32,
"64": GAIN.PGA_64,
"128": GAIN.PGA_128,
1: GAIN.PGA_1,
2: GAIN.PGA_2,
4: GAIN.PGA_4,
8: GAIN.PGA_8,
16: GAIN.PGA_16,
32: GAIN.PGA_32,
64: GAIN.PGA_64,
128: GAIN.PGA_128,
}
ADC_INPUT = ads131m08_ns.enum("ADC_INPUT_CHANNEL_MUX")
ALLOWED_MUX_INP = {
"normal": ADC_INPUT.ICM_AIN0P_AIN0N,
"shorted" : ADC_INPUT.ICM_INPUT_SHORTED,
"positive_dc" : ADC_INPUT.ICM_POSITIVE_DC_TEST_SIGNAL,
"negative_dc" : ADC_INPUT.ICM_NEGATIVE_DC_TEST_SIGNAL,
}
Channel = ads131m08_ns.class_(
"Channel", sensor.Sensor, cg.Component, voltage_sampler.VoltageSampler
)
CONFIG_SCHEMA = CONFIG_SCHEMA_RMS_SENSORS.extend(
{
cv.GenerateID(CONF_ADS131M08_ID): cv.use_id(ADS131M08Hub),
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=MAX_CHANNELS),
cv.Optional(CONF_GAIN, default=1): cv.enum(ALLOWED_GAINS, int=True),
cv.Optional(CONF_OFFSET_CALIBRATION, default=0): cv.int_range(min=-8388608, max=8388607), # should use volts, but need to figure out conversion function first
cv.Optional(CONF_GAIN_CALIBRATION, default=1): cv.float_range(min=0, max=2),
cv.Optional(CONF_PHASE_CALIBRATION, default=0): cv.int_range(min=-512, max=511), # should use degrees, but need to figure out conversion function first
cv.Optional(CONF_INPUT_SELECT, default='normal'): cv.enum(ALLOWED_MUX_INP, int=False),
}
).extend(
{
cv.GenerateID(): cv.declare_id(Channel)
}
).extend(cv.COMPONENT_SCHEMA)
# we are using 3 sensors:
# 1. channel_sensor: this represents 1 of the 8 ads131m08 channels and is used to program the adc channel gain, offset calibration, etc. This sensor publishes instantaneous sampled value
# 2. dc_sensor: to publish averaged dc value
# 3. ac_sensor: to publish rms ac value
async def to_code(config):
channel_sensor = cg.new_Pvariable(config[CONF_ID])
await cg.register_parented(channel_sensor, config[CONF_ADS131M08_ID])
channel = config[CONF_CHANNEL]
cg.add(channel_sensor.set_channel_number(channel))
gain = config[CONF_GAIN]
cg.add(channel_sensor.set_gain(gain))
mux_inp = config[CONF_INPUT_SELECT]
cg.add(channel_sensor.set_mux_input(mux_inp))
gain_cal = config[CONF_GAIN_CALIBRATION]
cg.add(channel_sensor.set_gain_calibration(gain_cal))
offset_cal = config[CONF_OFFSET_CALIBRATION]
cg.add(channel_sensor.set_offset_calibration(offset_cal))
phase_cal = config[CONF_PHASE_CALIBRATION]
cg.add(channel_sensor.set_phase_calibration(phase_cal))
await cg.register_component(channel_sensor, config)
if dc_sensor := await to_code_dc(config):
await cg.register_parented(dc_sensor, channel_sensor)
if ac_sensor := await to_code_ac(config):
await cg.register_parented(ac_sensor, channel_sensor)