Перевод статьи 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

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 выпускается довольно много — мы возьмём ту, что на фото ниже.

Модуль с датчиком SHT41 и разъёмами STEMMA QT / Qwiic

Breakout-плата SHT41 с двумя разъёмами STEMMA QT / Qwiic.

На нашей плате два разъёма, совместимых со STEMMA QT / Qwiic: один — для подключения к микроконтроллеру, второй — чтобы при необходимости добавить в шину ещё I2C-датчиков или модулей. Можно вместо этого припаять штырьки и подключаться обычными джамперами или через макетную плату.

Где купить#

Сравнить цены на модуль SHT41 в разных магазинах можно на Maker Advisor:

Это руководство также совместимо с:

SHT40, SHT41 и SHT45: в чём разница#

SHT40, SHT41 и SHT45 принадлежат к одному, четвёртому поколению датчиков температуры и относительной влажности Sensirion. Работают они одинаково, и код для них один и тот же.

Датчики SHT40, SHT41 и SHT45

Вся тройка — SHT40, SHT41 и SHT45 — различается только точностью.

Разница между ними — в точности. У SHT40 и SHT41 типичная точность одинаковая (правда, SHT41 лучше удерживает её при влажности ближе к краям диапазона), а SHT45 точнее обоих.

SHT40SHT41SHT45
Типичная точность по температуре±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 % RH0…100 % RH0…100 % RH
Напряжение питания1,08…3,6 В1,08…3,6 В1,08…3,6 В
ИнтерфейсI2CI2CI2C
Средний ток0,4 мкА0,4 мкА0,4 мкА
Время отклика по температуре2 с2 с2 с
Время отклика по влажности4 с4 с4 с
Где купитьSHT40SHT41SHT45

Распиновка SHT4x#

Все три датчика — SHT40, SHT41 и SHT45 — общаются по I2C, и распиновка у них одинаковая.

Распиновка модуля SHT4x: VIN, 3Vo, GND, SCL, SDA

Распиновка модуля SHT4x.

  • VIN: питание. На большинстве breakout-плат стоит стабилизатор напряжения, поэтому подавать можно тот же уровень, что и у логики микроконтроллера (например, 5 В для Arduino и 3,3 В для ESP32);
  • 3Vo: выход стабилизатора (3,3 В); на некоторых платах этого вывода нет;
  • GND: земля;
  • SCL: линия тактирования I2C;
  • SDA: линия данных I2C.

Подключение SHT4x к ESP32#

Если на вашей плате есть разъём, датчик можно подключить к ESP32 через него — либо использовать стандартные I2C-выводы платы.

SHT41ESP32 DevKitESP32-S3
VIN3V33V3
3Voне подключатьне подключать
GNDGNDGND
SCLGPIO 22GPIO 9
SDAGPIO 21GPIO 8

Понадобятся следующие детали:

I2C-выводы могут отличаться в зависимости от модели платы ESP32, так что при необходимости скорректируйте схему. Рекомендуемое чтение:

Схема для ESP32-S3:

Схема подключения датчика SHT41 к ESP32-S3

SHT41 на шине I2C платы ESP32-S3.

Схема для ESP32 DevKit:

Схема подключения датчика SHT41 к 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 в менеджере библиотек Arduino IDE

Библиотека 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);
}

Исходник скетча на GitHub.

Как работает код#

Начнём с подключения библиотеки 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_PRECISION
  • SHT4X_MED_PRECISION
  • SHT4X_LOW_PRECISION

Мы выбираем высокую точность.

sht4.setPrecision(SHT4X_HIGH_PRECISION);

Дальше в коде показано, как настраивается подогреватель. Режимы могут быть такими:

  • SHT4X_NO_HEATER
  • SHT4X_HIGH_HEATER_1S
  • SHT4X_HIGH_HEATER_100MS
  • SHT4X_MED_HEATER_1S
  • SHT4X_MED_HEATER_100MS
  • SHT4X_LOW_HEATER_1S
  • SHT4X_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.

Через несколько секунд в мониторе должны пойти текущая температура, относительная влажность и время, которое занимает каждое измерение.

Показания датчика SHT41 в мониторе последовательного порта Arduino IDE

Температура, влажность и длительность чтения в мониторе порта.

Вариант с OLED-дисплеем#

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

ESP32 с датчиком SHT41 и OLED-дисплеем

ESP32, SHT41 и OLED-дисплей на одной шине I2C.

Понадобятся следующие детали:

Схемы подключения#

OLED-дисплей тоже работает по I2C, так что подключайте его к тем же выводам.

Схема для ESP32-S3:

Схема подключения ESP32-S3, датчика SHT41 и OLED-дисплея

ESP32-S3 с датчиком SHT41 и OLED-дисплеем.

Схема для ESP32 DevKit:

Схема подключения ESP32 DevKit, датчика SHT41 и OLED-дисплея

ESP32 DevKit с датчиком SHT41 и OLED-дисплеем.

Установка библиотек#

Для этого проекта дополнительно понадобятся две библиотеки, если они у вас ещё не стоят:

Ищите их по названию в менеджере библиотек Arduino IDE — и обязательно установите все предложенные зависимости.

Установка зависимостей при установке библиотеки Adafruit

Не забудьте про предлагаемые зависимости.

Код: выводим показания на 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);
}

Исходник скетча на GitHub.

Если вам уже приходилось работать с OLED-дисплеем на контроллере SSD1306, код будет вполне понятен. Подробно про подключение и программирование такого дисплея к ESP32 — в руководстве ESP32 OLED Display with Arduino IDE.

Демонстрация#

После загрузки кода OLED-дисплей покажет текущую температуру и относительную влажность, как на фото.

Показания датчика SHT41 на OLED-дисплее

Температура и влажность на экране.

Итог#

В этом руководстве мы подключили к ESP32 датчик температуры и относительной влажности SHT41 и прочитали его показания из Arduino IDE. Всё то же самое работает и с SHT40, и с SHT45 — схема и код не отличаются.

SHT41 — один из лучших датчиков по соотношению цены и характеристик, так что это отличный выбор для любительских IoT-проектов и умного дома. Если планируете собирать что-то посерьёзнее — посмотрите монитор качества воздуха на ESP32 с датчиком SPS30, а если нужны ещё и атмосферное давление — перевод про датчик BME280.

У Random Nerd Tutorials есть руководства и по другим популярным датчикам температуры и влажности:

  • DS18B20 — датчик температуры;
  • DHT11/DHT22 — температура и влажность;
  • BME680 — газ, давление, влажность, температура.