diff --git a/.gitignore b/.gitignore index 4e3cd48..3511368 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ /secrets.yaml /.esphome.bak/ /fonts/ +**/__pycache__/ +components/ads131m08/__pycache__/sensor.cpython-312.pyc +components/ads131m08/__pycache__/__init__.cpython-312.pyc diff --git a/.vscode/arduino.json b/.vscode/arduino.json new file mode 100644 index 0000000..9f5e851 --- /dev/null +++ b/.vscode/arduino.json @@ -0,0 +1,19 @@ +{ + "port": "", + "configuration": "", + "output": "build", + "board": "", + "programmer": "", + "useProgrammer": false, + "optimize_for_debug": false, + "configurationRequired": false, + "compile_profile": "", + "monitorPortSettings": { + "port": "", + "baudRate": 115200, + "lineEnding": "\r\n", + "dataBits": 8, + "parity": "none", + "stopBits": "one" + } +} \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..d40834a --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,23 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "${vcpkgRoot}/x64-windows/include", + "\\\\TRUENAS\\esphome\\config\\.esphome\\build\\sthome-ut8\\src" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.26100.0", + "compilerPath": "cl.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/components/ads1115_int/__init__.py b/components/ads1115_int/__init__.py new file mode 100644 index 0000000..b9670c9 --- /dev/null +++ b/components/ads1115_int/__init__.py @@ -0,0 +1,40 @@ +import esphome.codegen as cg +from esphome.components import i2c +from esphome import pins +import esphome.config_validation as cv +from esphome.const import CONF_ID + +CONF_ALERT_RDY_PIN = "alert_rdy_pin" + +DEPENDENCIES = ["i2c"] +MULTI_CONF = True + +ads1115_ns = cg.esphome_ns.namespace("ads1115_int") +ADS1115Component = ads1115_ns.class_("ADS1115Component", cg.Component, i2c.I2CDevice) + +CONF_CONTINUOUS_MODE = "continuous_mode" +CONF_ADS1115_ID = "ads1115_int_id" + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ADS1115Component), + cv.Required(CONF_ALERT_RDY_PIN): pins.internal_gpio_input_pin_schema, + cv.Optional(CONF_CONTINUOUS_MODE, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(None)) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + alert_rdy = await cg.gpio_pin_expression( + config.get(CONF_ALERT_RDY_PIN) + ) + if alert_rdy is not None: + cg.add(var.set_alert_pin(alert_rdy)) + cg.add(var.set_continuous_mode(config[CONF_CONTINUOUS_MODE])) diff --git a/components/ads1115_int/ads1115_int.cpp b/components/ads1115_int/ads1115_int.cpp new file mode 100644 index 0000000..0272fb7 --- /dev/null +++ b/components/ads1115_int/ads1115_int.cpp @@ -0,0 +1,228 @@ +#include "ads1115_int.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace ads1115_int { + +static const char *const TAG = "ads1115_int"; +static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00; +static const uint8_t ADS1115_REGISTER_CONFIG = 0x01; +static const uint8_t ADS1115_REGISTER_LO_TRESH = 0x02; +static const uint8_t ADS1115_REGISTER_HI_TRESH = 0x03; + +void ADS1115Component::setup() { + uint16_t value; + this->alert_pin_->setup(); + this->alert_pin_->attach_interrupt(&ADS1115Component::isr, this, gpio::INTERRUPT_FALLING_EDGE); + if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) { + this->mark_failed(); + return; + } + uint16_t config = 0; + // Clear single-shot bit + // 0b0xxxxxxxxxxxxxxx + config |= 0b0000000000000000; + // Setup multiplexer + // 0bx000xxxxxxxxxxxx + config |= ADS1115_MULTIPLEXER_P0_N1 << 12; + + // Setup Gain + // 0bxxxx000xxxxxxxxx + config |= ADS1115_GAIN_6P144 << 9; + + if (this->continuous_mode_) { + // Set continuous mode + // 0bxxxxxxx0xxxxxxxx + config |= 0b0000000000000000; + } else { + // Set singleshot mode + // 0bxxxxxxx1xxxxxxxx + config |= 0b0000000100000000; + } + + // Set data rate - 860 samples per second + // 0bxxxxxxxx100xxxxx + config |= ADS1115_860SPS << 5; + + // Set comparator mode - hysteresis + // 0bxxxxxxxxxxx0xxxx + config |= 0b0000000000000000; + + // Set comparator polarity - active low + // 0bxxxxxxxxxxxx0xxx + config |= 0b0000000000000000; + + // Set comparator latch enabled - false + // 0bxxxxxxxxxxxxx0xx + config |= 0b0000000000000000; + + // Set comparator que mode - disabled + // 0bxxxxxxxxxxxxxx11 + config |= 0b0000000000000011; + + if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) { + this->mark_failed(); + return; + } + this->prev_config_ = config; + if(!this->set_alert_ready_mode()) { + this->mark_failed(); + return; + } +} +bool ADS1115Component::set_alert_ready_mode() +{ + uint16_t config = this->prev_config_; + // Set comparator que mode - assert after one conversion + // 0bxxxxxxxxxxxxxx00 + config &= 0b1111111111111100; + + if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) { + return false; + } + this->prev_config_ = config; + if(!this->write_byte_16(ADS1115_REGISTER_HI_TRESH, 0x8000)) { + return false; + } + if(!this->write_byte_16(ADS1115_REGISTER_LO_TRESH, 0x0000)) { + return false; + } + // also clear all data_ready_ flags + for (int i = 0; i < 8; i++) + this->data_ready_[i] = false; + return true; +} +// ISR function to handle interrupt from alert pin +// only function that sets data_ready_ flags +void IRAM_ATTR ADS1115Component::isr(ADS1115Component *arg) +{ + for (int i = 0; i < 8; i++) + arg->data_ready_[i] = true; +} +bool ADS1115Component::is_data_ready(ADS1115Multiplexer multiplexer) +{ + int index = static_cast(multiplexer); + if(index < 0 || index >= 8) + return false; + return this->data_ready_[index]; +} +void ADS1115Component::clear_alert_ready(ADS1115Multiplexer multiplexer) +{ + int index = static_cast(multiplexer); + if(index < 0 || index >= 8) + return; + this->data_ready_[index] = false; +} + +// call only when data_ready_ is true +double ADS1115Component::read_data(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, ADS1115Samplerate samplerate) +{ + uint16_t config = this->prev_config_; + // Multiplexer + // 0bxBBBxxxxxxxxxxxx + config &= 0b1000111111111111; + config |= (multiplexer & 0b111) << 12; + + // Gain + // 0bxxxxBBBxxxxxxxxx + config &= 0b1111000111111111; + config |= (gain & 0b111) << 9; + + // Sample rate + // 0bxxxxxxxxBBBxxxxx + config &= 0b1111111100011111; + config |= (samplerate & 0b111) << 5; + + if (!this->continuous_mode_) { + // Start conversion + config |= 0b1000000000000000; + } + + this->clear_alert_ready(multiplexer); + //ESP_LOGI(TAG, "'mux:%d': Gain=%d, Res=%d, CONF=<0x%04X>", static_cast(multiplexer), static_cast(gain), static_cast(resolution), config); + // write config if in single-shot mode or config has changed + if (!this->continuous_mode_ || this->prev_config_ != config) { + if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) { + this->status_set_warning(); + return false; + } + this->prev_config_ = config; + if (!this->continuous_mode_) { + uint32_t start = millis(); + // wait for conversion to complete + while (this->read_byte_16(ADS1115_REGISTER_CONFIG, &config) && (config >> 15) == 0) { + if (millis() - start > 100) { + ESP_LOGW(TAG, "Reading ADS1115 timed out"); + this->status_set_warning(); + return NAN; + } + yield(); + } + } + } + uint16_t raw_conversion; + if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) { + this->status_set_warning(); + return NAN; + } + //ESP_LOGI(TAG, "'mux:%d': raw=<0x%04X>", static_cast(multiplexer), raw_conversion); + + if (resolution == ADS1015_12_BITS) { + bool negative = (raw_conversion >> 15) == 1; + + // shift raw_conversion as it's only 12-bits, left justified + raw_conversion = raw_conversion >> (16 - ADS1015_12_BITS); + + // check if number was negative in order to keep the sign + if (negative) { + // the number was negative + // 1) set the negative bit back + raw_conversion |= 0x8000; + // 2) reset the former (shifted) negative bit + raw_conversion &= 0xF7FF; + } + } + auto signed_conversion = static_cast(raw_conversion); + double millivolts; + double divider = (resolution == ADS1115_16_BITS) ? 32768.0f : 2048.0f; + switch (gain) { + case ADS1115_GAIN_6P144: + millivolts = (signed_conversion * 6144) / divider; + break; + case ADS1115_GAIN_4P096: + millivolts = (signed_conversion * 4096) / divider; + break; + case ADS1115_GAIN_2P048: + millivolts = (signed_conversion * 2048) / divider; + break; + case ADS1115_GAIN_1P024: + millivolts = (signed_conversion * 1024) / divider; + break; + case ADS1115_GAIN_0P512: + millivolts = (signed_conversion * 512) / divider; + break; + case ADS1115_GAIN_0P256: + millivolts = (signed_conversion * 256) / divider; + break; + default: + millivolts = NAN; + } + + this->status_clear_warning(); + return millivolts / 1e3f; +} + +void ADS1115Component::dump_config() +{ + ESP_LOGCONFIG(TAG, "ADS1115_INT:"); + LOG_I2C_DEVICE(this); + LOG_PIN(" ALERT Pin:", this->alert_pin_); + if (this->is_failed()) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + } +} + + +} // namespace ads1115_int +} // namespace esphome diff --git a/components/ads1115_int/ads1115_int.h b/components/ads1115_int/ads1115_int.h new file mode 100644 index 0000000..f28d4f3 --- /dev/null +++ b/components/ads1115_int/ads1115_int.h @@ -0,0 +1,72 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" // Ensure this header defines i2c::I2CDevice +#include "esphome/core/component.h" // Ensure this header defines Component + +#include +#include + +namespace esphome { +namespace ads1115_int { + +enum ADS1115Multiplexer { + ADS1115_MULTIPLEXER_P0_N1 = 0b000, + ADS1115_MULTIPLEXER_P0_N3 = 0b001, + ADS1115_MULTIPLEXER_P1_N3 = 0b010, + ADS1115_MULTIPLEXER_P2_N3 = 0b011, + ADS1115_MULTIPLEXER_P0_NG = 0b100, + ADS1115_MULTIPLEXER_P1_NG = 0b101, + ADS1115_MULTIPLEXER_P2_NG = 0b110, + ADS1115_MULTIPLEXER_P3_NG = 0b111, +}; + +enum ADS1115Gain { + ADS1115_GAIN_6P144 = 0b000, + ADS1115_GAIN_4P096 = 0b001, + ADS1115_GAIN_2P048 = 0b010, + ADS1115_GAIN_1P024 = 0b011, + ADS1115_GAIN_0P512 = 0b100, + ADS1115_GAIN_0P256 = 0b101, +}; + +enum ADS1115Resolution { + ADS1115_16_BITS = 16, + ADS1015_12_BITS = 12, +}; + +enum ADS1115Samplerate { + ADS1115_8SPS = 0b000, + ADS1115_16SPS = 0b001, + ADS1115_32SPS = 0b010, + ADS1115_64SPS = 0b011, + ADS1115_128SPS = 0b100, + ADS1115_250SPS = 0b101, + ADS1115_475SPS = 0b110, + ADS1115_860SPS = 0b111 +}; + +class ADS1115Component : public Component, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + /// HARDWARE_LATE setup priority + void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; } + + // Method to read converted data + double read_data(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, ADS1115Samplerate samplerate); + void set_alert_pin(InternalGPIOPin *pin) { alert_pin_ = pin; } + bool set_alert_ready_mode(); + bool is_data_ready(ADS1115Multiplexer multiplexer); + void clear_alert_ready(ADS1115Multiplexer multiplexer); + + protected: + uint16_t prev_config_{0}; + bool continuous_mode_; + InternalGPIOPin *alert_pin_; + static void isr(ADS1115Component *arg); + volatile bool data_ready_[8]{false}; + +}; + +} // namespace ads1115_int +} // namespace esphome diff --git a/components/ads1115_int/sensor/__init__.py b/components/ads1115_int/sensor/__init__.py new file mode 100644 index 0000000..5715fcc --- /dev/null +++ b/components/ads1115_int/sensor/__init__.py @@ -0,0 +1,98 @@ +import esphome.codegen as cg +from esphome.components import sensor, voltage_sampler +import esphome.config_validation as cv +from esphome.const import ( + CONF_GAIN, + CONF_ID, + CONF_MULTIPLEXER, + CONF_RESOLUTION, + CONF_SAMPLE_RATE, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + UNIT_VOLT, +) + +from .. import CONF_ADS1115_ID, ADS1115Component, ads1115_ns + +AUTO_LOAD = ["voltage_sampler"] +DEPENDENCIES = ["ads1115"] + +ADS1115Multiplexer = ads1115_ns.enum("ADS1115Multiplexer") +MUX = { + "A0_A1": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N1, + "A0_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N3, + "A1_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_N3, + "A2_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_N3, + "A0_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_NG, + "A1_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_NG, + "A2_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_NG, + "A3_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P3_NG, +} + +ADS1115Gain = ads1115_ns.enum("ADS1115Gain") +GAIN = { + "6.144": ADS1115Gain.ADS1115_GAIN_6P144, + "4.096": ADS1115Gain.ADS1115_GAIN_4P096, + "2.048": ADS1115Gain.ADS1115_GAIN_2P048, + "1.024": ADS1115Gain.ADS1115_GAIN_1P024, + "0.512": ADS1115Gain.ADS1115_GAIN_0P512, + "0.256": ADS1115Gain.ADS1115_GAIN_0P256, +} + +ADS1115Resolution = ads1115_ns.enum("ADS1115Resolution") +RESOLUTION = { + "16_BITS": ADS1115Resolution.ADS1115_16_BITS, + "12_BITS": ADS1115Resolution.ADS1015_12_BITS, +} + +ADS1115Samplerate = ads1115_ns.enum("ADS1115Samplerate") +SAMPLERATE = { + "8": ADS1115Samplerate.ADS1115_8SPS, + "16": ADS1115Samplerate.ADS1115_16SPS, + "32": ADS1115Samplerate.ADS1115_32SPS, + "64": ADS1115Samplerate.ADS1115_64SPS, + "128": ADS1115Samplerate.ADS1115_128SPS, + "250": ADS1115Samplerate.ADS1115_250SPS, + "475": ADS1115Samplerate.ADS1115_475SPS, + "860": ADS1115Samplerate.ADS1115_860SPS, +} + +ADS1115Sensor = ads1115_ns.class_( + "ADS1115Sensor", sensor.Sensor, cg.Component, voltage_sampler.VoltageSampler +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + ADS1115Sensor, + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=3, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ) + .extend( + { + cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), + cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"), + cv.Required(CONF_GAIN): cv.enum(GAIN, string=True), + cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum( + RESOLUTION, upper=True, space="_" + ), + cv.Optional(CONF_SAMPLE_RATE, default="860"): cv.enum( + SAMPLERATE, string=True + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await sensor.register_sensor(var, config) + await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_ADS1115_ID]) + + cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) + cg.add(var.set_gain(config[CONF_GAIN])) + cg.add(var.set_resolution(config[CONF_RESOLUTION])) + cg.add(var.set_samplerate(config[CONF_SAMPLE_RATE])) diff --git a/components/ads1115_int/sensor/ads1115_int_sensor.cpp b/components/ads1115_int/sensor/ads1115_int_sensor.cpp new file mode 100644 index 0000000..7e78aed --- /dev/null +++ b/components/ads1115_int/sensor/ads1115_int_sensor.cpp @@ -0,0 +1,30 @@ +#include "ads1115_int_sensor.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace ads1115_int { + +static const char *const TAG = "ads1115_int.sensor"; + +void ADS1115Sensor::loop() { + if (parent_->is_data_ready(this->multiplexer_)) { + this->parent_->clear_alert_ready(this->multiplexer_); + double v = this->parent_->read_data(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_); + if (!std::isnan(v)) { + ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v); + this->publish_state(v); + } + } +} + +void ADS1115Sensor::dump_config() { + LOG_SENSOR(" ", "ADS1115 Int Sensor", this); + ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_); + ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_); + ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_); + ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_); +} + +} // namespace ads1115 +} // namespace esphome diff --git a/components/ads1115_int/sensor/ads1115_int_sensor.h b/components/ads1115_int/sensor/ads1115_int_sensor.h new file mode 100644 index 0000000..13708b2 --- /dev/null +++ b/components/ads1115_int/sensor/ads1115_int_sensor.h @@ -0,0 +1,37 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" + +#include "esphome/components/sensor/sensor.h" +//#include "esphome/components/voltage_sampler/voltage_sampler.h" + +#include "../ads1115_int.h" + +namespace esphome { +namespace ads1115_int { + +/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. +class ADS1115Sensor : public sensor::Sensor, + public Component, + //public voltage_sampler::VoltageSampler, + public Parented { + public: + void loop() override; + void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } + void set_gain(ADS1115Gain gain) { this->gain_ = gain; } + void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; } + void set_samplerate(ADS1115Samplerate samplerate) { this->samplerate_ = samplerate; } + + void dump_config() override; + + protected: + ADS1115Multiplexer multiplexer_; + ADS1115Gain gain_; + ADS1115Resolution resolution_; + ADS1115Samplerate samplerate_; + +}; + +} // namespace ads1115 +} // namespace esphome diff --git a/components/ads131m08/README.md b/components/ads131m08/README.md index 334b0a4..e2591b6 100644 --- a/components/ads131m08/README.md +++ b/components/ads131m08/README.md @@ -1,6 +1,6 @@ # ESPHome config/components/ads131m08 -This folder contains Contains source code files and related resources for external ads131m08 component. +This folder contains source code files and related resources for external ads131m08 component. ## Example .yaml config diff --git a/components/ads131m08/__init__.py b/components/ads131m08/__init__.py index 0dc14d6..04cb856 100644 --- a/components/ads131m08/__init__.py +++ b/components/ads131m08/__init__.py @@ -2,7 +2,12 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import spi -from esphome.const import CONF_ID +from esphome.const import ( + CONF_ID +) + +CONF_DRDY_PIN = "drdy_pin" +CONF_REFERENCE_VOLTAGE = "reference_voltage" DEPENDENCIES = ["spi"] ads131m08_ns = cg.esphome_ns.namespace("ads131m08") @@ -10,15 +15,15 @@ ADS131M08Hub = ads131m08_ns.class_("ADS131M08Hub", cg.Component, spi.SPIDevice) CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_id(ADS131M08Hub), - cv.Required("drdy_pin"): pins.internal_gpio_input_pin_schema, - cv.Required("vref"): cv.float_, + cv.Required(CONF_DRDY_PIN): pins.internal_gpio_input_pin_schema, + cv.Optional(CONF_REFERENCE_VOLTAGE, default=1.2): cv.float_range(min=1.1, max=1.3), }).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=True)) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await spi.register_spi_device(var, config) - drdy = await cg.gpio_pin_expression(config["drdy_pin"]) - reference_voltage = config["vref"] + drdy = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) + reference_voltage = config[CONF_REFERENCE_VOLTAGE] cg.add(var.set_reference_voltage(reference_voltage)) cg.add(var.set_drdy_pin(drdy)) diff --git a/components/ads131m08/__pycache__/__init__.cpython-312.pyc b/components/ads131m08/__pycache__/__init__.cpython-312.pyc index beb6a95..eb65fde 100644 Binary files a/components/ads131m08/__pycache__/__init__.cpython-312.pyc and b/components/ads131m08/__pycache__/__init__.cpython-312.pyc differ diff --git a/components/ads131m08/__pycache__/sensor.cpython-312.pyc b/components/ads131m08/__pycache__/sensor.cpython-312.pyc index 2b470a9..23e1cae 100644 Binary files a/components/ads131m08/__pycache__/sensor.cpython-312.pyc and b/components/ads131m08/__pycache__/sensor.cpython-312.pyc differ diff --git a/components/ads131m08/sensor.py b/components/ads131m08/sensor.py index 0481d23..50943cd 100644 --- a/components/ads131m08/sensor.py +++ b/components/ads131m08/sensor.py @@ -1,14 +1,27 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import CONF_ID, CONF_CHANNEL +from esphome.const import ( + CONF_ID, CONF_CHANNEL, STATE_CLASS_MEASUREMENT, DEVICE_CLASS_VOLTAGE, UNIT_VOLT, ICON_FLASH +) from . import ADS131M08Hub, ads131m08_ns +AUTO_LOAD = [ + "sensor", +] + +CONF_ADS131M08_ID = "ads131m08_id" + ADS131M08Sensor = ads131m08_ns.class_("ADS131M08Sensor", sensor.Sensor, cg.Component) -CONFIG_SCHEMA = sensor.sensor_schema().extend({ +CONFIG_SCHEMA = sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + device_class=DEVICE_CLASS_VOLTAGE, + icon=ICON_FLASH, + state_class=STATE_CLASS_MEASUREMENT, +).extend({ cv.GenerateID(): cv.declare_id(ADS131M08Sensor), - cv.Required("ads_hub_id"): cv.use_id(ADS131M08Hub), + cv.Required(CONF_ADS131M08_ID): cv.use_id(ADS131M08Hub), cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7), }).extend(cv.COMPONENT_SCHEMA) @@ -16,6 +29,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await sensor.register_sensor(var, config) - - hub = await cg.get_variable(config["ads_hub_id"]) + + hub = await cg.get_variable(config[CONF_ADS131M08_ID]) cg.add(hub.register_sensor(config[CONF_CHANNEL], var)) \ No newline at end of file diff --git a/sthome-ut8.yaml b/sthome-ut8.yaml index 8420d4f..ae88d47 100644 --- a/sthome-ut8.yaml +++ b/sthome-ut8.yaml @@ -2,7 +2,7 @@ external_components: - source: type: local path: components # Path relative to this YAML file - components: [ ads131m08 ] + components: [ ads131m08, ads1115_int ] packages: - !include common/wifi.yaml @@ -261,10 +261,12 @@ i2c: id: bus_a frequency: 10kHz -ads1115: +ads1115_int: - address: 0x48 id: ads1115_48 + alert_rdy_pin: GPIO3 continuous_mode: true +ads1115: - address: 0x49 id: ads1115_49 continuous_mode: true @@ -1492,39 +1494,39 @@ ads131m08: id: highres_adc cs_pin: GPIO5 drdy_pin: GPIO10 - vref: 1.25 + reference_voltage: 1.25 sensor: - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 0 name: "ADS Channel 0 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 1 name: "ADS Channel 1 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 2 name: "ADS Channel 2 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 3 name: "ADS Channel 3 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 4 name: "ADS Channel 4 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 5 name: "ADS Channel 5 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 6 name: "ADS Channel 6 Voltage" - platform: ads131m08 - ads_hub_id: highres_adc + ads131m08_id: highres_adc channel: 7 name: "ADS Channel 7 Voltage" @@ -1541,18 +1543,15 @@ sensor: # NB! Keep all ads1115 sample rates the same. Update intervals should be more than or equal to 1/sample_rate # ads1115_48 - platform: ads1115 - multiplexer: 'A0_A1' + multiplexer: 'A2_A3' gain: 2.048 # 4.096 - ads1115_id: ads1115_48 - sample_rate: 128 #860 -# update_interval: 10ms -# id: mains_current_adc + ads1115_id: ads1115_49 + name: "ADC Mains Current" + id: mains_current + sample_rate: 475 #475 state_class: measurement device_class: current accuracy_decimals: 8 - # mod ########################### - name: "Mains Current" - id: mains_current unit_of_measurement: "A" icon: "mdi:current" update_interval: 8ms #5ms @@ -1560,75 +1559,67 @@ sensor: # - offset: 0.0002 - lambda: return x * x; - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 + window_size: 1250 #1250 #5000 + send_every: 208 #208 #416 + send_first_at: 208 #208 #416 - lambda: return sqrt(x); - - multiply: 95.5 #88.44 - - offset: -0.2 + - multiply: 95 #88.44 + - offset: 0.0 #-0.2 - lambda: |- if(abs(x) < 0.1) return 0.0; return x; - # mod end ####################### - - platform: ads1115 - multiplexer: 'A2_A3' + + - platform: ads1115_int + multiplexer: 'A0_A1' gain: 2.048 # 4.096 - ads1115_id: ads1115_48 - sample_rate: 128 #860 - # update_interval: 10ms - # id: power_outlets_current_adc + ads1115_int_id: ads1115_48 + sample_rate: 860 # 475 #860 state_class: measurement device_class: current accuracy_decimals: 8 - # mod ########################### - name: "Plugs Supply Current" + name: "ADC House Current" id: power_outlets_current unit_of_measurement: "A" icon: "mdi:current" - update_interval: 8ms #5ms + # update_interval: 8ms #5ms filters: # - offset: 0.0002 - lambda: return x * x; - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 + 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.2 + - multiply: 555 #95 #88.44 + - offset: 0.0 #-0.2 - lambda: |- if(abs(x) < 0.1) return 0.0; return x; -# # mod end ######################## # ads1115_49 - - platform: ads1115 - multiplexer: 'A0_A1' + - platform: ads1115_int + multiplexer: 'A2_A3' gain: 2.048 # 4.096 - ads1115_id: ads1115_49 - sample_rate: 128 #860 - # update_interval: 10ms - # id: geyser_current_adc + ads1115_int_id: ads1115_48 + name: "ADC Geyser Current" + id: geyser_current + sample_rate: 860 #860 state_class: measurement device_class: current accuracy_decimals: 8 - # mod ########################### - name: "Geyser Current" - id: geyser_current unit_of_measurement: "A" icon: "mdi:current" - update_interval: 8ms #5ms + #update_interval: 8ms #5ms filters: - # - offset: 0.0002 - lambda: return x * x; - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 + window_size: 1250 #1250 #5000 + send_every: 208 #208 #416 + send_first_at: 208 #208 #416 - lambda: return sqrt(x); - - multiply: 169.4 #91.1 #88.44 + - multiply: 555 #92.1 #91.1 #88.44 - offset: 0.0 #-0.2 - lambda: |- if(abs(x) < 0.1) @@ -1639,24 +1630,24 @@ sensor: then: - lambda: |- ESP_LOGI("geyser", "No geyser current detected. Geyser not heating."); - - above: 0.5 + - above: 5.0 then: - lambda: |- ESP_LOGI("geyser", "Geyser current detected. Geyser was energised."); - # mod end ####################### + - platform: ads1115 - multiplexer: A2_A3 + multiplexer: A0_A1 gain: 2.048 # 4.096 ads1115_id: ads1115_49 - sample_rate: 128 #860 + name: "ADC Lights Current" + id: lights_current + sample_rate: 475 #860 # update_interval: 10ms # id: lights_current_adc state_class: measurement device_class: current accuracy_decimals: 8 # mod ########################### - name: "Lights Current" - id: lights_current unit_of_measurement: "A" icon: "mdi:current" update_interval: 8ms #5ms @@ -1664,11 +1655,11 @@ sensor: # - offset: 0.0002 - lambda: return x * x; - sliding_window_moving_average: - window_size: 625 #1250 #5000 - send_every: 104 #208 #416 - send_first_at: 104 #208 #416 + window_size: 1250 #1250 #5000 + send_every: 208 #208 #416 + send_first_at: 208 #208 #416 - lambda: return sqrt(x); - - multiply: 92.1 #88.44 + - multiply: 95.8 #88.44 - offset: 0.0 #-0.2 - lambda: |- if(abs(x) < 0.1) @@ -1681,7 +1672,7 @@ sensor: - platform: ads1115 ads1115_id: ads1115_4A sample_rate: 475 #860 - name: "Mains Voltage ADC" + name: "ADC Mains Voltage" id: mains_voltage_adc unit_of_measurement: "V" accuracy_decimals: 8 @@ -1695,9 +1686,9 @@ sensor: - offset: -2.048 #-2.04794027 # 0.0131 - lambda: return x * x; - sliding_window_moving_average: - window_size: 625 #1250 - send_every: 104 - send_first_at: 104 + window_size: 1250 #1250 + send_every: 208 + send_first_at: 208 - lambda: return sqrt(x); - multiply: 766.6670 # 930 #650 #- lambda: |- @@ -1705,41 +1696,12 @@ sensor: # return 0; # return x;# -# # ads1115_4A -# # Mains voltage sensor -# - platform: ads1115 -# ads1115_id: ads1115_4A -# sample_rate: 128 #860 -# name: "Spare1 ADC" -# id: spare1_voltage_adc -# unit_of_measurement: "V" -# accuracy_decimals: 8 -# icon: "mdi:flash" -# multiplexer: A1_GND -# gain: 2.048 # 4.096 -# update_interval: 8ms #5ms #23ms -# device_class: voltage -# state_class: measurement -# filters: -# - offset: 0.0 #4.096 #0.0065 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 312 #625 #1250 -# send_every: 52 #104 -# send_first_at: 52 #104 #416 -# - lambda: return sqrt(x); -# - multiply: 100 # 930 #650 -# #- lambda: |- -# # if(abs(x) < 20) -# # return 0; -# # return x; - # ads1115_4A # Mains voltage sensor - platform: ads1115 ads1115_id: ads1115_4A sample_rate: 475 #860 - name: "Inverter Output Voltage ADC" + name: "ADC House Voltage" id: inverter_output_voltage_adc unit_of_measurement: "V" accuracy_decimals: 8 @@ -1753,94 +1715,17 @@ sensor: - offset: -2.048 #-2.0491 #4.096 #0.0065 - lambda: return x * x; - sliding_window_moving_average: - window_size: 312 #625 #1250 - send_every: 52 #104 - send_first_at: 52 #104 #416 + window_size: 1250 #625 #1250 + send_every: 208 #104 + send_first_at: 208 #104 #416 - lambda: return sqrt(x); - - multiply: 100 # 930 #650 + - multiply: 766.6670 # 930 #650 #- lambda: |- # if(abs(x) < 20) # return 0; # return x; -# # ads1115_4A -# # Mains voltage sensor -# - platform: ads1115 -# ads1115_id: ads1115_4A -# sample_rate: 128 #860 -# name: "Spare2 Voltage ADC" -# id: spare2_voltage_adc -# unit_of_measurement: "V" -# accuracy_decimals: 8 -# icon: "mdi:flash" -# multiplexer: A3_GND -# gain: 2.048 # 4.096 -# update_interval: 8ms #5ms #23ms -# device_class: voltage -# state_class: measurement -# filters: -# - offset: 0.0 #4.096 #0.0065 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 312 #625 #1250 -# send_every: 52 #104 -# send_first_at: 52 #104 #416 -# - lambda: return sqrt(x); -# - multiply: 100 # 930 #650 -# #- lambda: |- -# # if(abs(x) < 20) -# # return 0; -# # return x; - # ads1115_4A -# # Inverter voltage sensor -# - platform: ads1115 -# ads1115_id: ads1115_4A -# sample_rate: 860 -# name: "ADS1115 4A A2" -# id: adc4A_A2 -# unit_of_measurement: "V" -# accuracy_decimals: 8 -# icon: "mdi:flash" -# multiplexer: A2_GND -# gain: 4.096 -# update_interval: 23ms -# device_class: voltage -# state_class: measurement -# filters: -# - offset: -1.6249 # -1.266 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 1250 -# send_every: 104 -# send_first_at: 104 -# - lambda: return sqrt(x); -# - multiply: 10000 -# -# # ads1115_4A -# # Inverter voltage sensor -# - platform: ads1115 -# ads1115_id: ads1115_4A -# sample_rate: 860 -# name: "ADS1115 4A A3" -# id: adc4A_A3 -# unit_of_measurement: "V" -# accuracy_decimals: 8 -# icon: "mdi:flash" -# multiplexer: A3_GND -# gain: 4.096 -# update_interval: 23ms -# device_class: voltage -# state_class: measurement -# filters: -# - offset: -1.6249 # -1.266 -# - lambda: return x * x; -# - sliding_window_moving_average: -# window_size: 1250 -# send_every: 104 -# send_first_at: 104 -# - lambda: return sqrt(x); -# - multiply: 10000 # ## # 30A clamp ## - platform: ct_clamp