Ejercicio 01 — Leer temperatura y humedad de un DHT22 y mostrarlas por el Monitor…

Dificultad: verde · Módulo 06 (Sensores comunes)

Enunciado

Leer temperatura y humedad de un DHT22 y mostrarlas por el Monitor Serie.

Montaje (Arduino UNO)

DHT22 (VCC5V, DATApin 2, GNDGND) Librería: ‘DHT sensor library’ (Adafruit) + ‘Adafruit Unified Sensor’

Cómo se resuelve

Este es el primer ejercicio del curso en el que el programa no compila hasta que hagas algo fuera del editor: instalar una librería. Merece la pena empezar por ahí, porque es donde casi todo el mundo se atasca.

El DHT22 no entrega su medida como un voltaje. Cuando le preguntas, contesta por un único cable con una ristra de 40 bits, y cada bit se distingue del siguiente por la duración del pulso. Traducir eso a un número de grados es un trabajo de temporización fino que ya hizo otra persona, y esa persona lo publicó como librería. Para usarla hacen falta dos pasos: instalarla desde el gestor de bibliotecas del Arduino IDE —DHT sensor library de Adafruit y, además, Adafruit Unified Sensor, de la que depende— y luego incluirla en el sketch con #include <DHT.h>. En Wokwi el equivalente al primer paso es el fichero libraries.txt. Si haces solo el #include, el compilador te dirá DHT.h: No such file or directory, y ese mensaje no habla de tu código: habla de que el fichero no está en tu ordenador.

Las tres líneas de configuración se leen de arriba abajo:

#define DHTPIN  2
#define DHTTYPE DHT22
 
DHT dht(DHTPIN, DHTTYPE);

Los #define son sustituciones de texto que hace el compilador antes de compilar; aquí cumplen el mismo papel que el const int que ya conoces, dar nombre a un valor. La tercera línea es nueva: crea un objeto llamado dht, una variable que no guarda un número sino el sensor entero. Al construirlo le pasas las dos cosas que la librería no puede adivinar sola: que está conectado al pin 2 y que es un DHT22 y no un DHT11, porque la misma librería sirve para los dos modelos y sus tiempos internos no son iguales. A partir de aquí todo lo que quieras del sensor se lo pides al objeto con un punto.

En setup() hay dos arranques, y son de la misma naturaleza aunque uno sea del sensor y otro del ordenador: Serial.begin(9600) abre el canal serie a 9600 baudios —recuerda poner esa misma velocidad en el Monitor Serie o verás caracteres raros— y dht.begin() inicializa el sensor. Preparación que se hace una vez.

El loop() empieza con delay(2000), y esos dos segundos son una restricción física, no un capricho de estilo: el DHT22 tarda ese tiempo en tomar una medida nueva. Si le preguntas antes, no te da un error, te da basura. Fíjate en que el delay está al principio del bucle y no al final. En régimen permanente da igual, porque el bucle es circular y de todos modos pasan dos segundos entre lecturas, pero ponerlo arriba asegura que también hay una espera antes de la primerísima lectura, justo después de dht.begin(), cuando el sensor aún se está despertando.

Luego las dos lecturas, ambas en float porque los grados y el porcentaje tienen decimales:

float humedad     = dht.readHumidity();
float temperatura = dht.readTemperature();

readTemperature() devuelve grados Celsius; si alguna vez los quieres en Fahrenheit, la librería acepta un argumento para eso, pero aquí no hace falta.

Y ahora la parte del ejercicio que de verdad enseña algo, que es la que casi nadie escribiría por su cuenta:

if (isnan(humedad) || isnan(temperatura)) {
    Serial.println("Error leyendo el DHT22");
    return;
}

Cuando la lectura falla —cable suelto, sensor ocupado, ruido eléctrico— estas funciones no lanzan ningún error: devuelven NaN, Not a Number, el valor especial que tiene un float cuando el número que debería contener no existe. Lo peligroso de NaN es que se propaga en silencio. Súmalo, promédialo o compáralo y el resultado seguirá siendo NaN o falso, y tú acabarás viendo un nan por el Monitor Serie sin saber en qué punto se estropeó el dato. Se comprueba con isnan() y solo con eso: escribir temperatura == NaN no funciona, porque por definición NaN no es igual a nada, ni siquiera a sí mismo.

El return es la otra idea que vale la pena quedarse. Dentro de loop(), return no termina el programa: termina esta pasada del bucle y devuelve el control a Arduino, que acto seguido vuelve a llamar a loop() desde arriba. Es decir, avisamos del fallo y volvemos a intentarlo dentro de dos segundos. La alternativa sería meter todo el bloque de impresión dentro de un else, que funciona igual pero desplaza el código hacia la derecha; con return el caso excepcional se despacha pronto y el flujo normal se queda en el margen izquierdo, que es más fácil de leer cuando el programa crece.

El bloque final es la impresión, y usa el patrón que ya viste en el módulo 05: varios Serial.print seguidos, que escriben sin saltar de línea, y un Serial.println al final que cierra la línea. Los espacios de " C Humedad: " forman parte de la cadena y son los que separan visualmente los dos valores en la pantalla.

Cuando lo tengas funcionando, prueba a bajar el delay a 100 ms y mira lo que sale. Ver aparecer los nan a propósito es la mejor manera de no olvidar por qué está ahí el chequeo.

Para practicar — cópialo y complétalo

Pega este esqueleto y completa los TODO. Es la mejor forma de aprender: inténtalo antes de mirar la solución.

/*
 * Curso de Arduino — Módulo 06: Sensores comunes
 * Ejercicio 01 — PRÁCTICA (rellena los TODO)
 * Enunciado: Leer temperatura y humedad de un DHT22 y mostrarlas por el Monitor Serie.
 * Dificultad: verde
 * Placa: Arduino UNO    Montaje: DHT22 (VCC->5V, DATA->pin 2, GND->GND)
 * Librería: 'DHT sensor library' (Adafruit) + 'Adafruit Unified Sensor'
 * Correr: Arduino IDE / Wokwi (wokwi/ej01) / arduino-cli (ver README)
 */
#include <DHT.h>            // TODO: necesitamos esta librería; instálala desde el gestor de librerías
 
#define DHTPIN  2           // pin de datos del sensor
#define DHTTYPE DHT22       // modelo del sensor
 
DHT dht(DHTPIN, DHTTYPE);   // objeto sensor
 
void setup() {
    // TODO: abre el serie con Serial.begin(9600)
    // TODO: arranca el sensor con dht.begin()
}
 
void loop() {
    delay(2000);            // espera obligatoria entre lecturas del DHT22
 
    // TODO: lee la humedad     -> float humedad = dht.readHumidity();
    // TODO: lee la temperatura -> float temperatura = dht.readTemperature();
 
    // TODO: si isnan(humedad) || isnan(temperatura) -> imprime "Error leyendo el DHT22" y return
 
    // TODO: imprime por Serial "Temperatura: <valor> C   Humedad: <valor> %"
}

Solución — cópiala y ejecútala

/*
 * Curso de Arduino — Módulo 06: Sensores comunes
 * Ejercicio 01 — MODELO (resuelto)
 * Enunciado: Leer temperatura y humedad de un DHT22 y mostrarlas por el Monitor Serie.
 * Dificultad: verde
 * Placa: Arduino UNO    Montaje: DHT22 (VCC->5V, DATA->pin 2, GND->GND)
 * Librería: 'DHT sensor library' (Adafruit) + 'Adafruit Unified Sensor'
 * Correr: Arduino IDE / Wokwi (wokwi/ej01) / arduino-cli (ver README)
 */
#include <DHT.h>            // la librería que sabe "hablar" el protocolo del DHT
 
#define DHTPIN  2           // pin de datos del sensor
#define DHTTYPE DHT22       // modelo concreto (hay DHT11, DHT22...)
 
DHT dht(DHTPIN, DHTTYPE);   // objeto que representa nuestro sensor
 
void setup() {
    Serial.begin(9600);     // abrimos el canal serie a 9600 baudios
    dht.begin();            // arrancamos el sensor
}
 
void loop() {
    delay(2000);                            // el DHT22 da una lectura nueva como mucho cada 2 s
 
    float humedad     = dht.readHumidity();     // % de humedad relativa
    float temperatura = dht.readTemperature();  // grados Celsius
 
    // readHumidity/readTemperature devuelven NaN si la lectura falla
    if (isnan(humedad) || isnan(temperatura)) {
        Serial.println("Error leyendo el DHT22");
        return;                             // saltamos el resto del loop
    }
 
    Serial.print("Temperatura: ");
    Serial.print(temperatura);
    Serial.print(" C   Humedad: ");
    Serial.print(humedad);
    Serial.println(" %");
}

Cómo ejecutar la simulación

Sin instalar nada, en el navegador

  1. Abre wokwi.com y crea un proyecto nuevo de la placa que pide el ejercicio.
  2. Pega la solución (o tu intento) en la pestaña sketch.ino.
  3. Abre la pestaña diagram.json, borra lo que haya y pega el circuito de aquí abajo.
  4. Dale al play. Verás el circuito funcionando: LEDs, pantallas y monitor serie.
Circuito del ejercicio (diagram.json)
{
  "version": 1,
  "author": "ESIBot",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
    { "type": "wokwi-dht22", "id": "dht", "top": -100, "left": 200, "attrs": {} }
  ],
  "connections": [
    [ "dht:VCC", "uno:5V", "red", [ "v0" ] ],
    [ "dht:GND", "uno:GND.1", "black", [ "v0" ] ],
    [ "dht:SDA", "uno:2", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}

En VS Code, con el repo del curso

El paquete de simulación de este ejercicio está en practica/06-sensores-comunes/wokwi/ej01/. Con la extensión Wokwi instalada y la licencia activada (lo cuenta el onboarding del curso):

make sim EJ=06-sensores-comunes/ej01

y después, en VS Code, Ctrl+Shift+PWokwi: Start Simulator. La extensión no compila: simula un firmware ya compilado, y de compilarlo se encarga ese make.

Cómo usarlo

Con placa: abre el .ino en el Arduino IDE, elige placa y puerto y pulsa Subir. Sin placa: simulalo en Wokwi con cualquiera de las dos vias de arriba. Antes de mirar la solucion, intenta completar tu el esqueleto: es la mejor forma de aprender.

Conexiones