ESP32 и датчик SHT41: температура и влажность с точностью ±0,2 °C в Arduino IDE

Перевод статьи ESP32 with SHT41: Get Temperature and Humidity (Arduino IDE) — Sara Santos, Random Nerd Tutorials.
Разберёмся, как подключить к ESP32 датчик температуры и относительной влажности SHT41 и прочитать его показания из Arduino IDE. По соотношению цены и точности это один из лучших датчиков на рынке: четвёртое поколение серии SHT4x от Sensirion, с I2C-интерфейсом и очень низким потреблением. Руководство полностью подходит и для родственных датчиков SHT40 и SHT45 — схема и код не меняются.
Покажем короткое знакомство с датчиком, его подключение к ESP32 и программу, которая вытаскивает из него температуру и влажность.
Знакомство с датчиком SHT41#
SHT41 — датчик температуры и относительной влажности четвёртого поколения из серии SHT4x компании Sensirion: высокоточный и с ультранизким потреблением.

SHT41 — датчик температуры и относительной влажности серии SHT4x.
Типичная точность по температуре — ±0,2 °C, по относительной влажности — ±1,8 % RH. В даташите указан средний ток потребления 0,4 мкА, но на breakout-плате, как в нашем случае, потребление будет выше. Датчик откалиброван на заводе. Коротко о характеристиках:
- точность по температуре: ±0,2 °C;
- точность по влажности: ±1,8 % RH;
- диапазон температур: от −40 до +125 °C;
- диапазон влажности: от 0 до 100 % RH;
- напряжение питания: от 1,08 до 3,6 В;
- интерфейс: I2C;
- I2C-адрес: 0x44;
- средний ток: 0,4 мкА (для самого кристалла).
Кроме того, у датчика есть управляемый внутренний подогреватель с тремя уровнями нагрева — он рассчитан на работу в суровых условиях. Например, помогает избежать конденсации на чувствительном элементе при высокой влажности.
Подключить датчик к ESP32 или любому другому микроконтроллеру несложно: обмен идёт по протоколу I2C (подробно про I2C на ESP32 — в руководстве ESP32 I2C Communication: Pins and Commands).
В проектах удобнее использовать SHT41 в виде готового модуля. Breakout-плат с сенсорами серии SHT4x выпускается довольно много — мы возьмём ту, что на фото ниже.

Breakout-плата SHT41 с двумя разъёмами STEMMA QT / Qwiic.
На нашей плате два разъёма, совместимых со STEMMA QT / Qwiic: один — для подключения к микроконтроллеру, второй — чтобы при необходимости добавить в шину ещё I2C-датчиков или модулей. Можно вместо этого припаять штырьки и подключаться обычными джамперами или через макетную плату.
Где купить#
Сравнить цены на модуль SHT41 в разных магазинах можно на Maker Advisor:
Это руководство также совместимо с:
SHT40, SHT41 и SHT45: в чём разница#
SHT40, SHT41 и SHT45 принадлежат к одному, четвёртому поколению датчиков температуры и относительной влажности Sensirion. Работают они одинаково, и код для них один и тот же.

Вся тройка — SHT40, SHT41 и SHT45 — различается только точностью.
Разница между ними — в точности. У SHT40 и SHT41 типичная точность одинаковая (правда, SHT41 лучше удерживает её при влажности ближе к краям диапазона), а SHT45 точнее обоих.
| SHT40 | SHT41 | SHT45 | |
|---|---|---|---|
| Типичная точность по температуре | ±0,2 °C | ±0,2 °C | ±0,1 °C |
| Типичная точность по влажности | ±1,8 % RH | ±1,8 % RH | ±1,0 % RH |
| Диапазон температур | −40…+125 °C | −40…+125 °C | −40…+125 °C |
| Диапазон влажности | 0…100 % RH | 0…100 % RH | 0…100 % RH |
| Напряжение питания | 1,08…3,6 В | 1,08…3,6 В | 1,08…3,6 В |
| Интерфейс | I2C | I2C | I2C |
| Средний ток | 0,4 мкА | 0,4 мкА | 0,4 мкА |
| Время отклика по температуре | 2 с | 2 с | 2 с |
| Время отклика по влажности | 4 с | 4 с | 4 с |
| Где купить | SHT40 | SHT41 | SHT45 |
Распиновка SHT4x#
Все три датчика — SHT40, SHT41 и SHT45 — общаются по I2C, и распиновка у них одинаковая.

Распиновка модуля SHT4x.
- VIN: питание. На большинстве breakout-плат стоит стабилизатор напряжения, поэтому подавать можно тот же уровень, что и у логики микроконтроллера (например, 5 В для Arduino и 3,3 В для ESP32);
- 3Vo: выход стабилизатора (3,3 В); на некоторых платах этого вывода нет;
- GND: земля;
- SCL: линия тактирования I2C;
- SDA: линия данных I2C.
Подключение SHT4x к ESP32#
Если на вашей плате есть разъём, датчик можно подключить к ESP32 через него — либо использовать стандартные I2C-выводы платы.
| SHT41 | ESP32 DevKit | ESP32-S3 |
|---|---|---|
| VIN | 3V3 | 3V3 |
| 3Vo | не подключать | не подключать |
| GND | GND | GND |
| SCL | GPIO 22 | GPIO 9 |
| SDA | GPIO 21 | GPIO 8 |
Понадобятся следующие детали:
- плата ESP32 — любая модель на ваш выбор;
- датчик SHT41 (или SHT40, или SHT45);
- провода-джамперы;
- макетная плата.
I2C-выводы могут отличаться в зависимости от модели платы ESP32, так что при необходимости скорректируйте схему. Рекомендуемое чтение:
- ESP32-S3 DevKitC Pinout Reference Guide: GPIOs Explained
- ESP32 Pinout Reference: Which GPIO pins should you use?
Схема для ESP32-S3:

SHT41 на шине I2C платы ESP32-S3.
Схема для ESP32 DevKit:

SHT41 на шине I2C классического ESP32 DevKit.
Подготовка Arduino IDE#
Прежде чем двигаться дальше, убедитесь, что у вас установлена Arduino IDE и добавлена поддержка плат ESP32. Если ещё нет — начните с этого руководства:
Установка библиотеки SHT4x#
Библиотек для работы с SHT41 существует несколько. Мы возьмём Adafruit SHT4x — она совместима с SHT40, SHT41 и SHT45. Как альтернативу можно взять библиотеку от самой Sensirion.
Откройте в Arduino IDE менеджер библиотек, введите в поиске adafruit sht4x и установите Adafruit SHT4x Library от Adafruit (заодно установите все предложенные зависимости).

Библиотека Adafruit SHT4x ставится из менеджера библиотек.
Код: читаем температуру и относительную влажность#
Библиотека поставляется с простым примером, показывающим, как получить с датчика температуру и относительную влажность. Код и так предельно простой, поэтому мы берём исходный пример из библиотеки с небольшими правками. Он совместим с SHT40, SHT41 и SHT45.
Пример показывает, как получать температуру и влажность, как выбирать точность измерений (три варианта) и как настраивать встроенный подогреватель, если он вам нужен.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-sht41-temperature-humidity-arduino/
Based on the example provided by the Adafruit_SHT4x Library
*/
#include "Adafruit_SHT4x.h"
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
void setup() {
Serial.begin(115200);
Serial.println("SHT4x test");
if (!sht4.begin()) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
// You can have 3 different precisions, higher precision takes longer
sht4.setPrecision(SHT4X_HIGH_PRECISION);
switch (sht4.getPrecision()) {
case SHT4X_HIGH_PRECISION:
Serial.println("High precision");
break;
case SHT4X_MED_PRECISION:
Serial.println("Med precision");
break;
case SHT4X_LOW_PRECISION:
Serial.println("Low precision");
break;
}
// You can have 6 different heater settings higher heat and
// longer times uses more power and reads will take longer too
sht4.setHeater(SHT4X_NO_HEATER);
switch (sht4.getHeater()) {
case SHT4X_NO_HEATER:
Serial.println("No heater");
break;
case SHT4X_HIGH_HEATER_1S:
Serial.println("High heat for 1 second");
break;
case SHT4X_HIGH_HEATER_100MS:
Serial.println("High heat for 0.1 second");
break;
case SHT4X_MED_HEATER_1S:
Serial.println("Medium heat for 1 second");
break;
case SHT4X_MED_HEATER_100MS:
Serial.println("Medium heat for 0.1 second");
break;
case SHT4X_LOW_HEATER_1S:
Serial.println("Low heat for 1 second");
break;
case SHT4X_LOW_HEATER_100MS:
Serial.println("Low heat for 0.1 second");
break;
}
}
void loop() {
sensors_event_t humidity, temp;
uint32_t timestamp = millis();
// Get the latest temperature and humidity readings
sht4.getEvent(&humidity, &temp);
timestamp = millis() - timestamp;
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
// Convert temperature to Fahrenheit
float tempF = 1.8 * temp.temperature + 32;
Serial.print("Temperature: ");
Serial.print(tempF);
Serial.println(" degrees F");
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
Serial.println(" ");
delay(1000);
}
Как работает код#
Начнём с подключения библиотеки Adafruit_SHT4x.
#include "Adafruit_SHT4x.h"
Затем создаём объект Adafruit_SHT4x с именем sht4 — через него мы и будем обращаться к датчику.
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
В setup() инициализируем монитор последовательного порта.
void setup() {
Serial.begin(115200);
Следующие строки инициализируют сам датчик.
Serial.println("SHT4x test");
if (!sht4.begin()) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
У каждого датчика SHT4x есть уникальный серийный номер — его можно прочитать функцией readSerial() у объекта sht4.
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
Как мы уже говорили, точность измерений можно выбирать. Учитывайте, что чем выше точность, тем дольше длится чтение, — подбирайте режим под задачи своего проекта. Варианты такие:
SHT4X_HIGH_PRECISIONSHT4X_MED_PRECISIONSHT4X_LOW_PRECISION
Мы выбираем высокую точность.
sht4.setPrecision(SHT4X_HIGH_PRECISION);
Дальше в коде показано, как настраивается подогреватель. Режимы могут быть такими:
SHT4X_NO_HEATERSHT4X_HIGH_HEATER_1SSHT4X_HIGH_HEATER_100MSSHT4X_MED_HEATER_1SSHT4X_MED_HEATER_100MSSHT4X_LOW_HEATER_1SSHT4X_LOW_HEATER_100MS
В примере подогреватель не используется.
sht4.setHeater(SHT4X_NO_HEATER);
Показания мы получаем в loop().
Сначала создаём объекты типа sensors_event_t, в которые сохранятся температура и влажность.
sensors_event_t humidity, temp;
Код заодно измеряет, сколько времени занимает получение показаний, — результат складывается в переменную timestamp.
uint32_t timestamp = millis();
(...)
timestamp = millis() - timestamp;
Чтобы заполнить объекты temp и humidity свежими данными с датчика, делаем так:
sht4.getEvent(&humidity, &temp);
Наконец, когда температура и влажность лежат в соответствующих объектах, достаём их через temp.temperature и humidity.relative_humidity и печатаем в монитор последовательного порта:
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
Температуру можно вывести и в градусах Фаренгейта.
float tempF = 1.8 * temp.temperature + 32;
Serial.print("Temperature: ");
Serial.print(tempF);
Serial.println(" degrees F");
Заодно печатаем длительность чтения показаний. Поменяете точность или настройки подогревателя — увидите, что она изменилась.
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
Демонстрация#
Загрузите код на плату, не забыв выбрать правильную плату и COM-порт.
После загрузки откройте монитор последовательного порта на скорости 115200 бод и нажмите кнопку RST.
Через несколько секунд в мониторе должны пойти текущая температура, относительная влажность и время, которое занимает каждое измерение.

Температура, влажность и длительность чтения в мониторе порта.
Вариант с OLED-дисплеем#
В комплекте с библиотекой есть ещё один пример — вывод показаний датчика на OLED-дисплей.

ESP32, SHT41 и OLED-дисплей на одной шине I2C.
Понадобятся следующие детали:
- плата ESP32 — любая модель на ваш выбор;
- датчик SHT41 (или SHT40, или SHT45);
- OLED-дисплей SSD1306;
- провода-джамперы;
- макетная плата.
Схемы подключения#
OLED-дисплей тоже работает по I2C, так что подключайте его к тем же выводам.
Схема для ESP32-S3:

ESP32-S3 с датчиком SHT41 и OLED-дисплеем.
Схема для ESP32 DevKit:

ESP32 DevKit с датчиком SHT41 и OLED-дисплеем.
Установка библиотек#
Для этого проекта дополнительно понадобятся две библиотеки, если они у вас ещё не стоят:
Ищите их по названию в менеджере библиотек Arduino IDE — и обязательно установите все предложенные зависимости.

Не забудьте про предлагаемые зависимости.
Код: выводим показания на OLED#
Следующий код выводит температуру и относительную влажность на OLED-дисплей. Это слегка изменённый пример из библиотеки.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-sht41-temperature-humidity-arduino/
Based on the example provided by the Adafruit_SHT4x Library
*/
#include <Adafruit_SH110X.h>
#include <Adafruit_SSD1306.h>
#include "Adafruit_SHT4x.h"
#include <Fonts/FreeSans9pt7b.h>
#define SCREEN_WIDTH 128 // OLED display width (pixels)
#define SCREEN_HEIGHT 64 // OLED display height (pixels)
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Declaration for the SHT4X connected to the default I2C pins
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
void setup() {
Serial.begin(115200);
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
for (;;);
}
// Clear the display
display.clearDisplay();
display.display();
// Initialize SHT4x sensor
Serial.println("Initializing SHT4x");
if (! sht4.begin(&Wire)) {
Serial.println("Couldn't find SHT4x");
while (1) delay(1);
}
Serial.println("Found SHT4x sensor");
Serial.print("Serial number 0x");
Serial.println(sht4.readSerial(), HEX);
sht4.setPrecision(SHT4X_HIGH_PRECISION);
sht4.setHeater(SHT4X_NO_HEATER);
display.setFont(&FreeSans9pt7b);
display.setTextColor(SSD1306_WHITE);
}
void loop() {
sensors_event_t humidity, temp;
uint32_t timestamp = millis();
// Get the latest temperature and humidity readings
sht4.getEvent(&humidity, &temp);
// Calculate the time it takes to get a new reading
timestamp = millis() - timestamp;
Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Humidity: ");
Serial.print(humidity.relative_humidity);
Serial.println("% rH");
// Convert temperature to Fahrenheit
float tempF = 1.8 * temp.temperature + 32;
Serial.print("Temperature: ");
Serial.print(tempF);
Serial.println(" degrees F");
Serial.print("Read duration (ms): ");
Serial.println(timestamp);
display.clearDisplay();
display.setCursor(0, 20);
display.println("SHT41 Sensor");
display.setCursor(0, 40);
display.print("Temp: ");
display.print(temp.temperature,1);
display.println(" C");
// Display temperature in Fahrenheit
//display.print("Temp: ");
//display.print(tempF,1);
//display.println(" F");
display.print("Hum: ");
display.print(humidity.relative_humidity,1);
display.println(" %");
display.display();
yield();
delay(100);
}
Если вам уже приходилось работать с OLED-дисплеем на контроллере SSD1306, код будет вполне понятен. Подробно про подключение и программирование такого дисплея к ESP32 — в руководстве ESP32 OLED Display with Arduino IDE.
Демонстрация#
После загрузки кода OLED-дисплей покажет текущую температуру и относительную влажность, как на фото.

Температура и влажность на экране.
Итог#
В этом руководстве мы подключили к ESP32 датчик температуры и относительной влажности SHT41 и прочитали его показания из Arduino IDE. Всё то же самое работает и с SHT40, и с SHT45 — схема и код не отличаются.
SHT41 — один из лучших датчиков по соотношению цены и характеристик, так что это отличный выбор для любительских IoT-проектов и умного дома. Если планируете собирать что-то посерьёзнее — посмотрите монитор качества воздуха на ESP32 с датчиком SPS30, а если нужны ещё и атмосферное давление — перевод про датчик BME280.
У Random Nerd Tutorials есть руководства и по другим популярным датчикам температуры и влажности:
- DS18B20 — датчик температуры;
- DHT11/DHT22 — температура и влажность;
- BME680 — газ, давление, влажность, температура.