92 lines
3.5 KiB
Python
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 = 14
|
|
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)
|