Muestra la temperatura y humedad relativa de la habitación en pantalla OLED usando el sensor DHT22. Un proyecto fácil, corto y de pocos componentes.





Materiales necesarios
Sensor de temperatura y humedad DHT22
El DHT22 o también conocido como AM2302 es un sensor digital de temperatura y humedad relativa de buen rendimiento y bajo costo. Integra un sensor capacitivo de humedad y un termistor para medir el aire circundante, y muestra los datos mediante una señal digital en el pin de datos (no posee salida analógica).

En cuanto al hardware, solo es necesario conectar el pin VCC de alimentación a 3-5.5V, el pin GND a Tierra (0V) y el pin de datos a un pin digital (D2) en nuestro Arduino. El fabricante recomienda conectar una resistencia de 1k-10k en pull-up como se muestra en la imagen.

El pin número 3 no ha de utilizarse y en el datasheet consta como GND.

Quizá la única desventaja del sensor es que sólo se puede obtener nuevos datos cada 2 segundos, 0.5Hz. Cada sensor es calibrado en fabrica para obtener unos coeficientes de calibración grabados en su memoria OTP, asegurando alta estabilidad y fiabilidad a lo largo del tiempo. El protocolo de comunicación entre el sensor y el microcontrolador emplea un único hilo o cable que conectaremos al pin D2 del Arduino.

El DHT22 presenta mejores prestaciones respecto al sensor DHT11, como mejor resolución, en nuestro caso de 0.1 grados Celsius, mayor precisión y un empaque más robusto.
Pantalla OLED
Un OLED (Organic light-emitting diode) es un tipo de LED en el que la capa emisiva está formada por un compuesto orgánico que emite luz en respuesta a la electricidad.
Se comercializan unas pequeñas pantallas OLED de 0.96” listas para conectar a Arduino. Estas pantallas incorporan el controlador SDD1306 y tienen un tamaño muy reducido de 25mm x 14mm. Tienen una resolución de 128×64 pixels y son monocromáticas, aunque en nuestro caso usaremos unas que están fabricadas a dos colores (amarillo y azul).
Las pantallas OLED tienen la ventaja de tener un consumo muy bajo, en torno a 20mA, dado que solo se enciende el pixel necesario y no requieren de backlight. Esto es especialmente interesante en aplicaciones que funcionan con baterías.

La comunicación puede realizarse, según modelos, por bus SPI o por bus I2C por lo que es sencillo obtener los datos medidos.
En nuestro proyecto usaremos una pantalla I2C usando los pines SCL (A5) y SDA (A4) conectada a una alimentación directa de 5V aun que podría operar a 3.3V.
En la siguiente imagen vemos cómo se mostrará en pantalla los datos, siendo la barra amarilla superior la representación de la humedad en % y los números azules la temperatura ambiental expresada con un solo decimal.
Además, cuando se alcance una máxima o una mínima, se mostrará de forma destacable invirtiendo los colores de la pantalla.

Para la programación usaremos la librería de control de la pantalla SSD1306 en su versión I2C que precisa de la dirección del módulo que suele ser 0x3C, aunque puede variar según el modelo (resistencia en su parte posterior).
La pantalla cuenta con unos orificios para su sujeción que no son del todo cómodos, y para nuestro proyectos hemos fabricado una pieza especial que nos facilitará su colocación, como se muestra en la siguiente imagen.





|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
#include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Fonts/FreeSansBold12pt7b.h> #include <SimpleDHT.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // On an arduino UNO: A4(SDA), A5(SCL) // On an arduino MEGA 2560: 20(SDA), 21(SCL) // On an arduino LEONARDO: 2(SDA), 3(SCL), ... #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3C for 128x64, 0x3D for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define pinDHT22 2 SimpleDHT22 dht22(pinDHT22); float valor = 0; float humedad = 0; float tempMin = 22; // valor inicial muy alto float tempMax = 13; // valor inicial muy bajo int err = SimpleDHTErrSuccess; void setup() { Serial.begin(9600); Serial.println("Saludos, termometro 2/1/2026"); // Wait for display delay(500); if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;) ; // Don't proceed, loop forever } display.clearDisplay(); display.setFont(&FreeSansBold12pt7b); display.setTextSize(1); // Normal 1:5 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(35, 15); display.print("2026"); display.setCursor(8, 50); display.print("GENIERO"); display.display(); display.setTextSize(2); delay(1500); } void loop() { if ((err = dht22.read2(&valor, &humedad, NULL)) != SimpleDHTErrSuccess) { Serial.print("No se encuentra Termometro, err="); Serial.println(err); delay(2000); return; } // Actualizar temperatura mínima if (valor < tempMin) { tempMin = valor; } // Actualizar temperatura máxima if (valor > tempMax) { tempMax = valor; } display.clearDisplay(); int barraY = 6; int barraAltura = 8; // Marco display.drawRect(0, barraY, 128, barraAltura, SSD1306_WHITE); // Ancho proporcional a la humedad int anchoBarra = (int)(humedad * 128.0 / 100.0); // Relleno display.fillRect(1, barraY + 1, anchoBarra - 2, barraAltura - 2, SSD1306_WHITE); //linea central if (humedad <= 50) { display.drawLine(62, barraY, 62, barraY + barraAltura - 1, SSD1306_WHITE); } else { display.drawLine(62, barraY, 62, barraY + barraAltura - 1, SSD1306_BLACK); } // Convertimos a texto con 1 decimal char buffer[10]; dtostrf(valor, 0, 1, buffer); // 1 decimal if (valor != tempMax && valor != tempMin) { printSpaced(buffer, 3, 59, 40); } else { printmax(buffer, 3, 59, 40); } display.display(); // DHT22 sampling rate is 0.5HZ. delay(2000); } void printSpaced(String txt, int x, int y, int spacing) { // imprimimos el entero display.setTextColor(SSD1306_WHITE); // texto invertido for (int i = 0; i < 2; i++) { display.setCursor(x + i * spacing, y); display.print(txt[i]); } //Aquí se imprimen el punto y los decimales display.setCursor(77, y); display.print(txt[2]); display.setCursor(97, y); display.print(txt[3]); } void printmax(String txt, int x, int y, int spacing) { // imprimimos el entero display.fillRect(0, 22, 128, 64, SSD1306_WHITE); display.setTextColor(SSD1306_BLACK); // texto invertido for (int i = 0; i < 2; i++) { display.setCursor(x + i * spacing, y); display.print(txt[i]); } //Aquí se imprimen el punto y los decimales display.setCursor(77, y); display.print(txt[2]); display.setCursor(97, y); display.print(txt[3]); } |
Como vamos a usar un step-down, podremos obtener 5Voltios estables desde cualquier entrada no superior de 28Voltios. Así pues, alimentaremos el sistema directo a la fuente, es decir, en este caso no es necesario alimentar arduino por el pin VIN, pues la corriente que obtendrá ya vendrá regulada y estable, y tomará la corriente por el pin 5V, evitaremos así exceso de calor en el interior del sistema que puede perjudicar la toma de muestras del sensor.
Feliz día de Reyes, espero que hayáis sido buenos.
