ESP32 Internal Temperature Sensor with ESP-IDF

Temperature monitoring is a crucial aspect of many projects, from environmental monitoring systems to industrial automation. The ESP32 microcontroller, with its built-in temperature sensor, offers a convenient and reliable solution for capturing temperature readings. In this detailed guide, we will explore how to utilize the ESP-IDF framework to access and utilize the internal temperature sensor of the ESP32-S2 board. We will walk through the necessary steps to set up the development environment, create an example project, and retrieve temperature data using the ESP-IDF APIs.

In this ESP-IDF guide, we will learn how to use the ESP32-S2 internal temperature sensor to monitor temperature readings. We will create an example project provided by ESP-IDF that uses the temperature sensor driver. Through that example, we will demonstrate the use of the necessary APIs to fetch the temperature readings.

ESP32 Chips with Internal Temperature Sensor Support

The internal temperature sensor is part of some ESP32 boards including ESP32-S2, ESP32-S3, ESP32-C3, and ESP32-C2. This onboard temperature sensor is usually used to monitor the core temperature changes of the chip, whereby possessing a temperature range of -40°C to 125°C. It features an 8-bit Sigma-Delta ADC and a temperature offset DAC. The temperature sensor works by producing a voltage reading that changes with the temperature. This voltage reading is converted into a digital value through the ADC. The digital value then gets scaled according to the standard units which is then displayed as the temperature reading in degrees Celsius.

The table below shows the measurement range, offset, and measurement error for the in-built temperature sensor. It is as provided by Espressif. Among these readings, offset = 0 is the main measurement option, and other values are extended measurement options.

OffsetMeasure Range (Celsius)Measure Error (Celsius)
-250 ~ 125< 3
-120 ~ 100< 2
0-10 ~ 80< 1
1-30 ~ 50< 2
2-40 ~ 20< 3

Prerequisites

Before we move ahead, make sure you have the latest version of VS Code installed on your system with the ESP-IDF extension configured.

ESP32 Temperature Sensor with ESP-IDF

Let’s look at an example sketch provided by ESP-IDF to learn how to monitor the temperature readings accessed from the in-built temperature sensor of ESP32.

Create Example Project

Open your VS Code and head over to View > Command Palette. Type ESP-IDF: New Project in the search bar and press enter.

Specify the project name and directory. We have named our project ‘ESP_IDF_TEMP_SENSOR’. For the ESP-IDF board, we have chosen the custom board option. For the ESP-IDF target, we have chosen the ESP32-S2 module. Note: This example uses the driver/temp_sensor.h which is only supported for ESP32-C2, ESP32-C3, ESP32-S2, and ESP32-S3 targets. Do not set the target to ESP32 module. It will not work.

Click the ‘Choose Template’ button to proceed forward.

ESP32 Temperature Sensor using ESP-IDF Create Project 1

In the Extension, select the ESP-IDF option:

ESP-IDF in VS Code New Project 2

We will click the ‘temp_sensor’ under the Peripherals tab. Now click ‘Create a project using template temp_sensor.’

ESP32 Temperature Sensor using ESP-IDF Create Project 2

You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’

This opens our ESP_IDF_TEMP_SENSOR project that we created inside the EXPLORER tab. There are several folders inside our project folder. This is the same for every project which you will create through ESP-IDF Explorer. The main folder contains the source code meaning the main.c file will be found here.

Now go to main > temp_sensor_main.c and open it.

ESP32 Temperature Sensor using ESP-IDF Create Project 3

The following code opens up which is shown below. This example displays the temperature readings in the terminal after installing the temperature sensor and enabling it.

ESP-IDF Code: ESP32 Temperature Sensor

/* Temperature Sensor Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/* Note: ESP32 don't support temperature sensor */

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
#include "driver/temp_sensor.h"

static const char *TAG = "TempSensor";

void tempsensor_example(void *arg)
{
    // Initialize touch pad peripheral, it will start a timer to run a filter
    ESP_LOGI(TAG, "Initializing Temperature sensor");
    float tsens_out;
    temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
    temp_sensor_get_config(&temp_sensor);
    ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);
    temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~  80℃, error < 1℃.
    temp_sensor_set_config(temp_sensor);
    temp_sensor_start();
    ESP_LOGI(TAG, "Temperature sensor started");
    while (1) {
        vTaskDelay(1000 / portTICK_RATE_MS);
        temp_sensor_read_celsius(&tsens_out);
        ESP_LOGI(TAG, "Temperature out celsius %f°C", tsens_out);
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    xTaskCreate(tempsensor_example, "temp", 2048, NULL, 5, NULL);
}

#elif CONFIG_IDF_TARGET_ESP32

void app_main(void)
{
    printf("ESP32 don't support temperature sensor\n");
}

#endif

How does the Code Work?

Firstly, we will start by including the necessary libraries that include the FreeRTOS libraries to generate delays, esp_log.h to log the informational messages, and driver/temp_sensor.h for the functionality of the in-built temperature sensor. However, this library will only work if the configured target is either ESP32S2 or ESP32C3.

#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/* Note: ESP32 don't support temperature sensor */

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
#include "driver/temp_sensor.h"

This code uses Informational Logging. The log function takes in two arguments. The first argument is the tag and the second argument is a formatted string. Therefore this global variable will be useful while calling the ESP_LOGI() functions. Here, “TempSensor” is the tag that will be used while logging.

static const char *TAG = "TempSensor";

Then we have a function called tempsensor_example(). It first initializes the temperature sensor, starts it and then logs the current temperature readings in the terminal.

void tempsensor_example(void *arg)
{
    // Initialize touch pad peripheral, it will start a timer to run a filter
    ESP_LOGI(TAG, "Initializing Temperature sensor");
    float tsens_out;
    temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
    temp_sensor_get_config(&temp_sensor);
    ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);
    temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~  80℃, error < 1℃.
    temp_sensor_set_config(temp_sensor);
    temp_sensor_start();
    ESP_LOGI(TAG, "Temperature sensor started");
    while (1) {
        vTaskDelay(1000 / portTICK_RATE_MS);
        temp_sensor_read_celsius(&tsens_out);
        ESP_LOGI(TAG, "Temperature out celsius %f°C", tsens_out);
    }
    vTaskDelete(NULL);
}

First, we get the parameter of the temperature sensor using temp_sensor_get_config(). It takes in a single parameter temp_sensor which is a pointer to the already initialized configuration structure which is set to TSENS_CONFIG_DEFAULT() so that the initialization of the configuration is at default values. Here temp_sensor_config_t is a structure that is used for configuring the temperature sensor reading.

temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
temp_sensor_get_config(&temp_sensor);

At this point, the values for the default DAC and Clk are printed in the terminal.

ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);

Next, the DAC offset is set to the default value which is 0. This enables the range of the measured readings to be within -10~80 Celsius with a measured error of less than 1.

temp_sensor.dac_offset = TSENS_DAC_DEFAULT;

Then the temp_sensor_set_config() function is called with temp_sensor as a parameter inside it. This is used to set the parameter of the temperature sensor.

temp_sensor_set_config(temp_sensor);

The temp_sensor_start() function, starts measuring the temperature readings. Moreover, the informational log prints “Temperature sensor started” in the terminal.

temp_sensor_start();
ESP_LOGI(TAG, "Temperature sensor started");

Inside the while loop, after every second, the function temp_sensor_read_celsius() reads the temperature sensor data in degrees Celsius. This function takes the address of the measured output value (&tsens_out) as a parameter inside it. This measured output value is printed in the terminal when it is read.

    while (1) {
        vTaskDelay(1000 / portTICK_RATE_MS);
        temp_sensor_read_celsius(&tsens_out);
        ESP_LOGI(TAG, "Temperature out celsius %f°C", tsens_out);
    }

Then we will delete this task by calling the vTaskDelete() function. NULL is passed as a parameter inside it, thus causing it to delete the calling task.

vTaskDelete(NULL);

app_main()

Inside the main() function, we will create the task. To create a task, use the function xTaskCreate(). This function takes in several arguments.

  • The first argument is the name of the function. In our case, it is set to tempsensor_example.
  • The second argument is the name of the task for descriptive purposes. In our case, it is set as “temp.”
  • The third argument specifies the stack size of the task. This indicates the amount of memory we want to reserve for the particular task. It is set to ‘2048’.
  • The fourth argument is the parameter. It is a value that is passed as the parameter to the created task. This can be used to specify a variable that is being used in the main function and whose value needs to be added to the task. This argument is set as NULL which indicates that this property is not being used.
  • The fifth argument is the priority of the task. It is set to ’5.’
  • The last argument is the handle which is used to change the function of the task eg. suspend, delete, resume, get or set a config of task. This works as a pointer therefore the ampersand symbol is used with it. It is optional so we can also set it to NULL. It is set to NULL.
void app_main(void)
{
    xTaskCreate(tempsensor_example, "temp", 2048, NULL, 5, NULL);
}

In this case, if the target was set to ESP32, then the terminal will display the message: “ESP32 doesn’t support temperature sensor.”

#elif CONFIG_IDF_TARGET_ESP32

void app_main(void)
{
    printf("ESP32 don't support temperature sensor\n");
}
#endif

Compiling the Sketch

To flash your chip, type the following command in the serial terminal. Remember to replace the COM port with the one through which your board is connected.

idf.py -p COMX flash monitor
ESP32 Temperature Sensor using ESP-IDF project flash chip

After the code flashes successfully, you can view all the informational logs with the temperature readings in degrees Celsius.

esp32 esp-idf internal temperature sensor example

Conclusion

In conclusion, this ESP-IDF guide has provided a detailed walkthrough of leveraging the ESP32-S2 internal temperature sensor for temperature monitoring using ESP-IDF. By following the step-by-step instructions, developers can easily set up their development environment, create an example project, and access temperature readings from the onboard sensor. The guide has covered important concepts such as the specifications of the temperature sensor, the use of APIs to fetch temperature readings, and the compatibility with various ESP32 models. Armed with this knowledge, developers can confidently incorporate temperature monitoring capabilities into their ESP32 projects. Whether it’s for environmental monitoring, industrial automation, or any other application requiring temperature data, the ESP32-S2 internal temperature sensor combined with ESP-IDF provides a reliable and accessible solution.

You may also like to read:

Leave a Comment