Saltar al contenido
Nivel intermedio

Ver temperatura y humedad en un display LCD

Conectar el display LCD

Vamos a sumar un display LCD de 16 columnas por 2 filas para ver en pantalla lo que mide el sensor. Acá aparece la primera diferencia real entre las dos plataformas de este proyecto, y vale la pena entenderla, porque es muy didáctica: el display se conecta de una manera distinta en cada una.

Fotografía de un LCD Keypad Shield: una placa verde con una pantalla LCD azul de dos filas en la parte superior, una fila de botones (SELECT, LEFT, UP, DOWN, RIGHT y RST) abajo a la izquierda, y un pequeño potenciómetro azul en la esquina superior izquierda.
El LCD Keypad Shield del original (figura original del proyecto): tiene el formato del Arduino UNO para apilarse sobre él. Arriba a la izquierda, el potenciómetro (RP1) que ajusta el contraste.

En el Arduino UNO usamos el LCD Keypad Shield del original, un shield que tiene el formato de la placa y se apila directamente encima del UNO, encastrando en sus pines: no hay que cablear nada en la protoboard. Al apilarlo, el display queda conectado en modo paralelo, usando seis pines de datos de la placa (los pines 8, 9, 4, 5, 6 y 7). Es importante no forzar las piezas: todos los pines deben coincidir perfectamente. Como el shield ocupa varios pines, el LED y el sensor DHT11 se cablean a los pines que quedan libres, tal como veníamos.

El LCD Keypad Shield tiene el formato del Arduino UNO y no se enchufa en un ESP32. Por eso, en el ESP32 usamos un LCD 1602 con módulo I2C: la misma pantalla de 16x2, pero con una plaquita (el módulo I2C) pegada atrás que reduce el cableado a solo dos cables de señal. En lugar de los seis pines del modo paralelo, conectamos: VCC a 3,3 V, GND a GND, SDA al GPIO 21 y SCL al GPIO 22 (los pines I2C por defecto del ESP32). Esta es una adaptación de plataforma pensada a propósito: hace lo mismo que el shield con muchísimo menos cableado.

Instalar la librería y probar el display con un saludo

Para manejar el display necesitamos su librería, y cada plataforma usa una distinta, en correspondencia con la forma en que conectamos la pantalla en el paso anterior.

En el Arduino UNO, el shield en modo paralelo se maneja con la librería LiquidCrystal, que ya viene incluida con el Arduino IDE (no hay que instalar nada). En el código, el display se declara indicándole los seis pines que usa: LiquidCrystal lcd(8, 9, 4, 5, 6, 7).

En el ESP32, el LCD por I2C se maneja con la librería LiquidCrystal_I2C, que se instala desde el Gestor de bibliotecas del IDE (buscá “LiquidCrystal_I2C”). En el código, el display se declara con su dirección I2C —típicamente 0x27— y su tamaño: LiquidCrystal_I2C lcd(0x27, 16, 2). Si al probar la pantalla no muestra nada, es posible que tu módulo use la dirección 0x3F: probá con ese valor.

Para familiarizarnos con el display, un primer programa de prueba puede escribir un saludo: tras inicializar la pantalla, con lcd.print("Buen dia") aparece ese texto en la primera fila. Un detalle a tener siempre presente: el LCD no representa bien las tildes ni la letra Ñ, así que los textos se escriben sin ellas (por eso “Buen dia”, y más adelante “Temp.” y “Hum.”).

Si en el UNO el saludo no se lee (pantalla en blanco o todo encendido), ajustá el contraste con el potenciómetro azul (RP1) que está en la esquina superior izquierda del shield, usando un destornillador chico.

Mostrar la temperatura y la humedad en el display

Ahora volvemos al sistema completo: el sensor DHT11 y el LED de aviso siguen conectados como en el nivel inicial, y le sumamos el display. Aprovechamos que el LCD tiene dos filas para escribir la temperatura en la primera y la humedad en la segunda, cada una precedida por un rótulo (Temp.: y Hum.:) para que se lean con claridad.

Esquema de conexión del sistema completo en Arduino UNO: el LCD Keypad Shield a la izquierda, y una protoboard a la derecha con el LED verde, su resistencia y el módulo DHT11 azul, cableados a la placa.
El sistema completo del nivel intermedio en la variante Arduino UNO (figura original del proyecto): el LCD Keypad Shield junto al LED y el sensor DHT11 montados en la protoboard. En el ESP32, el display se reemplaza por el LCD 1602 por I2C.

El programa toma lo del nivel inicial y le agrega el display: en cada vuelta lee una sola vez la temperatura y la humedad del DHT11, con esos valores decide el aviso (el LED parpadea si la temperatura supera UMBRAL_TEMP_C, igual que antes) y los escribe en el LCD. Sigue midiendo cada INTERVALO_MEDICION_MS (2 segundos), respetando el límite del sensor.

Ver el código completo · temp-humedad-lcd.ino
temp-humedad-lcd.ino Arduino UNO
// Invernadero con display: el sensor DHT11 mide temperatura y humedad del
// aire, un LCD 16x2 las muestra en pantalla, y el LED de ventilación
// PARPADEA cuando la temperatura supera el umbral (igual que en el nivel
// inicial). Ahora, además del aviso, vemos los números exactos.
//
// Plataforma: Arduino UNO.
// Conexión (la del esquema original): dato del DHT11 → pin 2; LED → pin 13;
// display LCD Keypad Shield en modo paralelo por los pines 8, 9, 4, 5, 6, 7.
// El shield se apila directamente sobre el UNO; su potenciómetro RP1 ajusta
// el contraste si no se lee el texto.
//
// Nota del original: en el LCD no usar tildes ni la letra Ñ (el display no
// las representa bien). Por eso los rótulos van como "Temp." y "Hum.".
//
// Basado en: Fragmento de código del Nivel Intermedio (Paso 5) — Invernadero
// Inteligente, Saberes Digitales (INET/EDUCAR 2019)
// Modernización: (1) constantes nombradas en vez del C de mBlock3. (2)
// Librería DHT de Adafruit (ver nivel inicial), con dht.begin(). (3) El
// original llamaba a readTemperature() y readHumidity() varias veces por
// vuelta; acá se leen UNA vez a variables y esos mismos valores se usan
// para el LED y para el display.

#include "DHT.h"
#include <LiquidCrystal.h>

// Pin de datos del sensor y tipo de sensor (DHT11).
const int PIN_DHT = 2;
#define DHTTYPE DHT11

// LED indicador de "hay que ventilar".
const int PIN_LED_VENTILACION = 13;

// Umbral del original: por encima de 25 °C hay que ventilar.
const float UMBRAL_TEMP_C = 25.0;

// Tiempos del parpadeo del aviso, como en el original.
const unsigned long PARPADEO_ENCENDIDO_MS = 500;
const unsigned long PARPADEO_APAGADO_MS   = 500;

// El DHT11 no admite más de una lectura por segundo; medimos cada 2 s.
const unsigned long INTERVALO_MEDICION_MS = 2000;

// Objeto del sensor: pin de datos + tipo.
DHT dht(PIN_DHT, DHTTYPE);

// Display LCD en modo paralelo. El orden de pines es el del LCD Keypad
// Shield: (RS, E, D4, D5, D6, D7) = (8, 9, 4, 5, 6, 7).
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup() {
  pinMode(PIN_LED_VENTILACION, OUTPUT);
  dht.begin();
  // Inicializamos el display de 16 columnas por 2 filas y lo limpiamos.
  lcd.begin(16, 2);
  lcd.clear();
}

void loop() {
  // Leemos una sola vez y reutilizamos los valores. readTemperature() da
  // grados Celsius; readHumidity() da humedad relativa en %.
  float temperatura = dht.readTemperature();
  float humedad     = dht.readHumidity();

  if (temperatura > UMBRAL_TEMP_C) {
    // Demasiado calor: un parpadeo del LED para avisar que hay que ventilar.
    digitalWrite(PIN_LED_VENTILACION, HIGH);
    delay(PARPADEO_ENCENDIDO_MS);
    digitalWrite(PIN_LED_VENTILACION, LOW);
    delay(PARPADEO_APAGADO_MS);
  }

  // Fila 0: temperatura. Fila 1: humedad. Sin tildes ni Ñ (limitación LCD).
  lcd.setCursor(0, 0);
  lcd.print("Temp.: ");
  lcd.print(temperatura);
  lcd.setCursor(0, 1);
  lcd.print("Hum.: ");
  lcd.print(humedad);

  delay(INTERVALO_MEDICION_MS);
}
temp-humedad-lcd.ino ESP32
// Invernadero con display: el sensor DHT11 mide temperatura y humedad del
// aire, un LCD 16x2 las muestra en pantalla, y el LED de ventilación
// PARPADEA cuando la temperatura supera el umbral (igual que en el inicial).
//
// Plataforma: ESP32 (DevKit v1).
// Conexión: dato del DHT11 → GPIO 4; LED externo → GPIO 16; display LCD 1602
// por I2C: SDA → GPIO 21, SCL → GPIO 22 (los pines I2C por defecto del ESP32).
//
// ADAPTACIÓN DE PLATAFORMA (¡importante!, ver README): el original usa un
// LCD Keypad Shield, una placa con formato Arduino UNO que se apila sobre la
// placa y se maneja con LiquidCrystal en modo PARALELO (6 pines de datos:
// 8, 9, 4, 5, 6, 7). Ese shield NO se enchufa en un ESP32. Por eso en ESP32
// usamos un LCD 1602 con módulo I2C: solo DOS cables de señal (SDA y SCL) en
// lugar de seis, y la librería LiquidCrystal_I2C en lugar de LiquidCrystal.
// Es el estándar moderno y evita el problema del shield. La dirección I2C
// típica de estos módulos es 0x27 (algunos son 0x3F: si la pantalla no
// muestra nada, probá 0x3F o escaneá el bus I2C).
// Nota eléctrica: el ESP32 trabaja a 3,3 V; DHT11 y el módulo I2C del LCD
// funcionan a 3,3 V.
//
// Nota del original: en el LCD no usar tildes ni la letra Ñ.
//
// Librerías requeridas (Library Manager): "DHT sensor library" (Adafruit) +
// su dependencia "Adafruit Unified Sensor", y "LiquidCrystal_I2C".
//
// Basado en: Fragmento de código del Nivel Intermedio (Paso 5) — Invernadero
// Inteligente, Saberes Digitales (INET/EDUCAR 2019)
// Modernización: constantes nombradas; DHT de Adafruit con dht.begin(); LCD
// paralelo del original adaptado a I2C para ESP32; una sola lectura por
// vuelta reutilizada para LED y display.

#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Pin de datos del sensor y tipo de sensor (DHT11).
const int PIN_DHT = 4;
#define DHTTYPE DHT11

// LED externo indicador de "hay que ventilar".
const int PIN_LED_VENTILACION = 16;

// Dirección I2C y tamaño del display (16 columnas x 2 filas).
const uint8_t LCD_DIRECCION_I2C = 0x27;
const uint8_t LCD_COLUMNAS      = 16;
const uint8_t LCD_FILAS         = 2;

// Umbral del original: por encima de 25 °C hay que ventilar.
const float UMBRAL_TEMP_C = 25.0;

// Tiempos del parpadeo del aviso, como en el original.
const unsigned long PARPADEO_ENCENDIDO_MS = 500;
const unsigned long PARPADEO_APAGADO_MS   = 500;

// El DHT11 no admite más de una lectura por segundo; medimos cada 2 s.
const unsigned long INTERVALO_MEDICION_MS = 2000;

// Objeto del sensor y display por I2C.
DHT dht(PIN_DHT, DHTTYPE);
LiquidCrystal_I2C lcd(LCD_DIRECCION_I2C, LCD_COLUMNAS, LCD_FILAS);

void setup() {
  pinMode(PIN_LED_VENTILACION, OUTPUT);
  dht.begin();
  // Con I2C, primero arranca el bus y el display; backlight enciende la luz.
  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  // Leemos una sola vez y reutilizamos los valores.
  float temperatura = dht.readTemperature(); // grados Celsius
  float humedad     = dht.readHumidity();    // humedad relativa en %

  if (temperatura > UMBRAL_TEMP_C) {
    // Demasiado calor: un parpadeo del LED para avisar que hay que ventilar.
    digitalWrite(PIN_LED_VENTILACION, HIGH);
    delay(PARPADEO_ENCENDIDO_MS);
    digitalWrite(PIN_LED_VENTILACION, LOW);
    delay(PARPADEO_APAGADO_MS);
  }

  // Fila 0: temperatura. Fila 1: humedad. Sin tildes ni Ñ (limitación LCD).
  lcd.setCursor(0, 0);
  lcd.print("Temp.: ");
  lcd.print(temperatura);
  lcd.setCursor(0, 1);
  lcd.print("Hum.: ");
  lcd.print(humedad);

  delay(INTERVALO_MEDICION_MS);
}
Temperatura y humedad en el display: el DHT11 mide, el LCD muestra Temp. en la fila 0 y Hum. en la fila 1, y el LED parpadea si la temperatura supera UMBRAL_TEMP_C. La única diferencia entre plataformas es cómo se maneja el display (LiquidCrystal en el UNO, LiquidCrystal_I2C en el ESP32).

Fijate, al comparar las dos plataformas con el selector, que el corazón del programa es idéntico: cambia solo la parte del display (qué librería se incluye y cómo se declara e inicializa la pantalla). Todo lo demás —leer el sensor, decidir el aviso, los rótulos— es el mismo código.

Podés ver el sistema completo —el sensor midiendo, el display actualizándose y el LED avisando— en el simulador:

Simulación del comportamiento

La misma máquina de estados del firmware, portada a TypeScript, maneja el comportamiento del dispositivo. No se ejecuta el binario real: la ejecución del .hex con avr8js está en el roadmap.

Simulación lista. Presioná «Iniciar» para arrancar la secuencia.

Cierre del nivel

Al terminar este nivel, el invernadero no solo avisa que hace calor: muestra en pantalla los valores exactos de temperatura y humedad del aire. En el camino apareció una diferencia real y muy formativa entre las plataformas —el shield paralelo del UNO frente al LCD por I2C del ESP32— y viste que la lógica del proyecto no cambia, solo la manera de conectar la pantalla. En el nivel avanzado vamos a poder mirar todo esto a distancia: publicaremos la temperatura y la humedad por Internet de las Cosas para monitorear el invernadero desde el celular.

Evidencia de cierre

Al terminar este nivel, esto tiene que estar funcionando:

  • El display LCD está conectado: en el UNO, el LCD Keypad Shield apilado sobre la placa (modo paralelo, 6 pines); en el ESP32, un LCD 1602 por I2C, con solo dos cables de señal (SDA y SCL).
  • Instalaste la librería correcta según tu plataforma (LiquidCrystal, que ya viene con el IDE, en el UNO; LiquidCrystal_I2C en el ESP32) y probaste el display con un saludo, sin tildes ni Ñ.
  • El display muestra la temperatura en la primera fila y la humedad en la segunda, y el LED sigue avisando (parpadea) cuando la temperatura supera UMBRAL_TEMP_C (25 °C).