¿Tu DHT22 marca 99 % de humedad una mañana de invierno y no vuelve a bajar en todo el día? Es uno de los problemas más comunes cuando un sensor de humedad barato pasa una noche de condensación en Santiago, Concepción o el sur. El SHT41 de Sensirion es una respuesta seria a eso: un sensor de cuarta generación, calibrado de fábrica, con interfaz I2C y un calefactor interno que justamente sirve para sacarle el agua de encima.

En esta guía vas a conectar un SHT41 a un ESP32, leer temperatura y humedad relativa desde el Arduino IDE y después mostrar los datos en una pantalla OLED. Al final vas a entender qué significan los modos de precisión y de calefactor, cuánto demora cada lectura y en qué casos conviene el SHT41 frente al DHT22 o al BME280. Todo lo que aprendas aquí sirve igual para el SHT40 y el SHT45: mismo pinout, misma librería y mismo código.

Placa del sensor SHT41 con la serigrafía que indica la versión del chip

Concepto: qué hace distinto al SHT41

El SHT41 mide la humedad con un condensador cuya capacitancia cambia según el vapor de agua que absorbe una capa de polímero, y la temperatura con una referencia de banda prohibida (bandgap) integrada en el mismo chip. Las dos mediciones salen ya compensadas y con CRC por I2C, así que el microcontrolador no tiene que hacer ninguna calibración.

Sus datos principales, según la hoja de datos:

  • Precisión típica de temperatura: ±0,2 °C
  • Precisión típica de humedad: ±1,8 %HR
  • Rango: -40 a 125 °C y 0 a 100 %HR
  • Alimentación del chip: 1,08 a 3,6 V
  • Dirección I2C: 0x44
  • Consumo promedio: 0,4 µA (chip solo; la placa breakout consume más por su regulador y su LED)

El detalle que pocos sensores de este segmento tienen es el calefactor interno, que se puede encender en tres niveles de potencia por 0,1 o 1 segundo. Sirve para evaporar la condensación que se forma sobre el sensor cuando la humedad está cerca del 100 %, que es precisamente lo que deja "pegados" a otros sensores capacitivos.

SHT40, SHT41 y SHT45: cuál elegir

Los tres son de la misma familia, usan el mismo código y se conectan igual. La diferencia está en la precisión:

SHT40 SHT41 SHT45
Precisión de temperatura ±0,2 °C ±0,2 °C ±0,1 °C
Precisión de humedad ±1,8 %HR ±1,8 %HR ±1,0 %HR
Tiempo de respuesta (temperatura) 2 s 2 s 2 s
Tiempo de respuesta (humedad) 4 s 4 s 4 s

El SHT40 y el SHT41 tienen la misma precisión típica, pero el SHT41 la mantiene mejor cuando la humedad se acerca a los extremos. El SHT45 es el que conviene si necesitas una referencia de laboratorio.

Las tres versiones del sensor: SHT40, SHT41 y SHT45

SHT41 frente al DHT22 y al BME280

Esta es la comparación que más importa a la hora de elegir sensor para una estación en casa:

SHT41 DHT22 BME280
Protocolo I2C (0x44) Un cable propio, con tiempos estrictos I2C o SPI
Precisión de humedad ±1,8 %HR ±2 a 5 %HR ±3 %HR
Precisión de temperatura ±0,2 °C ±0,5 °C ±1 °C
Lecturas por segundo Varias (según precisión) Una cada 2 s como máximo Varias
Presión atmosférica No No Sí
Calefactor anticondensación Sí No No

En la práctica: si te interesa la presión (para una estación meteorológica o un altímetro), el BME280 sigue siendo la opción. Si lo que quieres es humedad confiable, en particular en invierno con neblina matinal o en un invernadero, el SHT41 le gana a los dos. Un detalle del BME280 que suele sorprender: su sensor de temperatura se calienta con el propio uso del chip y tiende a marcar algo más alto, lo que a su vez baja la humedad relativa calculada. El DHT22, por su parte, usa un protocolo de un cable que depende de tiempos de microsegundos y a veces devuelve NaN si el ESP32 está ocupado con el WiFi.

Hardware: la placa y las conexiones

Trabajar con el chip suelto es incómodo (es un encapsulado DFN de 1,5 mm), así que lo normal es usar una placa breakout. La del tutorial original trae dos conectores STEMMA QT / Qwiic para I2C: uno va al microcontrolador y el otro permite encadenar más sensores I2C. Si tu placa no los tiene, o no tienes cables Qwiic, sueldas la tira de pines y usas cables jumper con una protoboard.

Placa breakout del SHT41 con sus pines y los dos conectores I2C

Los pines de la placa son:

  • VIN: alimentación. La mayoría de las placas trae regulador, así que puedes darle el mismo nivel lógico de tu microcontrolador (5 V en un Arduino, 3,3 V en el ESP32).
  • 3Vo: salida del regulador de 3,3 V. No todas las placas lo tienen y en este montaje queda libre.
  • GND: tierra.
  • SCL: reloj del bus I2C.
  • SDA: datos del bus I2C.

El sensor se cablea con cuatro conexiones a los pines I2C por defecto del ESP32:

SHT41 ESP32 DevKit ESP32-S3
VIN 3V3 3V3
3Vo No conectar No conectar
GND GND GND
SCL GPIO 22 GPIO 9
SDA GPIO 21 GPIO 8

Los pines I2C cambian según el modelo de placa, así que revisa el pinout de la tuya antes de cablear. Si necesitas usar otros pines, puedes llamar a Wire.begin(SDA, SCL) con los números que quieras antes de sht4.begin().

Diagrama de conexión del SHT41 a un ESP32 DevKit

Diagrama de conexión del SHT41 a un ESP32-S3 DevKit

Un consejo de montaje que el original no menciona: aleja el sensor del ESP32. El chip del ESP32 se calienta varios grados cuando el WiFi está activo, y si el SHT41 queda pegado a la placa vas a medir el calor del microcontrolador, no el del ambiente. Con un cable de 10 a 20 cm basta.

Montaje real del ESP32 con el sensor SHT41

Software: librería y primer sketch

Necesitas el Arduino IDE con el soporte para placas ESP32 instalado. Para el sensor hay varias librerías; aquí se usa la Adafruit SHT4x, compatible con SHT40, SHT41 y SHT45. Sensirion también publica una propia si prefieres la oficial.

En el Arduino IDE abre el gestor de librerías, busca adafruit sht4x e instala la Adafruit SHT4x Library. Acepta las dependencias que te ofrezca (Adafruit BusIO y Adafruit Unified Sensor).

Instalación de la librería Adafruit SHT4x en el gestor de librerías del Arduino IDE

El sketch de abajo es el ejemplo de la librería con algunos ajustes de los autores originales. Lee temperatura y humedad cada segundo, muestra cómo elegir la precisión y deja preparado el calefactor:

C++
/*
  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);
}

Cómo funciona el código

El sketch arranca incluyendo la librería y creando un objeto sht4 que representa al sensor. En setup() se abre el monitor serie a 115200 baudios y se llama a sht4.begin(). Si no encuentra el sensor en la dirección 0x44, el programa se queda detenido en un bucle con el mensaje "Couldn't find SHT4x". Si eso te pasa, revisa en este orden: que SDA y SCL no estén invertidos, que la placa reciba 3,3 V y que estés usando los pines I2C de tu modelo de ESP32.

Cada SHT4x trae un número de serie único que se obtiene con sht4.readSerial(). Es útil si vas a tener varios sensores en una red y quieres saber cuál mandó cada dato.

Después vienen las dos decisiones importantes:

  • Precisión (setPrecision): SHT4X_HIGH_PRECISION, SHT4X_MED_PRECISION o SHT4X_LOW_PRECISION. Más precisión implica más repeticiones internas de la medición y, por lo tanto, más tiempo y algo más de consumo. Según la hoja de datos, una lectura en alta precisión toma cerca de 8 ms y en baja, unos 2 ms.
  • Calefactor (setHeater): siete opciones, desde SHT4X_NO_HEATER hasta SHT4X_HIGH_HEATER_1S. El ejemplo lo deja apagado, que es lo correcto para medir el ambiente.

En loop() se crean dos estructuras sensors_event_t, una para la humedad y otra para la temperatura, y sht4.getEvent(&humidity, &temp) las llena con la lectura nueva. Los valores quedan en temp.temperature y humidity.relative_humidity. El código también convierte a grados Fahrenheit y mide con millis() cuánto demoró la lectura: si cambias la precisión o enciendes el calefactor, vas a ver cómo cambia ese tiempo.

Pruebas: lo que deberías ver

Sube el sketch, elige la placa y el puerto correctos, abre el monitor serie a 115200 baudios y presiona el botón RST del ESP32. En unos segundos aparecen la temperatura, la humedad y la duración de cada lectura.

Lecturas de temperatura y humedad del SHT41 en el monitor serie

Una prueba rápida para confirmar que todo responde: sopla suavemente sobre el sensor. La humedad debería subir varios puntos en un par de segundos y volver a bajar de a poco. Si la temperatura tampoco se mueve al tocar el sensor con el dedo, probablemente estás leyendo valores congelados de un sensor mal conectado.

Segunda parte: mostrar los datos en una pantalla OLED

La pantalla OLED SSD1306 de 128x64 también es I2C, así que comparte los mismos dos pines con el sensor: el bus I2C admite varios dispositivos, cada uno con su dirección (0x44 el SHT41 y 0x3C la pantalla).

Montaje del ESP32 con el SHT41 y la pantalla OLED

Conecta VCC, GND, SDA y SCL de la pantalla a los mismos pines que usa el sensor:

Diagrama de conexión del ESP32 DevKit con el SHT41 y la pantalla OLED en el mismo bus I2C

Diagrama de conexión del ESP32-S3 con el SHT41 y la pantalla OLED

Para la pantalla instala también Adafruit SSD1306 y Adafruit GFX desde el gestor de librerías, con sus dependencias sugeridas.

Dependencias que ofrece instalar el gestor de librerías del Arduino IDE

Este sketch muestra la temperatura y la humedad en la pantalla, con la fuente FreeSans de 9 puntos, y sigue enviando todo al monitor serie:

C++
/*
  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);
}

La parte nueva respecto del primer sketch es la pantalla: display.begin(SSD1306_SWITCHCAPVCC, 0x3C) la inicia en su dirección, setFont() y setTextColor() definen el estilo, y en cada vuelta del loop() se borra la pantalla, se escriben las líneas con setCursor() y print(), y se manda todo junto con display.display(). El segundo argumento de print(temp.temperature,1) deja un solo decimal, que es lo razonable para un sensor de ±0,2 °C.

Ojo con un detalle: este sketch lee el sensor cada 100 ms. Para una pantalla está bien, pero si después lo pasas a un registro de datos, una lectura por segundo (o menos) es más que suficiente, porque el sensor tarda 2 a 4 segundos en responder a un cambio real del ambiente.

La pantalla OLED mostrando la temperatura y la humedad leídas del SHT41

Variantes y mejoras

  • Usa el calefactor contra la condensación. Si el sensor va en un invernadero, un baño o al exterior en el sur de Chile, programa un pulso de SHT4X_MED_HEATER_1S cada 10 o 15 minutos cuando la humedad pase del 95 %. Descarta la lectura que viene justo después del pulso (sale con la temperatura alterada) y espera unos segundos a que el sensor se enfríe antes de volver a medir.
  • Calcula el punto de rocío. Con temperatura y humedad puedes estimar a qué temperatura se condensa el agua usando la fórmula de Magnus. Es el dato que de verdad sirve para anticipar hongos en una pieza mal ventilada o escarcha sobre los cultivos en las noches de helada.
  • Llévalo a Home Assistant por WiFi. Publica las lecturas por MQTT cada minuto y pon el ESP32 en deep sleep entre envíos. Con una batería 18650 el nodo puede durar semanas, y el SHT41 consume tan poco que el gasto lo pone casi entero el WiFi.

Personalización para Chile

En Chile consigues lo necesario para el montaje en MechatronicStore:

  • ESP32 con Wifi y Bluetooth ESP WROOM-32 Micro USB (SKU N-303): la placa principal, con sus pines I2C en GPIO 21 (SDA) y GPIO 22 (SCL), igual que el DevKit del tutorial original.
  • Pantalla Oled 128x64 I2C 0.96" SSD1315 (SKU D-111): para la segunda parte. Usa el controlador SSD1315, que acepta los mismos comandos que el SSD1306, así que funciona con la librería Adafruit SSD1306 y la dirección 0x3C del código sin cambios.
  • Breadboard / Protoboard 830 puntos MB102 (SKU C-302): para montar el sensor y la pantalla sin soldar.
  • Cables macho macho 40 piezas 20cm (SKU C-411): para unir la protoboard con el ESP32.
  • Cable USB a Micro USB (SKU X3-10): para programar y alimentar la placa desde el computador.

El SHT41 en sí no está hoy en el catálogo. Si quieres armar el proyecto con lo que hay en stock local, el Módulo Sensor de Temperatura y Humedad Digital AHT10 (SKU G-212) también es I2C y se cablea igual, aunque necesita la librería Adafruit AHTX0 y tiene menos precisión en humedad. Si el sensor va a la intemperie o dentro de un estanque, la Sonda Impermeable Metálica SHT30 (SKU G-073) es de Sensirion, de la generación anterior, y viene protegida en una cápsula metálica.

Recursos

Versión chilena con componentes en stock local en MechatronicStore.