diff --git a/CODEOWNERS b/CODEOWNERS index 4d458eceb8..7e785db451 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -290,6 +290,7 @@ esphome/components/mcp23x17_base/* @jesserockz esphome/components/mcp23xxx_base/* @jesserockz esphome/components/mcp2515/* @danielschramm @mvturnho esphome/components/mcp3204/* @rsumner +esphome/components/mcp3221/* @philippderdiedas esphome/components/mcp4461/* @p1ngb4ck esphome/components/mcp4728/* @berfenger esphome/components/mcp47a1/* @jesserockz diff --git a/esphome/components/mcp3221/__init__.py b/esphome/components/mcp3221/__init__.py new file mode 100644 index 0000000000..677bb78c35 --- /dev/null +++ b/esphome/components/mcp3221/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@philippderdiedas"] diff --git a/esphome/components/mcp3221/mcp3221_sensor.cpp b/esphome/components/mcp3221/mcp3221_sensor.cpp new file mode 100644 index 0000000000..c04b1c0b93 --- /dev/null +++ b/esphome/components/mcp3221/mcp3221_sensor.cpp @@ -0,0 +1,31 @@ +#include "mcp3221_sensor.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace mcp3221 { + +static const char *const TAG = "mcp3221"; + +float MCP3221Sensor::sample() { + uint8_t data[2]; + if (this->read(data, 2) != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Read failed"); + this->status_set_warning(); + return NAN; + } + this->status_clear_warning(); + + uint16_t value = encode_uint16(data[0], data[1]); + float voltage = value * this->reference_voltage_ / 4096.0f; + + return voltage; +} + +void MCP3221Sensor::update() { + float v = this->sample(); + this->publish_state(v); +} + +} // namespace mcp3221 +} // namespace esphome diff --git a/esphome/components/mcp3221/mcp3221_sensor.h b/esphome/components/mcp3221/mcp3221_sensor.h new file mode 100644 index 0000000000..c83caccabf --- /dev/null +++ b/esphome/components/mcp3221/mcp3221_sensor.h @@ -0,0 +1,28 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/voltage_sampler/voltage_sampler.h" + +#include + +namespace esphome { +namespace mcp3221 { + +class MCP3221Sensor : public sensor::Sensor, + public PollingComponent, + public voltage_sampler::VoltageSampler, + public i2c::I2CDevice { + public: + void set_reference_voltage(float reference_voltage) { this->reference_voltage_ = reference_voltage; } + void update() override; + float sample() override; + + protected: + float reference_voltage_; +}; + +} // namespace mcp3221 +} // namespace esphome diff --git a/esphome/components/mcp3221/sensor.py b/esphome/components/mcp3221/sensor.py new file mode 100644 index 0000000000..993876c2c8 --- /dev/null +++ b/esphome/components/mcp3221/sensor.py @@ -0,0 +1,49 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor, voltage_sampler +import esphome.config_validation as cv +from esphome.const import ( + CONF_REFERENCE_VOLTAGE, + DEVICE_CLASS_VOLTAGE, + ICON_SCALE, + STATE_CLASS_MEASUREMENT, + UNIT_VOLT, +) + +AUTO_LOAD = ["voltage_sampler"] +DEPENDENCIES = ["i2c"] + + +mcp3221_ns = cg.esphome_ns.namespace("mcp3221") +MCP3221Sensor = mcp3221_ns.class_( + "MCP3221Sensor", + sensor.Sensor, + voltage_sampler.VoltageSampler, + cg.PollingComponent, + i2c.I2CDevice, +) + + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + MCP3221Sensor, + icon=ICON_SCALE, + accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, + device_class=DEVICE_CLASS_VOLTAGE, + unit_of_measurement=UNIT_VOLT, + ) + .extend( + { + cv.Optional(CONF_REFERENCE_VOLTAGE, default="3.3V"): cv.voltage, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x48)) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + cg.add(var.set_reference_voltage(config[CONF_REFERENCE_VOLTAGE])) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) diff --git a/tests/components/mcp3221/common.yaml b/tests/components/mcp3221/common.yaml new file mode 100644 index 0000000000..cc3eadbf4f --- /dev/null +++ b/tests/components/mcp3221/common.yaml @@ -0,0 +1,6 @@ +sensor: + - platform: mcp3221 + id: test_id + name: voltage + i2c_id: i2c_bus + reference_voltage: 3.3V diff --git a/tests/components/mcp3221/test.esp32-c3-idf.yaml b/tests/components/mcp3221/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..9990d96d29 --- /dev/null +++ b/tests/components/mcp3221/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-c3-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/mcp3221/test.esp32-idf.yaml b/tests/components/mcp3221/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/mcp3221/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/mcp3221/test.esp32-s3-idf.yaml b/tests/components/mcp3221/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..0fd8684a2c --- /dev/null +++ b/tests/components/mcp3221/test.esp32-s3-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/mcp3221/test.esp8266-ard.yaml b/tests/components/mcp3221/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/mcp3221/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/mcp3221/test.rp2040-ard.yaml b/tests/components/mcp3221/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/mcp3221/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml