In this tutorial, we will learn to interface SHT31 temperature and humidity sensor using ESP32 and ESP-IDF. This guide will include a brief description of the sensor, connection with ESP32 board and then setting up a project in VS Code with ESP-IDF extension to acquire the sensor data and display it on the console.
Before we move ahead, make sure you have the latest version of VS Code installed on your system with the ESP-IDF extension configured.
SHT31 Sensor Module Introduction
The SHT31 sensor module is used in electronic projects to measure ambient temperature and relative humidity. The module uses the SHT31 chip by Sensirion to output sensor data with great accuracy and covers a good range to be used for temperature and humidity measurements. On top of that, it is low cost and compact in nature, which uses I2C communication protocol to send data over to the microcontroller. This protocol is based on a synchronous, multi-master multi-slave system where the ESP32 board acts as the master and the SHT31 sensor acts as the slave. With its broad operating voltage range of 2.15 to 5.5V, it is a stellar choice to be used with microcntrollers.
The diagram below shows the SHT31 Sensor Module featuring the I2C interface with the SHT31 sensor chip highlighted at one side.
SHT31 Sensor Module Pinout
The diagram below shows the pinout of the SHT31 sensor module.
As you can see in the diagram above, the SHt31 sensor consists of six pins. Two are power supply pins. two are I2C communication pins, while the other two are I2C address selection (AD) and alert output (AL) pins.
VIN | This is the power supply pin which is connected with 3.3V of ESP32. You can supply power in the range of 2.4-5.5V |
GND | This is the ground pin |
SCL | This is the serial clock pin which will produce the clock signal |
SDA | This is the serial data pin which is used for sending and receiving data |
AD | This pin is the I2C address selection pin. This pin allows the user to change the I2C address of the sensor module. By default, when this pin is in a low state, the I2C address is 0x44. When the state of this pin is high, the I2C address changes to 0x45. |
AL | This pin is the alert output pin. It acts as a trigger to monitor the temperature and humidity readings. When these readings are not within the user defined range, the state of this pin goes to high. It stays high until the readings go back to the range set. |
Specifications
Let us look at some key specifications of the SHT31 sensor module.
- Supply voltage of 2.4 – 5.5V
- Average supply current of 1.7uA
- Maximum supply current of 1500uA
Humidity Measurements
- Typical relative humidity accuracy of 2 %RH
- Operating relative humidity range of 0–100 %RH
- Response time (τ63%) of 8s
Temperature Measurements
- Typical temperature accuracy of 0.2°C
- Operating temperature range of -40–125°C
- Response time (τ63%) is less than 2s
ESP32 I2C Pins
We will be using I2C interface to get SHT31 sensor readings with ESP32 and ESP-IDF. Now let’s discuss I2C pins of ESP32. The diagram below shows the pinout for the ESP32, where the default I2C pins are highlighted in red. These are the default I2C pins of the ESP32 DEVKIT module. However, if you want to use other GPIO pins as I2C pins then you will have to set them in code.
Refer to the following article to know more about ESP32 GPIO pins:
You can check this complete guide on ESP32 I2C communication:
Interfacing SHT31 Sensor Module with ESP32
We will need the following components to connect our ESP32 board with the SHT31 Sensor Module.
- ESP32 board
- SHT31 Sensor Module
- Connecting Wires
- Breadboard
The connection of SHT31 Sensor Module with the ESP32 board is straightforward as it just involves the connection of the 4 pins (GND, VCC, SDA, and SCL) with ESP32. We have to connect the VCC terminal with 3.3V pin, ground with the ground (common ground), SCL of the sensor with SCL of ESP32 board, and SDA of the sensor with the SDA pin of the ESP32 board. We will use the default I2C pins of ESP32 board to connect with the sensor module.
In ESP32, the default I2C pin for SDA is GPIO21 and for SCL is GPIO22.
The connections between the devices are specified in the table below:
SHT31 Sensor Module | ESP32 |
---|---|
GND | GND |
VCC | 3.3V |
SDA | GPIO21(I2C SDA) |
SCL | GPIO22 (I2C SCL) |
Measure SHT31 Readings with ESP32 and ESP-IDF
We will build and create a project in VS Code with ESP-IDF extension. The code will read temperature and humidity values by using the I2C device library and sht3x.h. We will use SHT3x library written by UncleRus.
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 ‘SHT31.’ For the ESP-IDF board, we have chosen the custom board option. For ESP-IDF target, we have chosen ESP32 module. Click ‘Choose Template’ button to proceed forward.
In the Extension, select ESP-IDF option:
We will click the ‘sample_project’ under the get-started tab. Now click ‘Create project using template sample_project.’
You will get a notification that the project has been created. To open the project in a new window, click ‘Yes.’
This opens the 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.
- First, let’s add the necessary header files for the libraries required for this project. Create a new folder called ‘components’ and add the following three sub-folders under it:
- esp_idf_lib_helpers
- i2cdev
- sht3x
Add the sht3x, esp_idf_lib_helpers, and i2cdev folders in ‘components’ folder by copying from this link as listed below:
Now go to main and create a new file named ‘Kconfig.projbuild‘ under the main folder. Copy the file from this destination in this newly created file.
SHT31 MenuConfig Settings ESP-IDF
Now let’s head over to the menuconfig. Open the ESP-IDF SDK Configuration Editor. Scroll down and open the Example configuration. Here we can set the configuration parameter according to our needs. This includes the demo mode, the I2C address of SHT3x, SCL GPIO pin and SDA GPIO pin. Here you can view that we have set the demo mode as High level, I2C address of SHT3x as 0x44 (default), SCL GPIO as 22 and SDA GPIO as 21. You can alter these parameters according to your requirement and then click the Save button found at the top.
Alternatively, we can also set this config value with menuconfig. Open menuconfig by typing idf.py menuconfig in the terminal. This command opens the Espressif IoT Development Framework Configuration. Head over to Example configuration and set the parameters accordingly.
- Now head over to the main.c file. The main folder contains the source code meaning the main.c file will be found here. Go to main > main.c and open it. Copy the code given below in that file and save it.
ESP32 SHT31 Display Readings Code
This is an example sketch for the driver sht3x. It allows the users to select different demos, and implements the tasks in either periodic mode or single shot mode. In single shot mode, the user can either select high level demo or low level demo from the menuconfig.
If CONFIG_EXAMPLE_SHT3X_DEMO_HL is selected, then the high level function sht3x_meaure() is used to obtain the sensor data for every cycle. The sensor readings are triggered in single shot mode, after every 5 seconds.
However, if CONFIG_EXAMPLE_SHT3X_DEMO_LL is selected, then the sensor data is measured one at a time, every 5 seconds, in single shot mode with high repeatability. Then it waits for the output and then retrieves them.
If CONFIG_SHT3X_DEMO_PERIODIC is selected, then the SHT3x sensor is started in periodic mode, which takes a measurement every second. The user task obtains the sensor data measurements after every 2 seconds.
/**
* Simple example with SHT3x sensor.
*
* It shows different user task implementations in *single shot mode* and
* *periodic mode*. In *single shot* mode either low level or high level
* functions are used.
*/
#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_system.h>
#include <sht3x.h>
#include <string.h>
#include <esp_err.h>
/* float is used in printf(). you need non-default configuration in
* sdkconfig for ESP8266, which is enabled by default for this
* example. see sdkconfig.defaults.esp8266
*/
#ifndef APP_CPU_NUM
#define APP_CPU_NUM PRO_CPU_NUM
#endif
static sht3x_t dev;
#if defined(CONFIG_EXAMPLE_SHT3X_DEMO_HL)
/*
* User task that triggers a measurement every 5 seconds. Due to power
* efficiency reasons it uses *single shot* mode. In this example it uses the
* high level function *sht3x_measure* to perform one measurement in each cycle.
*/
void task(void *pvParameters)
{
float temperature;
float humidity;
TickType_t last_wakeup = xTaskGetTickCount();
while (1)
{
// perform one measurement and do something with the results
ESP_ERROR_CHECK(sht3x_measure(&dev, &temperature, &humidity));
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
// wait until 5 seconds are over
vTaskDelayUntil(&last_wakeup, pdMS_TO_TICKS(5000));
}
}
#elif defined(CONFIG_EXAMPLE_SHT3X_DEMO_LL)
/*
* User task that triggers a measurement every 5 seconds. Due to power
* efficiency reasons it uses *single shot* mode. In this example it starts the
* measurement, waits for the results and fetches the results using separate
* functions
*/
void task(void *pvParameters)
{
float temperature;
float humidity;
TickType_t last_wakeup = xTaskGetTickCount();
// get the measurement duration for high repeatability;
uint8_t duration = sht3x_get_measurement_duration(SHT3X_HIGH);
while (1)
{
// Trigger one measurement in single shot mode with high repeatability.
ESP_ERROR_CHECK(sht3x_start_measurement(&dev, SHT3X_SINGLE_SHOT, SHT3X_HIGH));
// Wait until measurement is ready (constant time of at least 30 ms
// or the duration returned from *sht3x_get_measurement_duration*).
vTaskDelay(duration);
// retrieve the values and do something with them
ESP_ERROR_CHECK(sht3x_get_results(&dev, &temperature, &humidity));
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
// wait until 5 seconds are over
vTaskDelayUntil(&last_wakeup, pdMS_TO_TICKS(5000));
}
}
#else // CONFIG_SHT3X_DEMO_PERIODIC
/*
* User task that fetches latest measurement results of sensor every 2
* seconds. It starts the SHT3x in periodic mode with 1 measurements per
* second (*SHT3X_PERIODIC_1MPS*).
*/
void task(void *pvParameters)
{
float temperature;
float humidity;
esp_err_t res;
// Start periodic measurements with 1 measurement per second.
ESP_ERROR_CHECK(sht3x_start_measurement(&dev, SHT3X_PERIODIC_1MPS, SHT3X_HIGH));
// Wait until first measurement is ready (constant time of at least 30 ms
// or the duration returned from *sht3x_get_measurement_duration*).
vTaskDelay(sht3x_get_measurement_duration(SHT3X_HIGH));
TickType_t last_wakeup = xTaskGetTickCount();
while (1)
{
// Get the values and do something with them.
if ((res = sht3x_get_results(&dev, &temperature, &humidity)) == ESP_OK)
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
else
printf("Could not get results: %d (%s)", res, esp_err_to_name(res));
// Wait until 2 seconds (cycle time) are over.
vTaskDelayUntil(&last_wakeup, pdMS_TO_TICKS(2000));
}
}
#endif
void app_main()
{
ESP_ERROR_CHECK(i2cdev_init());
memset(&dev, 0, sizeof(sht3x_t));
ESP_ERROR_CHECK(sht3x_init_desc(&dev, CONFIG_EXAMPLE_SHT3X_ADDR, 0, CONFIG_EXAMPLE_I2C_MASTER_SDA, CONFIG_EXAMPLE_I2C_MASTER_SCL));
ESP_ERROR_CHECK(sht3x_init(&dev));
xTaskCreatePinnedToCore(task, "sh301x_test", configMINIMAL_STACK_SIZE * 8, NULL, 5, NULL, APP_CPU_NUM);
}
We will define CONFIG_SHT3X_DEMO_PERIODIC and explain the working of that part.
How the Code Works?
Firstly, we will start by including the necessary libraries for this project. This includes the SHT3x library to access the APIs for configuring the sht3x device and obtaining sensor measurements.
#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_system.h>
#include <sht3x.h>
#include <string.h>
#include <esp_err.h>
First we will create the device descriptor ‘dev’ of sht3x_t.
static sht3x_t dev;
Then for the user task implementation in periodic mode, we have the following task() function.
void task(void *pvParameters)
{
float temperature;
float humidity;
esp_err_t res;
ESP_ERROR_CHECK(sht3x_start_measurement(&dev, SHT3X_PERIODIC_1MPS, SHT3X_HIGH));
vTaskDelay(sht3x_get_measurement_duration(SHT3X_HIGH));
TickType_t last_wakeup = xTaskGetTickCount();
while (1)
{
// Get the values and do something with them.
if ((res = sht3x_get_results(&dev, &temperature, &humidity)) == ESP_OK)
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
else
printf("Could not get results: %d (%s)", res, esp_err_to_name(res));
// Wait until 2 seconds (cycle time) are over.
vTaskDelayUntil(&last_wakeup, pdMS_TO_TICKS(2000));
}
}
It initiates the periodic sensor data measurements at one measurement per second. This is done by calling the function sht3x_start_measurement(). This function takes in three parameters: the pointer to the object descriptor structure, the measurement mode, and the repeatability.
ESP_ERROR_CHECK(sht3x_start_measurement(&dev, SHT3X_PERIODIC_1MPS, SHT3X_HIGH));
After starting the sht3x measurement, we add a delay until the measurement is ready.
vTaskDelay(sht3x_get_measurement_duration(SHT3X_HIGH));
Inside the infinite while loop, we obtain the sensor measurements through sht3x_get_results() for both temperature and humidity values. These are printed on the ESP-IDF terminal after every 2 seconds.
while (1)
{
// Get the values and do something with them.
if ((res = sht3x_get_results(&dev, &temperature, &humidity)) == ESP_OK)
printf("SHT3x Sensor: %.2f °C, %.2f %%\n", temperature, humidity);
else
printf("Could not get results: %d (%s)", res, esp_err_to_name(res));
// Wait until 2 seconds (cycle time) are over.
vTaskDelayUntil(&last_wakeup, pdMS_TO_TICKS(2000));
}
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
After the code is successfully flashed, you can view the temperature and humidity readings on the console.
You may also like to read:
- ESP32 ESP-IDF BME680 Environmental Sensor (Gas, Pressure, Humidity, Temperature)
- BMP180 Sensor with ESP32 ESP-IDF
- HC-SR04 Ultrasonic Sensor with ESP32 ESP-IDF
- Interface DS18B20 with ESP32 ESP-IDF and Display Readings on OLED
- DHT22 with ESP32 ESP-IDF and Display Readings on OLED
- BME280 with ESP32 ESP-IDF and Display Readings on OLED
We are a team of experienced Embedded Software Developers with skills in developing Embedded Linux, RTOS, and IoT products from scratch to deployment with a demonstrated history of working in the embedded software industry. Contact us for your projects: admin@esp32tutorials.com
thanks