diff --git a/components/ac_voltage_sensor/__init__.py b/components/ac_voltage_sensor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/components/ac_voltage_sensor/ac_voltage_sensor.cpp b/components/ac_voltage_sensor/ac_voltage_sensor.cpp new file mode 100644 index 0000000..37ff63f --- /dev/null +++ b/components/ac_voltage_sensor/ac_voltage_sensor.cpp @@ -0,0 +1,73 @@ +#include "ac_voltage_sensor.h" + +#include "esphome/core/log.h" +#include +#include + +namespace esphome { +namespace ac_voltage_sensor { + +static const char *const TAG = "ac_voltage_sensor"; + +void AC_Voltage_Sensor::dump_config() { + LOG_SENSOR("", "AC Voltage Sensor", this); + ESP_LOGCONFIG(TAG, " Sample Duration: %.2fs", this->sample_duration_ / 1e3f); + LOG_UPDATE_INTERVAL(this); +} + +void AC_Voltage_Sensor::update() { + // Update only starts the sampling phase, in loop() the actual sampling is happening. + + // Request a high loop() execution interval during sampling phase. + this->high_freq_.start(); + + // Set timeout for ending sampling phase + this->set_timeout("read", this->sample_duration_, [this]() { + this->is_sampling_ = false; + this->high_freq_.stop(); + + if (this->num_samples_ == 0) { + // Shouldn't happen, but let's not crash if it does. + this->publish_state(NAN); + return; + } + + const float rms_ac_dc_squared = this->sample_squared_sum_ / this->num_samples_; + const float rms_dc = this->sample_sum_ / this->num_samples_; + const float rms_ac_squared = rms_ac_dc_squared - rms_dc * rms_dc; + float rms_ac = 0; + if (rms_ac_squared > 0) + rms_ac = std::sqrt(rms_ac_squared); + ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fV, DC: %.3fV after %" PRIu32 " different samples (%" PRIu32 " SPS)", + this->name_.c_str(), rms_ac, rms_dc, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_); + this->publish_state(rms_ac); + }); + + // Set sampling values + this->last_value_ = 0.0; + this->num_samples_ = 0; + this->sample_sum_ = 0.0f; + this->sample_squared_sum_ = 0.0f; + this->is_sampling_ = true; +} + +void AC_Voltage_Sensor::loop() { + if (!this->is_sampling_) + return; + + // Perform a single sample + float value = this->source_->sample(); + if (std::isnan(value)) + return; + + // Assuming a sine wave, avoid requesting values faster than the ADC can provide them + if (this->last_value_ == value) + return; + this->last_value_ = value; + this->num_samples_++; + this->sample_sum_ += value; + this->sample_squared_sum_ += value * value; +} + +} // namespace ac_voltage_sensor +} // namespace esphome diff --git a/components/ac_voltage_sensor/ac_voltage_sensor.h b/components/ac_voltage_sensor/ac_voltage_sensor.h new file mode 100644 index 0000000..071c019 --- /dev/null +++ b/components/ac_voltage_sensor/ac_voltage_sensor.h @@ -0,0 +1,52 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" + +namespace esphome { +namespace ac_voltage_sensor { + +class AC_Voltage_Sensor : public sensor::Sensor, public PollingComponent { + public: + void update() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override { + // After the base sensor has been initialized + return setup_priority::DATA - 1.0f; + } + + void set_sample_duration(uint32_t sample_duration) { sample_duration_ = sample_duration; } + void set_source(voltage_sampler::VoltageSampler *source) { source_ = source; } + + protected: + /// High Frequency loop() requester used during sampling phase. + HighFrequencyLoopRequester high_freq_; + + /// Duration in ms of the sampling phase. + uint32_t sample_duration_; + /// The sampling source to read values from. + voltage_sampler::VoltageSampler *source_; + + /** The DC offset of the circuit is removed from the AC value, i.e. the value in dc_component_ is subtracted from the sampled value + * + * Diagram: https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino + * + * The AC component is essentially the same as the calculating the Standard-Deviation, + * which can be done by cumulating 3 values per sample: + * 1) Number of samples + * 2) Sum of samples + * 3) Sum of sample squared + * https://en.wikipedia.org/wiki/Root_mean_square + */ + float last_value_ = 0.0f; + float sample_sum_ = 0.0f; + float sample_squared_sum_ = 0.0f; + uint32_t num_samples_ = 0; + bool is_sampling_ = false; +}; + +} // namespace ac_voltage_sensor +} // namespace esphome diff --git a/components/ac_voltage_sensor/sensor.py b/components/ac_voltage_sensor/sensor.py new file mode 100644 index 0000000..54d02a6 --- /dev/null +++ b/components/ac_voltage_sensor/sensor.py @@ -0,0 +1,45 @@ +import esphome.codegen as cg +from esphome.components import sensor, voltage_sampler +import esphome.config_validation as cv +from esphome.const import ( + CONF_SENSOR, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + UNIT_VOLT, +) +# based on ctclamp by jesserockz +AUTO_LOAD = ["voltage_sampler"] +CODEOWNERS = ["@stuurmcp"] + +CONF_SAMPLE_DURATION = "sample_duration" + +ac_voltage_sensor_ns = cg.esphome_ns.namespace("ac_voltage_sensor") +AC_Voltage_Sensor = ac_voltage_sensor_ns.class_("AC_Voltage_Sensor", sensor.Sensor, cg.PollingComponent) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + AC_Voltage_Sensor, + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend( + { + cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler), + cv.Optional( + CONF_SAMPLE_DURATION, default="200ms" + ): cv.positive_time_period_milliseconds, + } + ) + .extend(cv.polling_component_schema("60s")) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + + sens = await cg.get_variable(config[CONF_SENSOR]) + cg.add(var.set_source(sens)) + cg.add(var.set_sample_duration(config[CONF_SAMPLE_DURATION])) diff --git a/sthome-ut8.yaml b/sthome-ut8.yaml index fe8aa9b..60671c0 100644 --- a/sthome-ut8.yaml +++ b/sthome-ut8.yaml @@ -4,7 +4,7 @@ external_components: - source: type: local path: components # Path relative to this YAML file - components: [ ads1115_int, tlc59208f_ext, ds3231 ] #, ads131m08 ] + components: [ ads1115_int, tlc59208f_ext, ds3231, ac_voltage_sensor ] #, ads131m08 ] packages: - !include common/wifi.yaml @@ -228,8 +228,10 @@ logger: ds3231: DEBUG tlc59208f_ext: VERBOSE text_sensor: INFO - ads1115_int: VERBOSE - ads1115_int.sensor: VERBOSE + ads1115: DEBUG + ads1115_int: DEBUG + ads1115_int.sensor: DEBUG + ac_voltage_sensor: INFO modbus: VERBOSE modbus_controller: INFO modbus_controller.sensor: INFO @@ -279,35 +281,36 @@ ads1115_int: - address: 0x4A id: ads1115_4A i2c_id: bus_a + continuous_mode: true interleaved_mode: true - continuous_mode: false alert_rdy_pin: number: GPIO27 mode: input: true pullup: false +ads1115: - address: 0x49 id: ads1115_49 i2c_id: bus_a - interleaved_mode: true - continuous_mode: false - alert_rdy_pin: - number: GPIO5 - mode: - input: true - pullup: false + continuous_mode: true +# interleaved_mode: true +# alert_rdy_pin: +# number: GPIO5 +# mode: +# input: true +# pullup: false - address: 0x48 id: ads1115_48 i2c_id: bus_a - interleaved_mode: true - continuous_mode: false - alert_rdy_pin: - number: GPIO3 - mode: - input: true - pullup: false # external 10k pullup on ads1115 dev board + continuous_mode: true +# interleaved_mode: true +# alert_rdy_pin: +# number: GPIO3 +# mode: +# input: true +# pullup: false # external 10k pullup on ads1115 dev board spi: - id: spi_bus0 @@ -1543,353 +1546,319 @@ sensor: name: "CPU Frequency" # NB! Keep all ads1115 sample rates the same. Update intervals should be more than or equal to 1/sample_rate - - platform: ads1115_int - #resolution: 12_BITS - multiplexer: 'A0_A1' - gain: 2.048 # 4.096 - ads1115_id: ads1115_48 - sample_rate: 860 # 475 #860 - state_class: measurement - device_class: current - accuracy_decimals: 8 - name: "ADC House Current" - id: power_outlets_current - unit_of_measurement: "A" - icon: "mdi:current" - # update_interval: 8ms #5ms - #filters: - ## - offset: 0.0002 - # - lambda: return x * x; - # - sliding_window_moving_average: - # window_size: 1250 #1250 #5000 - # send_every: 208 #208 #416 - # send_first_at: 208 #208 #416 - # - lambda: return sqrt(x); - # - multiply: 555 #95 #88.44 - # - offset: 0.0 #-0.2 - # - lambda: |- - # if(abs(x) < 0.1) - # return 0.0; - # return x; - - # ads1115_48 - - platform: ads1115_int - multiplexer: 'A2_A3' - gain: 2.048 # 4.096 - ads1115_id: ads1115_48 - name: "ADC Geyser Current" - id: geyser_current - sample_rate: 860 #860 - state_class: measurement - device_class: current - accuracy_decimals: 8 - unit_of_measurement: "A" - icon: "mdi:current" - filters: - - lambda: return x * x; - - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 - - lambda: return sqrt(x); - - multiply: 100 #92.1 #91.1 #88.44 - - offset: 0.0 #-0.2 - # - lambda: |- - # if(abs(x) < 0.1) - # return 0.0; - # return x; - on_value_range: - - below: 5.0 - then: - - lambda: |- - ESP_LOGI("geyser", "No geyser current detected. Geyser not heating."); - - above: 5.0 - then: - - lambda: |- - ESP_LOGI("geyser", "Geyser current detected. Geyser was energised."); - - # ads1115_49 - - platform: ads1115_int - multiplexer: A0_A1 - gain: 2.048 # 4.096 - ads1115_id: ads1115_49 - name: "ADC Lights Current" - id: lights_current - sample_rate: 860 - # update_interval: 10ms - # id: lights_current_adc - state_class: measurement - device_class: current - accuracy_decimals: 8 - unit_of_measurement: "A" - icon: "mdi:current" - filters: - - lambda: return x * x; - - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 - - lambda: return sqrt(x); - - multiply: 100 #92.1 #91.1 #88.44 - - offset: 0.0 #-0.2 - # - lambda: |- - # if(abs(x) < 0.1) - # return 0.0; - # return x; - - - platform: ads1115_int - multiplexer: 'A2_A3' - gain: 2.048 # 4.096 - ads1115_id: ads1115_49 - name: "ADC Mains Current" - id: mains_current - sample_rate: 860 #475 - state_class: measurement - device_class: current - accuracy_decimals: 8 - unit_of_measurement: "A" - icon: "mdi:current" - #update_interval: 8ms #5ms - #filters: - ## - offset: 0.0002 - # - lambda: return x * x; - # - sliding_window_moving_average: - # window_size: 1250 #1250 #5000 - # send_every: 208 #208 #416 - # send_first_at: 208 #208 #416 - # - lambda: return sqrt(x); - # - multiply: 95 #88.44 - # - offset: 0.0 #-0.2 - # - lambda: |- - # if(abs(x) < 0.1) - # return 0.0; - # return x; - +# - name: "ADC House Current" +# platform: ads1115_int +# multiplexer: 'A0_A1' +# gain: 2.048 +# ads1115_id: ads1115_48 +# sample_rate: 860 +# state_class: measurement +# device_class: current +# accuracy_decimals: 8 +# id: power_outlets_current +# unit_of_measurement: "A" +# icon: "mdi:current" +# filters: +# - lambda: return x * x; +# - sliding_window_moving_average: +# window_size: 1250 +# send_every: 208 +# send_first_at: 208 +# - lambda: return sqrt(x); +# - multiply: 105 +# +# - name: "ADC Geyser Current" +# platform: ads1115_int +# multiplexer: 'A2_A3' +# gain: 2.048 +# ads1115_id: ads1115_48 +# id: geyser_current +# sample_rate: 860 +# state_class: measurement +# device_class: current +# accuracy_decimals: 8 +# unit_of_measurement: "A" +# icon: "mdi:current" +# filters: +# - lambda: return x * x; +# - sliding_window_moving_average: +# window_size: 1250 +# send_every: 208 +# send_first_at: 208 +# - lambda: return sqrt(x); +# - multiply: 105 +# on_value_range: +# - below: 5.0 +# then: +# - lambda: |- +# ESP_LOGI("geyser", "No geyser current detected. Geyser not heating."); +# - above: 5.0 +# then: +# - lambda: |- +# ESP_LOGI("geyser", "Geyser current detected. Geyser was energised."); +# +# - name: "ADC Lights Current" +# platform: ads1115_int +# multiplexer: A0_A1 +# gain: 2.048 +# ads1115_id: ads1115_49 +# id: lights_current +# sample_rate: 860 +# # id: lights_current_adc +# state_class: measurement +# device_class: current +# accuracy_decimals: 8 +# unit_of_measurement: "A" +# icon: "mdi:current" +# filters: +# - lambda: return x * x; +# - sliding_window_moving_average: +# window_size: 1250 +# send_every: 208 +# send_first_at: 208 +# - lambda: return sqrt(x); +# - multiply: 98 +# +# - name: "ADC Mains Current" +# platform: ads1115_int +# multiplexer: 'A2_A3' +# gain: 2.048 +# ads1115_id: ads1115_49 +# id: mains_current +# sample_rate: 860 +# state_class: measurement +# device_class: current +# accuracy_decimals: 8 +# unit_of_measurement: "A" +# icon: "mdi:current" +# filters: +# - lambda: return x * x; +# - sliding_window_moving_average: +# window_size: 1250 +# send_every: 208 +# send_first_at: 208 +# - lambda: return sqrt(x); +# - multiply: 100 # - # ads1115_4A - # Inverter voltage sensor - - platform: ads1115_int + - name: "ADC Mains Voltage" + platform: ads1115_int ads1115_id: ads1115_4A sample_rate: 860 - name: "ADC Mains Voltage" id: mains_voltage_adc unit_of_measurement: "V" accuracy_decimals: 8 icon: "mdi:flash" multiplexer: A0_GND - gain: 2.048 # 4.096 - #update_interval: 8ms #5ms #23ms + gain: 2.048 device_class: voltage state_class: measurement -# filters: -# - offset: -2.048 #-2.04794027 # 0.0131 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 1250 #1250 -# send_every: 208 -# send_first_at: 208 -# - lambda: return sqrt(x); -# - multiply: 766.6670 # 930 #650 - #- lambda: |- - # if(abs(x) < 10) - # return 0; - # return x;# + filters: + - offset: -2.048 + - lambda: return x * x; + - sliding_window_moving_average: + window_size: 1250 + send_every: 208 + send_first_at: 208 + - lambda: return sqrt(x); + - multiply: 653 - - platform: ads1115_int + - name: "ADC Spare1 Voltage" + platform: ads1115_int ads1115_id: ads1115_4A sample_rate: 860 - name: "ADC Spare1 Voltage" unit_of_measurement: "V" accuracy_decimals: 8 icon: "mdi:flash" multiplexer: A1_GND - gain: 2.048 # 4.096 - #update_interval: 8ms #5ms #23ms + gain: 2.048 device_class: voltage state_class: measurement - - platform: ads1115_int + - name: "ADC House Voltage" + platform: ads1115_int ads1115_id: ads1115_4A sample_rate: 860 - name: "ADC House Voltage" id: inverter_output_voltage_adc unit_of_measurement: "V" accuracy_decimals: 8 icon: "mdi:flash" multiplexer: A2_GND - gain: 2.048 # 4.096 + gain: 2.048 device_class: voltage state_class: measurement -# filters: -# - offset: -2.048 #-2.0491 #4.096 #0.0065 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 1250 #625 #1250 -# send_every: 208 #104 -# send_first_at: 208 #104 #416 -# - lambda: return sqrt(x); -# - multiply: 766.6670 # 930 #650 - #- lambda: |- - # if(abs(x) < 20) - # return 0; - # return x; + filters: + - offset: -2.048 + - lambda: return x * x; + - sliding_window_moving_average: + window_size: 1250 + send_every: 208 + send_first_at: 208 + - lambda: return sqrt(x); + - multiply: 653 - - - platform: ads1115_int + - name: "ADC Spare2 Voltage" + platform: ads1115_int ads1115_id: ads1115_4A sample_rate: 860 - name: "ADC Spare2 Voltage" unit_of_measurement: "V" accuracy_decimals: 8 icon: "mdi:flash" multiplexer: A3_GND - gain: 2.048 # 4.096 - #update_interval: 8ms #5ms #23ms + gain: 2.048 device_class: voltage state_class: measurement +# +######################################################## CT CLAMP ######################################################## + - platform: ads1115 + multiplexer: 'A0_A1' + gain: 2.048 + ads1115_id: ads1115_48 + sample_rate: 860 + id: adc_house_current + - platform: ads1115 + multiplexer: 'A2_A3' + gain: 2.048 + ads1115_id: ads1115_48 + id: adc_geyser_current + sample_rate: 860 + - platform: ads1115 + multiplexer: A0_A1 + gain: 2.048 + ads1115_id: ads1115_49 + id: adc_lights_current + sample_rate: 860 + - platform: ads1115 + multiplexer: 'A2_A3' + gain: 2.048 + ads1115_id: ads1115_49 + id: adc_mains_current + sample_rate: 860 + + # 30A clamp + - platform: ct_clamp + sensor: adc_geyser_current + id: geyser_current + name: "ACL Geyser Current" + update_interval: 5s + sample_duration: 4s + state_class: measurement + device_class: current + filters: + # burden resistor is 62Ω in parallel with 33Ω = 21.54Ω + # multiplier should be 1860/21.54 = x86.35 + - multiply: 88.51 #88.51 = real world + on_value_range: + - below: 0.5 + then: + - lambda: |- + ESP_LOGI("geyser", "Geyser lost power."); + - above: 0.5 + then: + - lambda: |- + ESP_LOGI("geyser", "Geyser was energised."); + + # 30A clamp + - platform: ct_clamp + sensor: adc_lights_current + id: lights_current + name: "ACL Lights Current" + update_interval: 5s + sample_duration: 4s + state_class: measurement + device_class: current + filters: + # burden resistor is 62Ω in parallel with 33Ω = 21.54Ω + # multiplier should be 1860/21.54 = x86.35 + - multiply: 88.44 #88.44 = real world + + # 100A clamp + - platform: ct_clamp + sensor: adc_mains_current + id: mains_current + name: "ACL Mains Current" + update_interval: 5s + sample_duration: 4s + state_class: measurement + device_class: current + filters: + # burden resistor is 22Ω + # multiplier should be 2000/22 = x90.9 + - multiply: 90.25 # 90.25 = real world + + # 100A clamp + - platform: ct_clamp + sensor: adc_house_current + id: power_outlets_current + name: "ACL House Current" + update_interval: 5s + sample_duration: 4s + state_class: measurement + device_class: current + filters: + # burden resistor is 22Ω + # multiplier should be 2000/22 = x90.9 + - multiply: 91.14 #91.14 = real world + +####################################################### EOF CT CLAMP ####################################################### +# - platform: ads1115 +# ads1115_id: ads1115_4A +# sample_rate: 860 +# id: adc_mains_voltage +# multiplexer: A0_GND +# gain: 2.048 +# - platform: ads1115 +# ads1115_id: ads1115_4A +# sample_rate: 860 +# id: adc_spare1_voltage +# multiplexer: A1_GND +# gain: 2.048 +# - platform: ads1115 +# ads1115_id: ads1115_4A +# sample_rate: 860 +# id: adc_house_voltage +# multiplexer: A2_GND +# gain: 2.048 +# - platform: ads1115 +# ads1115_id: ads1115_4A +# sample_rate: 860 +# id: adc_spare2_voltage +# multiplexer: A3_GND +# gain: 2.048 # -## # 30A clamp -## - platform: ct_clamp -## sensor: geyser_current_adc -## id: geyser_current -## name: "Geyser Current" -## update_interval: 2s -## sample_duration: 2000ms #15000ms -## state_class: measurement -## device_class: current -## filters: -## # burden resistor is 62Ω in parallel with 33Ω = 21.54Ω -## # multiplier should be 1860/21.54 = x86.35 -## - multiply: 88.51 # real world -## - lambda: |- -## if(x < 0.25) -## return 0.0; -## return x; -## on_value_range: -## - below: 0.5 -## then: -## - lambda: |- -## ESP_LOGI("geyser", "Geyser lost power."); -## - above: 0.5 -## then: -## - lambda: |- -## ESP_LOGI("geyser", "Geyser was energised."); +# - name: "ADC Mains Voltage" +# platform: ac_voltage_sensor +# sensor: adc_mains_voltage +# update_interval: 5s +# sample_duration: 4.5s +# filters: +# - multiply: 884 # -## # 30A clamp -## - platform: ct_clamp -## sensor: lights_current_adc -## id: lights_current -## name: "Lights Current" -## update_interval: 1s -## sample_duration: 1s #15000ms -## state_class: measurement -## device_class: current -## filters: -## # burden resistor is 62Ω in parallel with 33Ω = 21.54Ω -## # multiplier should be 1860/21.54 = x86.35 -## - multiply: 88.44 # real world -## - lambda: |- -## if(x < 0.25) -## return 0.0; -## return x; +# - name: "ADC Spare1 Voltage" +# platform: ac_voltage_sensor +# sensor: adc_spare1_voltage +# update_interval: 5s +# sample_duration: 4.5s +# filters: +# - multiply: 884 # -## # 100A clamp -## - platform: ct_clamp -## sensor: mains_current_adc -## id: mains_current -## name: "Mains Current" -## update_interval: 1s -## sample_duration: 1s #15000ms -## state_class: measurement -## device_class: current -## filters: -## # burden resistor is 22Ω -## # multiplier should be 2000/22 = x90.9 -## - multiply: 90.25 # real world -## - lambda: |- -## if(x < 0.25) -## return 0.0; -## return x; -## -## # 100A clamp -## - platform: ct_clamp -## sensor: power_outlets_current_adc -## id: power_outlets_current -## name: "Plugs Supply Current" -## update_interval: 1s -## sample_duration: 1s #15000ms -## state_class: measurement -## device_class: current -## filters: -## # burden resistor is 22Ω -## # multiplier should be 2000/22 = x90.9 -## - multiply: 91.14 # real world -## - lambda: |- -## if(x < 0.25) -## return 0.0; -## return x; +# - name: "ADC House Voltage" +# platform: ac_voltage_sensor +# sensor: adc_house_voltage +# update_interval: 5s +# sample_duration: 4.5s +# filters: +# - multiply: 884 # -# - platform: template -# id: calibrate_lights -# name: "AAA Lights A" -# lambda: |- -# return id(lights_current).state; -# state_class: measurement -# device_class: current -# accuracy_decimals: 8 -# update_interval: 1s -# -# - platform: template -# id: calibrate_mains -# name: "AAA Mains A" -# lambda: |- -# return id(mains_current).state; -# state_class: measurement -# device_class: current -# accuracy_decimals: 8 -# update_interval: 1s -# -# - platform: template -# id: calibrate_mains_v -# name: "AAA Mains V" -# lambda: |- -# return id(mains_voltage_adc).state; -# state_class: measurement -# device_class: voltage -# accuracy_decimals: 8 -# update_interval: 1s -# -# - platform: template -# id: calibrate_plugs -# name: "AAA Plugs A" -# lambda: |- -# return id(power_outlets_current).state; -# state_class: measurement -# device_class: current -# accuracy_decimals: 8 -# update_interval: 1s -# -# - platform: template -# id: calibrate_plugs_V -# name: "AAA Plugs V" -# lambda: |- -# return id(inverter_output_voltage_adc).state; -# state_class: measurement -# device_class: voltage -# accuracy_decimals: 8 -# update_interval: 1s -# -# - platform: template -# id: calibrate_geyser -# name: "AAA Geyser A" -# lambda: |- -# return id(geyser_current).state; -# state_class: measurement -# device_class: current -# accuracy_decimals: 8 -# update_interval: 1s +# - name: "ADC Spare2 Voltage" +# platform: ac_voltage_sensor +# sensor: adc_spare2_voltage +# update_interval: 5s +# sample_duration: 4.5s +# filters: +# - multiply: 884 + # # for now we use a template until we get a voltage sensor - platform: template