diff --git a/CODEOWNERS b/CODEOWNERS index ca1da2f153..9cfa81b36c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -113,6 +113,7 @@ esphome/components/ina260/* @MrEditor97 esphome/components/inkbird_ibsth1_mini/* @fkirill esphome/components/inkplate6/* @jesserockz esphome/components/integration/* @OttoWinter +esphome/components/internal_temperature/* @Mat931 esphome/components/interval/* @esphome/core esphome/components/json/* @OttoWinter esphome/components/kalman_combinator/* @Cat-Ion diff --git a/esphome/components/internal_temperature/__init__.py b/esphome/components/internal_temperature/__init__.py new file mode 100644 index 0000000000..9433ade13f --- /dev/null +++ b/esphome/components/internal_temperature/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@Mat931"] diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp new file mode 100644 index 0000000000..9a22a77f63 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -0,0 +1,58 @@ +#include "internal_temperature.h" +#include "esphome/core/log.h" + +#ifdef USE_ESP32 +#if defined(USE_ESP32_VARIANT_ESP32) +// there is no official API available on the original ESP32 +extern "C" { +uint8_t temprature_sens_read(); +} +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#include "driver/temp_sensor.h" +#endif // USE_ESP32_VARIANT +#endif // USE_ESP32 +#ifdef USE_RP2040 +#include "Arduino.h" +#endif // USE_RP2040 + +namespace esphome { +namespace internal_temperature { + +static const char *const TAG = "internal_temperature"; + +void InternalTemperatureSensor::update() { + float temperature = NAN; + bool success = false; +#ifdef USE_ESP32 +#if defined(USE_ESP32_VARIANT_ESP32) + uint8_t raw = temprature_sens_read(); + ESP_LOGV(TAG, "Raw temperature value: %d", raw); + temperature = (raw - 32) / 1.8f; + success = (raw != 128); +#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + temp_sensor_config_t tsens = TSENS_CONFIG_DEFAULT(); + temp_sensor_set_config(tsens); + temp_sensor_start(); + esp_err_t result = temp_sensor_read_celsius(&temperature); + temp_sensor_stop(); + success = (result == ESP_OK); +#endif // USE_ESP32_VARIANT +#endif // USE_ESP32 +#ifdef USE_RP2040 + temperature = analogReadTemp(); + success = (temperature != 0.0f); +#endif // USE_RP2040 + if (success && std::isfinite(temperature)) { + this->publish_state(temperature); + } else { + ESP_LOGD(TAG, "Ignoring invalid temperature (success=%d, value=%.1f)", success, temperature); + if (!this->has_state()) { + this->publish_state(NAN); + } + } +} + +void InternalTemperatureSensor::dump_config() { LOG_SENSOR("", "Internal Temperature Sensor", this); } + +} // namespace internal_temperature +} // namespace esphome diff --git a/esphome/components/internal_temperature/internal_temperature.h b/esphome/components/internal_temperature/internal_temperature.h new file mode 100644 index 0000000000..0e46a69769 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature.h @@ -0,0 +1,17 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome { +namespace internal_temperature { + +class InternalTemperatureSensor : public sensor::Sensor, public PollingComponent { + public: + void dump_config() override; + + void update() override; +}; + +} // namespace internal_temperature +} // namespace esphome diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py new file mode 100644 index 0000000000..2655711bb5 --- /dev/null +++ b/esphome/components/internal_temperature/sensor.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import ( + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + DEVICE_CLASS_TEMPERATURE, + ENTITY_CATEGORY_DIAGNOSTIC, +) + +internal_temperature_ns = cg.esphome_ns.namespace("internal_temperature") +InternalTemperatureSensor = internal_temperature_ns.class_( + "InternalTemperatureSensor", sensor.Sensor, cg.PollingComponent +) + +CONFIG_SCHEMA = cv.All( + sensor.sensor_schema( + InternalTemperatureSensor, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ).extend(cv.polling_component_schema("60s")), + cv.only_on(["esp32", "rp2040"]), +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) diff --git a/tests/test1.yaml b/tests/test1.yaml index a77f8802b9..bdc6da3406 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -324,6 +324,8 @@ mcp23s17: deviceaddress: 1 sensor: + - platform: internal_temperature + name: "Internal Temperature" - platform: ble_client type: characteristic ble_client_id: ble_foo diff --git a/tests/test5.yaml b/tests/test5.yaml index 5f72579d08..21419692e4 100644 --- a/tests/test5.yaml +++ b/tests/test5.yaml @@ -373,6 +373,8 @@ select: "Three": 3 sensor: + - platform: internal_temperature + name: "Internal Temperature" - platform: selec_meter total_active_energy: name: SelecEM2M Total Active Energy diff --git a/tests/test6.yaml b/tests/test6.yaml index 264773331e..2930400e34 100644 --- a/tests/test6.yaml +++ b/tests/test6.yaml @@ -37,3 +37,7 @@ switch: - platform: output output: pin_4 id: pin_4_switch + +sensor: + - platform: internal_temperature + name: "Internal Temperature"