Chapter 167: Temperature Sensor Integration with ESP32
Chapter Objectives
By the end of this chapter, you will be able to:
- Understand the presence and purpose of the internal temperature sensor in ESP32 series chips.
- Describe the basic working principle and characteristics of the on-chip temperature sensor.
- Initialize and configure the internal temperature sensor using ESP-IDF v5.x drivers.
- Read temperature values from the sensor and convert them to standard units (Celsius).
- Recognize the limitations, accuracy, and factors influencing the internal temperature sensor readings.
- Implement applications that utilize internal temperature data, such as monitoring or simple thermal responses.
- Identify differences in internal temperature sensor availability and usage across various ESP32 variants.
Introduction
Many modern microcontrollers, including those in the ESP32 family, integrate an on-chip temperature sensor. While not typically designed for high-precision meteorological measurements, this internal sensor provides a convenient way to estimate the silicon die temperature or approximate ambient temperature changes without requiring external components.
Understanding the temperature of the microcontroller itself can be crucial for several reasons:
- Thermal Management: Ensuring the chip operates within its safe temperature limits, especially under heavy load (e.g., intensive Wi-Fi communication or CPU processing).
- System Health Monitoring: Detecting overheating conditions that might indicate a fault or an unsuitable operating environment.
- Relative Temperature Sensing: Observing changes in temperature, which can be useful even if the absolute accuracy is moderate.
- Compensation: Some peripheral characteristics might change with temperature, and an internal sensor can provide data for potential compensation algorithms.
This chapter will guide you through accessing and utilizing the internal temperature sensor on ESP32 devices using the ESP-IDF, focusing on its practical application and inherent characteristics.
Theory
The On-Chip Temperature Sensor
The internal temperature sensor on ESP32 devices is typically a silicon-based sensor whose electrical characteristics (often related to a P-N junction’s voltage or a ring oscillator’s frequency) change predictably with temperature. The raw output from such a sensor is usually an analog voltage or a digital value that needs to be converted into a standard temperature unit like Celsius.
Key Characteristics:
- Measurement Target: The sensor primarily measures the temperature of the silicon die itself. This means it’s influenced by the chip’s own heat generation (self-heating) due to processing load, radio activity, and I/O operations, as well as the ambient temperature of the environment.
- Accuracy and Resolution:
- Accuracy: The absolute accuracy of these internal sensors can vary (e.g., ± several degrees Celsius) and might require calibration for more precise measurements. They are generally not as accurate as dedicated external temperature sensors (like thermistors, RTDs, or digital temperature sensor ICs).
- Resolution: The smallest change in temperature that the sensor can detect.
Sensor Type | Measurement Target | Typical Accuracy | Primary Use Case |
---|---|---|---|
ESP32 Internal | Silicon Die Temperature | ±2°C to ±5°C (uncallibrated) | Thermal management, relative changes, system health. |
NTC Thermistor | Ambient / Surface | ±0.5°C to ±2°C (requires ADC and calculation) | Cost-effective ambient sensing, liquid temperature. |
Digital (e.g., DS18B20) | Ambient / Surface | ±0.5°C | Precise, general-purpose temperature measurement with simple digital interface. |
Environmental (e.g., BME280) | Ambient | ±1.0°C (Temp) | Weather stations, HVAC; often includes humidity and pressure sensing. |
- Range: The operational temperature range within which the sensor provides meaningful readings. This is usually tied to the overall operating temperature range of the ESP32 chip.
- Self-Heating: As the ESP32 performs tasks, its internal components generate heat. This self-heating will cause the internal temperature sensor to report a temperature higher than the actual ambient air temperature. The amount of self-heating depends on CPU load, peripheral usage (especially Wi-Fi/Bluetooth radios), and power supply voltage.
- Calibration: For more accurate absolute temperature readings, a calibration process might be necessary. This typically involves comparing the internal sensor’s output with a known reference temperature and applying an offset or scaling factor. However, the ESP-IDF driver for the temperature sensor often includes some factory calibration data or a standardized conversion formula.
ESP-IDF esp_temperature_sensor
Driver
ESP-IDF v5.x provides a unified driver API for accessing the on-chip temperature sensor, located in the esp_temperature_sensor.h
header file. This driver simplifies the process of initializing the sensor and reading calibrated temperature values in Celsius.
%%{init: {'fontFamily': 'Open Sans'}}%% graph TD subgraph "Hardware" A[On-Chip Sensor] -->|Analog Voltage/Signal| B(ADC); end subgraph "ESP-IDF Driver (esp_temperature_sensor)" B --> |Raw Digital Value| C{Conversion Logic}; D[Factory Calibration Data] --> C; C --> |Floating Point Value| E[Output]; end subgraph "User Application" E -- "temperature_sensor_get_celsius()" --> F(<b>Float variable holding<br>Temperature in °C</b>); end %% Styling classDef hardwareNode fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B; classDef driverNode fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF; classDef userNode fill:#D1FAE5,stroke:#059669,stroke-width:1px,color:#065F46; classDef dataNode fill:#FEF3C7,stroke:#D97706,stroke-width:2px,color:#92400E; class A,B hardwareNode; class C,D,E driverNode; class F userNode; class D dataNode;
Core Components of the API:
- Handle:
temperature_sensor_handle_t
- An opaque handle representing an installed temperature sensor driver instance.
- Configuration:
temperature_sensor_config_t
range_min
,range_max
: Defines the expected measurement range in Celsius. The driver uses this to select the appropriate internal configuration or clock source for the sensor. For general use, you can often use pre-defined typical ranges.clk_src
: Clock source for the temperature sensor. Usually, this can be left to the driver’s default.
- Key Functions:
temperature_sensor_install(const temperature_sensor_config_t *tsens_config, temperature_sensor_handle_t *ret_tsens)
: Initializes and installs the temperature sensor driver with the given configuration. Returns a handle to the sensor.temperature_sensor_enable(temperature_sensor_handle_t tsens)
: Enables the temperature sensor.temperature_sensor_disable(temperature_sensor_handle_t tsens)
: Disables the temperature sensor to save power.temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius)
: Reads the temperature and returns it in degrees Celsius. This function typically handles the raw-to-Celsius conversion, possibly applying factory calibration data.temperature_sensor_uninstall(temperature_sensor_handle_t tsens)
: Uninstalls the temperature sensor driver and releases resources.
Workflow:
%%{init: {'fontFamily': 'Open Sans'}}%% flowchart TD A(Start) --> B["Define <b>temperature_sensor_config_t</b><br><i>Set min/max range</i>"]; B --> C{"temperature_sensor_install()"}; C -- "OK" --> D["temperature_sensor_enable()"]; C -- "Error" --> X(Handle Error / Stop); D -- "OK" --> E{Read Loop}; D -- "Error" --> X; E -- " " --> F["temperature_sensor_get_celsius()"]; F --> G{Continue?}; G -- "Yes" --> E; G -- "No" --> H["temperature_sensor_disable()"]; H --> I["temperature_sensor_uninstall()"]; I --> Z(End); %% Styling classDef startNode fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6; classDef processNode fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF; classDef decisionNode fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E; classDef endNode fill:#D1FAE5,stroke:#059669,stroke-width:2px,color:#065F46; classDef errorNode fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B; class A,Z startNode; class B,D,F,H,I processNode; class C,G,E decisionNode; class X errorNode; class Z endNode;
- Define a
temperature_sensor_config_t
structure. - Call
temperature_sensor_install()
to get a sensor handle. - Call
temperature_sensor_enable()
to power on and enable the sensor. - Call
temperature_sensor_get_celsius()
to read the temperature. - When done, call
temperature_sensor_disable()
and thentemperature_sensor_uninstall()
.
Note: The internal temperature sensor is often linked with the ADC (Analog-to-Digital Converter) system, as the raw sensing mechanism might be analog. The
esp_temperature_sensor
driver abstracts these underlying details.
Practical Examples
Let’s see how to use the internal temperature sensor.
Project Setup
- Create a new ESP-IDF project or use an existing one.
- Ensure your
main/CMakeLists.txt
includes the necessary components:idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES esp_log esp_common driver esp_timer freertos temperature_sensor) # 'temperature_sensor' component is needed for the driver # 'esp_common' for ESP_ERROR_CHECK # 'driver' for general driver framework dependencies
- You might need to explicitly enable the temperature sensor component in
sdkconfig
if it’s not enabled by default, although it usually is ifdriver
is included. Check under “Component config –> Temperature Sensor”.
Example 1: Reading Internal Temperature Periodically
This example initializes the internal temperature sensor and prints its reading to the console every few seconds.
main/main.c
:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_temperature_sensor.h" // Main header for the temperature sensor driver
static const char *TAG = "TEMP_SENSOR_EXAMPLE";
// Global handle for the temperature sensor
static temperature_sensor_handle_t temp_sensor_handle = NULL;
void initialize_temperature_sensor(void)
{
ESP_LOGI(TAG, "Initializing Temperature Sensor");
temperature_sensor_config_t temp_sensor_config = {
// Default configuration:
// Set the temperature range to measure.
// The driver will select the appropriate internal range and clock source.
// These are typical values; refer to datasheet for specific chip limits if needed.
.range_min = -10, // Celsius
.range_max = 80, // Celsius
// .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT, // Or specific like TEMPERATURE_SENSOR_CLK_SRC_XTAL
};
esp_err_t err = temperature_sensor_install(&temp_sensor_config, &temp_sensor_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to install temperature sensor: %s", esp_err_to_name(err));
// Consider aborting or handling the error appropriately
return;
}
ESP_LOGI(TAG, "Temperature sensor installed");
err = temperature_sensor_enable(temp_sensor_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to enable temperature sensor: %s", esp_err_to_name(err));
// Uninstall if enable fails
temperature_sensor_uninstall(temp_sensor_handle);
temp_sensor_handle = NULL; // Mark as uninitialized
return;
}
ESP_LOGI(TAG, "Temperature sensor enabled");
}
void app_main(void)
{
initialize_temperature_sensor();
if (temp_sensor_handle == NULL) {
ESP_LOGE(TAG, "Temperature sensor initialization failed. Aborting app_main.");
return;
}
float current_temp_celsius = 0;
while (1) {
esp_err_t err = temperature_sensor_get_celsius(temp_sensor_handle, ¤t_temp_celsius);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Temperature: %.2f °C", current_temp_celsius);
// Convert to Fahrenheit (optional)
// float current_temp_fahrenheit = (current_temp_celsius * 9.0f / 5.0f) + 32.0f;
// ESP_LOGI(TAG, "Temperature: %.2f °F", current_temp_fahrenheit);
} else {
ESP_LOGE(TAG, "Failed to read temperature: %s", esp_err_to_name(err));
// Handle error, e.g., re-initialize or log persistently
}
vTaskDelay(pdMS_TO_TICKS(5000)); // Read every 5 seconds
}
// Cleanup (not typically reached in this kind of continuous loop)
// ESP_LOGI(TAG, "Disabling and uninstalling temperature sensor");
// temperature_sensor_disable(temp_sensor_handle);
// temperature_sensor_uninstall(temp_sensor_handle);
}
Build Instructions:
- Open your ESP-IDF project in VS Code.
- Ensure the ESP-IDF extension is active and configured.
- Click the “Build” button (or run
idf.py build
in the ESP-IDF terminal).
Run/Flash/Observe Steps:
- Connect your ESP32 board to your computer.
- Click the “Flash” button (or run
idf.py -p /dev/ttyUSB0 flash
replacing/dev/ttyUSB0
with your serial port). - Click the “Monitor” button (or run
idf.py monitor
). - You should see log messages appearing every 5 seconds, showing the internal temperature in Celsius.
Tip: Observe how the reported temperature might slowly rise after power-on as the chip warms up (self-heating). If you run CPU-intensive tasks or enable Wi-Fi, you might see a more significant increase.
Variant Notes
The internal temperature sensor and its driver (esp_temperature_sensor.h
) are available on most modern ESP32 variants, but there can be nuances:
ESP32 Variant | Internal Temp Sensor | Supported by esp_temperature_sensor Driver | Notes |
---|---|---|---|
ESP32 | ✔ | ✔ | The original implementation. |
ESP32-S2 | ✔ | ✔ | Sensor has different characteristics; handled by driver. |
ESP32-S3 | ✔ | ✔ | Similar to S2, fully supported. |
ESP32-C3 | ✔ | ✔ | RISC-V core, sensor is supported. |
ESP32-C6 | ✔ | ✔ | RISC-V core, sensor is supported. |
ESP32-H2 | ✔ | ✔ | RISC-V core, sensor is supported. |
Key Considerations:
- API Consistency: The
esp_temperature_sensor.h
API is intended to provide a uniform way to access the sensor across supported chips. The underlying implementation details and calibration data used by the driver will vary per chip. - Accuracy and Range: While the API is consistent, the inherent accuracy, resolution, and effective measurement range of the physical sensor can differ slightly between chip variants. Always consult the latest datasheet for your specific ESP32 variant for these hardware specifications. The
range_min
andrange_max
intemperature_sensor_config_t
help the driver optimize, but the hardware has its own limits. - Self-Heating Effects: The degree of self-heating will vary depending on the chip’s architecture, power consumption characteristics, and the specific application load. RISC-V based chips (C-series, H-series) might have different thermal profiles than the Xtensa-based ones (original, S-series).
- Driver Availability: Ensure your ESP-IDF version fully supports the
esp_temperature_sensor
driver for the specific chip variant you are using. This driver is the standard for v5.x and later.
For the most part, the provided example code should work across these variants with minimal to no changes, thanks to the abstraction provided by the esp_temperature_sensor
driver.
Common Mistakes & Troubleshooting Tips
Mistake / Issue | Symptom(s) | Troubleshooting / Solution |
---|---|---|
Expecting Ambient Temperature Ignoring self-heating effect. |
Sensor reports a temperature significantly higher than the room (e.g., 40°C when room is 25°C). The reading rises when Wi-Fi or Bluetooth is used. | Acknowledge the reading is die temperature. For rough ambient estimates, measure when the chip is idle or establish an offset by comparing with an external sensor under typical load. |
Forgetting to Enable Sensor Missing temperature_sensor_enable() call. |
temperature_sensor_get_celsius() returns an ESP_ERR_INVALID_STATE error. |
Always call temperature_sensor_enable() after a successful installation via temperature_sensor_install() and before attempting to read any values. |
No Error Checking Ignoring esp_err_t return values. |
Application crashes or behaves strangely if the sensor fails to initialize or read, with no useful logs. | Wrap all driver calls in ESP_ERROR_CHECK() or an if statement to handle potential failures gracefully. Use esp_err_to_name() to log meaningful error messages. |
Missing Component Dependency Forgetting temperature_sensor in CMakeLists. |
Build fails with “undefined reference” errors for temperature sensor functions. | Ensure your main/CMakeLists.txt includes temperature_sensor in the REQUIRES or PRIV_REQUIRES list for your component. |
Incorrect Configuration Range Setting invalid values in config struct. |
temperature_sensor_install() returns an ESP_ERR_INVALID_ARG error. |
Ensure the range_min value in temperature_sensor_config_t is strictly less than the range_max value. Use reasonable defaults like -10 and 80. |
Exercises
- Temperature Logging with Timestamps:
- Modify Example 1 to include a timestamp with each temperature reading. You can use
esp_timer_get_time()
to get microseconds since boot or integrate with an SNTP client (from previous volumes) to get wall-clock time. - Log the data in a CSV-like format (e.g., “timestamp,temperature_C”).
- Modify Example 1 to include a timestamp with each temperature reading. You can use
- Thermal Alert System:
- Implement a system that reads the internal temperature periodically.
- If the temperature exceeds a predefined threshold (e.g., 60°C), print a “WARNING: High Temperature Detected!” message to the console.
- Add a “Normal Temperature” message if it drops below a hysteresis threshold (e.g., 55°C) after being high. This prevents rapid toggling of alerts.
- Average Temperature Calculation:
- Read the temperature sensor 10 times with a short delay (e.g., 100ms) between readings.
- Calculate the average of these 10 readings.
- Print the average temperature. This can help smooth out very short-term fluctuations or noise in the readings.
Summary
- ESP32 series microcontrollers include an on-chip temperature sensor primarily for measuring silicon die temperature.
- The sensor’s readings are influenced by self-heating from chip activity and the ambient environment.
- ESP-IDF v5.x provides the
esp_temperature_sensor.h
driver for a unified API to install, enable, read (in Celsius), disable, and uninstall the sensor. - The internal sensor is useful for thermal management, relative temperature changes, and system health monitoring but generally not for high-accuracy absolute ambient temperature measurements without calibration and consideration of self-heating.
- The API (
temperature_sensor_install
,temperature_sensor_enable
,temperature_sensor_get_celsius
) is designed to be consistent across supported ESP32 variants, though underlying hardware characteristics can vary slightly. - Common pitfalls include forgetting to enable the sensor, misinterpreting accuracy due to self-heating, and not handling API errors.
Further Reading
- ESP-IDF Temperature Sensor Driver Documentation:
- Temperature Sensor API Guide (Ensure the URL path reflects
v5.x
or your current stable IDF version, and replaceesp32
with your specific variant likeesp32s3
oresp32c3
if you need variant-specific nuances, though the driver page is often generic).
- Temperature Sensor API Guide (Ensure the URL path reflects
- ESP32 Series Technical Reference Manuals (TRM):
- Consult the TRM for your specific ESP32 variant for detailed hardware descriptions of the internal temperature sensor and its characteristics. These are available on the Espressif Documentation Page.
- Application Notes on Thermal Considerations:
- Look for application notes from Espressif regarding thermal design or power management, which might discuss the implications of die temperature.