Higrómetro de espejo enfriado DIY con Arduino: Monitorización precisa de temperatura y humedad
Componentes y suministros
- Arduino UNO × 1
- Fuente de alimentación 12 V 10 A × 1
- Ventilador 12 V 40 mm alta potencia × 1
- Módulo Peltier (TEC) 12 V 40 mm × 1
- Disipador 40 mm × 1
- Espejo pequeño × 1
- Adhesivo térmicamente conductor × 1
- Pasta térmica × 1
- Driver motor BTS7960 × 1
- LED 3 mm amarillo × 1
- Sensor de luz OPT101 × 1
- Módulo MOSFET IRF520 × 1
- Termómetro digital DS18B20 (1‑Wire) × 1
- Sensor humedad/temperatura Si7021 (SparkFun breakout) × 1
Herramientas necesarias
- Pistola de pegamento caliente (genérica)
Aplicaciones y servicios en línea
- Arduino IDE
Sobre el proyecto
Descripción
Medir la humedad puede hacerse de muchas formas. El método más popular es usar un sensor de humedad capacitivo. Desafortunadamente, estos sensores pierden precisión rápidamente cuando operan continuamente en ambientes muy húmedos. Un higrómetro de espejo enfriado no sufre este problema y es mucho más preciso, especialmente en rangos altos de humedad. Por desgracia, un higrómetro de espejo enfriado comercial cuesta miles de dólares. La operación básica es bastante simple, así que es posible fabricar uno mismo. No tendrá la misma precisión de 0,1 °C que un dispositivo comercial, pero para la mayoría de propósitos será suficiente y ciertamente más preciso que un sensor capacitivo.
Este proyecto es una prueba de concepto y no está listo para producción. Se pueden hacer muchas mejoras, pero demuestra que funciona.
Cómo funciona
Un higrómetro de espejo enfriado usa un Peltier (TEC) para enfriar una superficie reflectante hasta que aparece condensación. La condensación se detecta con una fuente de luz y un sensor óptico. La temperatura de la superficie del espejo se registra en el momento en que aparece la condensación. Esta temperatura equivale al punto de rocío. La humedad relativa se calcula entonces usando el punto de rocío y la temperatura ambiente.
Simplificaciones
Hay algunas diferencias con un higrómetro de espejo enfriado comercial:
- Un dispositivo comercial no usa un espejo convencional porque no conduce ni distribuye bien el calor, reduciendo precisión y eficiencia. Suelen usar cobre plateado en platino o rodio. Al no ser fácilmente obtenible ni rentable, aquí se usa un espejo normal. Un espejo cuadrado pequeño sería mejor que uno redondo, pero no encontré. Como alternativa, una lámina de acero inoxidable pulido sería incluso mejor.
- Un dispositivo comercial usa un termómetro de resistencia de platino (PRT) incrustado bajo el espejo en lugar de un termómetro SMD montado en la superficie. Un PRT requiere electrónica adicional y montarlo entre el Peltier y el espejo manteniendo buena conductividad térmica es problemático. La desventaja de montar el termómetro en la superficie es que modifica la distribución de calor, reduciendo precisión. Pero un termómetro de superficie es mucho más fácil de construir y es lo suficientemente preciso.
- Un dispositivo comercial usa un espejo mucho más pequeño (~5 mm) en lugar de 4 cm, pues requiere menos potencia y tiene factor de forma menor. Sin embargo, un espejo y Peltier pequeños no están tan disponibles como los grandes. Además, un Peltier pequeño requiere voltaje muy bajo, necesitando un driver personalizado. También es más difícil montar un termómetro SMD en un espejo pequeño dejando espacio para reflejar luz.
- La versión actual no tiene carcasa bloqueadora de luz. Esto puede imprimirse en 3D fácilmente y es muy recomendable para bloquear interferencias de fuentes de luz externas. También puede usarse para sujetar la fuente de luz y el sensor. Si haces una carcasa impresa en 3D, asegúrate de que esté bien ventilada. Puedes usar el ventilador del Peltier para ventilación, pero asegúrate de aspirar aire hacia dentro, no soplar hacia dentro. El interior debe ser fácilmente accesible para limpiar el espejo.
- La implementación actual no puede medir el punto de escarcha, ya que requiere diferenciar entre partículas de hielo y gotas de agua, lo que necesita un segundo sensor óptico para medir luz dispersada.
Cómo construirlo
Toma el Peltier, limpia ambas superficies y coloca adhesivo térmicamente conductor en el lado caliente. Asegúrate de que esté distribuido uniformemente. Si no tienes adhesivo térmico, puedes usar pasta térmica con unas gotas de cianocrilato en los bordes; funciona igual de bien. Limpia la superficie del disipador y presiona disipador y Peltier juntos y deja secar el pegamento.
Después de que el disipador esté unido al Peltier y el pegamento seco, une el espejo del mismo modo, asegurándote de limpiar primero la superficie inferior. Es importante que la pasta térmica esté distribuida uniformemente y no haya burbujas de aire, de lo contrario la distribución de calor en el espejo no será uniforme.
Cuando todo el pegamento haya secado, coloca el ventilador. Asegúrate de usar un ventilador lo bastante potente para enfriar el disipador, que se calienta bastante. Cómo fijar el ventilador al disipador depende del tipo de disipador. Yo solo pegué ambos con pistola de pegamento caliente.

Alimenta el ventilador, luego el Peltier para comprobar si hay al menos dos áreas en el espejo donde la condensación aparece al mismo tiempo. No alimentes el Peltier demasiado tiempo porque eso crearía un perfil de condensación uniforme. Quieres ver cómo se ve cuando la condensación apenas se vuelve visible. Si no estás contento con el resultado, vuelve a intentarlo con nuevo Peltier, espejo y disipador, ya que es improbable que puedas quitar las piezas y restaurar la superficie lisa.


No distribuí la pasta térmica uniformemente, resultando en un perfil de condensación irregular como se ve en la foto superior.
Es importante hacer una foto o marcar el área donde la condensación aparece simultáneamente, porque ahí es donde debes montar el sensor de temperatura de la superficie del espejo y medir la luz reflejada.
En este proyecto uso un Si7021 para medir la temperatura del espejo porque da una salida de bajo ruido. Por desgracia, la dirección I2C está hardcodeada, así que solo puedes usar uno de esos sensores. Para la temperatura ambiente uso un DS18B20, pero no tiene muy alta precisión. La única razón por la que uso esos sensores es porque los tenía a mano.
Para montar el Si7021 (o cualquier sensor de temperatura basado en PCB) en el espejo, primero pon una gota grande de pasta térmica no conductora eléctricamente en el sensor. El PCB también debe cubrirse con pasta térmica para evitar condensación en la electrónica. Luego pon 4 gotas grandes de pegamento caliente en cada esquina del PCB. Tienes que mover rápido. Presiona el sensor contra el espejo en la ubicación donde la condensación apareció uniformemente. Asegúrate de colocar el sensor horizontalmente y presionar firmemente contra el espejo. El pegamento caliente se solidifica rápido al tocar el espejo. Si necesitas reposicionar, puedes raspar fácilmente con una cúter, quitar el pegamento y volver a intentar. Si hay condensación en el PCB, aíslalo con pegamento caliente o plástico en spray.

El ventilador se controla mediante un módulo MOSFET IRF520.
El sensor de luz usado es un OPT101, que es sensible, tiene bajo ruido de salida y es fácil de usar.
Para la fuente de luz puedes usar un diodo láser de baja potencia o un LED normal. Probé ambos y funcionan bien. El láser tiene la ventaja de mejor respuesta pero es más difícil de alinear. El LED tiene una respuesta más plana porque más luz se dispersa, pero es más fácil de alinear. Si usas LED, asegúrate de que emita un haz enfocado.
La salida de luz del LED o láser es probablemente demasiado alta, y usar PWM para reducirla no es opción porque causaría interferencias en el sensor de luz. En su lugar, pon una resistencia en serie con el LED o láser para reducir la salida.
Para montar el LED/láser y el sensor OPT101, usé alambre de cobre trenzado en alambre de bloqueo para dar rigidez. Ambos extremos se aseguraron con pegamento caliente. Esto sirve para prueba de concepto pero es demasiado frágil para usar fuera de un laboratorio (o sótano). Es fácil alinear el sensor y la fuente de luz. Una forma mejor sería imprimir en 3D un soporte para estos dispositivos, también porque una carcasa impresa en 3D es imprescindible para evitar interferencias de luz externa.

Para controlar el Peltier se usa un driver de motor BTS7960. La forma más eficiente de impulsar un Peltier es variar la corriente, no usar PWM. Sin embargo, los controladores de Peltier no están tan disponibles como el BTS7960 y para esta prueba de concepto el consumo no es factor.

Una vez montado, sube el código al Arduino y ajusta el rango de sensibilidad del OPT101 con un potenciómetro. Una resistencia mayor significa mayor voltaje de salida para la misma cantidad de luz. Consulta el datasheet OPT101, Figura 3 – Responsividad voltaje vs irradiancia. Para depuración, puedes soplar sobre el espejo para crear condensación, o poner un objeto frente al sensor. Si tienes aire acondicionado, enciéndelo (o apágalo) y espera. Verás el cambio de humedad.
En el gráfico abajo puedes ver la temperatura (azul), lectura óptica (rojo) y punto de rocío medido (verde). Se ve el punto de rocío subiendo al apagar el aire acondicionado.

Seguridad
Aunque el código suministrado no lo soporta, el hardware puede calentar el espejo además de enfriarlo. Esto se hace simplemente invirtiendo la polaridad en el Peltier. El calentamiento del espejo puede usarse para eliminar condensación rápidamente y mejorar el tiempo de respuesta. Además, la evaporación instantánea de la condensación elimina pequeños contaminantes. Sin embargo, esto también supone un riesgo potencial de seguridad porque la superficie del espejo no tiene disipador. Si el código se queda calentando el Peltier, en el mejor caso fundirá el pegamento caliente que sujeta el termómetro y en el peor caso iniciará un incendio por fundir cables causando cortocircuito.
Precisión
Como la temperatura del punto de rocío medida es un valor absoluto, la calibración no es tan importante como en un higrómetro capacitivo o resistivo. Sin embargo, habrá al menos alguna diferencia de temperatura entre el área del sensor de temperatura de la superficie del espejo y el área de detección de luz. Si necesitas verificar la precisión, puedes calibrar el dispositivo con un higrómetro de espejo enfriado comercial calibrado.
Respecto a la contaminación del espejo, esto es solo parcialmente un problema. La lectura de luz reflejada no es absoluta sino relativa al inicio de un ciclo de enfriamiento. Al iniciar un ciclo, el espejo está libre de condensación. La cantidad de luz reflejada se mide y se usa como referencia para detectar condensación. Si el espejo está contaminado y refleja menos luz, no debería afectar la detección. Sin embargo, algunos contaminantes bajan o suben la temperatura a la que ocurre la condensación, así que para mejor precisión, limpia la superficie del espejo de vez en cuando.
Los sensores de temperatura del espejo y ambiente no necesitan alta precisión calibrada, pero la resolución debe ser alta. Por ejemplo, si la temperatura real es 24,0 °C pero mide 24,5 °C, está bien mientras ambos termómetros midan 24,5 °C (puede normalizarse) y el número solo fluctúe con un decimal. Muchos termómetros tienen fluctuación de 0,2‑0,3 °C. Sería mejor usar un sensor TSYS01 para ambas mediciones, ya que estos sensores dan la misma precisión que un PRT de 0,1 °C.
Es importante que el sensor de temperatura haga buen contacto con la superficie del espejo. El uso de pasta térmica no conductora eléctricamente es imperativo.
No enfríes el espejo más rápido que el tiempo de respuesta del termómetro, si no el punto de rocío detectado será inexacto.
El sensor de temperatura debe colocarse en una zona del espejo donde la condensación del área de detección de luz aparezca al mismo tiempo.
Montar un sensor de temperatura en la superficie del espejo modifica la distribución de calor, reduciendo la precisión. Podría ser tentador usar un termómetro infrarrojo como alternativa, pero por desgracia el espejo refleja algo de radiación térmica, por lo que la medición se vería influida por el entorno.

Técnicamente, una lectura de humedad también depende de la presión barométrica, pero el efecto es muy pequeño en ambientes normales. Cualquier cambio de presión por portazos o viento exterior causando presión diferencial en un edificio probablemente cause más problemas de los que vale.
El aire caliente del disipador del Peltier no debe ser aspirado sobre el espejo.
Una bajada lenta de temperatura dará lecturas más precisas, pero también reduce el tiempo de respuesta. El tiempo de respuesta puede mejorarse oscilando la temperatura cerca del punto de rocío.
Código
#include <math.h>
#include <avr/wdt.h> // Detección de bloqueo por Watchdog
// Librerías propias
#include "Si7021.h" // sensor humedad con heater
#include <OneWire.h> // DS18B20 temp sensor
#include <DallasTemperature.h> // DS18B20 temp sensor
// Librería Timer: https://github.com/brunocalou/Timer
#include "timer.h"
#include "timerManager.h"
// Pines hardware en Arduino
#define coolingPWM 6
#define heatingPWM 5
#define coolingEnable 13
#define heatingEnable 12
#define tecFan 7
#define opticalSensor 0 // Entrada analógica
#define oneWireBus A3 // DS18B20 temp sensor
// Estados del TEC
#define COOLING 0
#define HEATING 1
#define OFF 2
// Temporizadores
Timer timerMainLoop;
Timer timerTecCooling;
Timer timerSampleNoise;
// Sensor temperatura (humedad no usada)
Si7021 si7021;
// DS18B20 temp sensor
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
float humidity = 0;
float ambientTemp = 0;
float opticalDewpoint = 0;
// Valores iniciales más altos para rango correcto en Serial Plotter
float mirrorTemp = 30;
float optical = 30;
float dewPoint = 15; // valor inicial menor que temp espejo
float relativeHumidity = 30;
int tecState = OFF;
bool cooling = false;
int intervalTecCooling = 200; // ms
float opticalThreshold = 0.5f; // caída óptica para detectar condensación (debe ser > ruido)
int pwmIncrement = 1;
int startPwm = 100;
int maxPwm = 255;
int intervalMainLoop = 200;
int tecPwm = 0;
int noiseSampleIndex = 0;
int noiseSampleAmount = 10;
float noiseSampleHighest = 0;
float noiseSampleLowest = 10000;
bool noiseSampling = false;
float calculateHumidity(float TD, float T) {
// El punto de rocío no puede ser mayor que la temperatura
if (TD > T) TD = T;
// Aproximación August-Roche-Magnus
float rh = 100 * (exp((17.625 * TD) / (243.04 + TD)) / exp((17.625 * T) / (243.04 + T)));
return rh;
}
// Configura TEC a calefacción, enfriamiento o apagado
void SetTEC(int state, int amount) {
tecState = state;
// Nota: tanto para calefacción como enfriamiento, los pines heating Y cooling deben ponerse HIGH. Pregunta al diseñador PCB por qué.
// Driver: BTS7960 motor driver board. PWM para TEC no es eficiente, mejor fuente de corriente variable.
switch (state) {
case COOLING:
digitalWrite(heatingEnable, HIGH);
analogWrite(heatingPWM, 0);
digitalWrite(coolingEnable, HIGH);
analogWrite(coolingPWM, amount);
break;
case HEATING:
digitalWrite(coolingEnable, HIGH);
analogWrite(coolingPWM, 0);
digitalWrite(heatingEnable, HIGH);
analogWrite(heatingPWM, amount);
break;
case OFF:
digitalWrite(coolingEnable, LOW);
analogWrite(coolingPWM, 0);
digitalWrite(heatingEnable, LOW);
analogWrite(heatingPWM, 0);
break;
default:
digitalWrite(coolingEnable, LOW);
analogWrite(coolingPWM, 0);
digitalWrite(heatingEnable, LOW);
analogWrite(heatingPWM, 0);
}
}
void setup() {
// Watchdog para seguridad: no quieres TEC atascado en calefacción
wdt_enable(WDTO_2S);
Serial.begin(9600);
pinMode(coolingPWM, OUTPUT);
pinMode(heatingPWM, OUTPUT);
pinMode(coolingEnable, OUTPUT);
pinMode(heatingEnable, OUTPUT);
pinMode(tecFan, OUTPUT);
pinMode(opticalSensor, INPUT);
// Timers
timerMainLoop.setInterval(intervalMainLoop);
timerMainLoop.setCallback(mainLoop);
timerMainLoop.start();
timerTecCooling.setInterval(intervalTecCooling);
timerTecCooling.setCallback(tecCoolingCallback);
timerSampleNoise.setInterval(intervalTecCooling);
timerSampleNoise.setCallback(sampleNoiseCallback);
// Si7021
uint64_t serialNumber = 0ULL;
si7021.begin();
serialNumber = si7021.getSerialNumber();
// DS18B20
sensors.begin();
// Desactivar logs debug para que Serial Plotter funcione bien
/*
Serial.print("Si7021 serial number: ");
Serial.print((uint32_t)(serialNumber >> 32), HEX);
Serial.println((uint32_t)(serialNumber), HEX);
Serial.print("Si7021 firmware version: ");
Serial.println(si7021.getFirmwareVersion(), HEX);
*/
startNoiseSampling();
}
// Lectura sensor óptico
float getOptical() {
int opt = analogRead(opticalSensor);
float optFactored = (float)opt / 30.0f;
return optFactored;
}
// Callback timer enfriamiento TEC
void tecCoolingCallback() {
digitalWrite(tecFan, HIGH);
// Aumentar potencia TEC lentamente
tecPwm += pwmIncrement;
if (tecPwm > maxPwm) tecPwm = maxPwm;
SetTEC(COOLING, tecPwm);
// ¿Condensación detectada?
if (optical <= (noiseSampleLowest - opticalThreshold)) {
dewPoint = mirrorTemp;
opticalDewpoint = optical;
stopTec();
}
}
void startNoiseSampling() {
noiseSampling = true;
noiseSampleHighest = 0;
noiseSampleLowest = 10000;
timerSampleNoise.start();
}
void sampleNoiseReset() {
timerSampleNoise.stop();
noiseSampleIndex = 0;
noiseSampling = false;
}
void sampleNoiseCallback() {
if (noiseSampleIndex > noiseSampleAmount) {
sampleNoiseReset();
startTecCooling();
} else {
if (optical > noiseSampleHighest) noiseSampleHighest = optical;
if (optical < noiseSampleLowest) noiseSampleLowest = optical;
}
noiseSampleIndex++;
}
void startTecCooling() {
cooling = true;
digitalWrite(tecFan, HIGH);
tecPwm = startPwm;
timerTecCooling.start();
}
void stopTec() {
cooling = false;
digitalWrite(tecFan, LOW);
timerTecCooling.stop();
SetTEC(OFF, 0);
}
// Timer no bloqueante
void mainLoop() {
// DS18B20 temperatura ambiente
sensors.setResolution(10); // antes de cada medición. Mayor resolución = más lento
sensors.requestTemperatures();
ambientTemp = sensors.getTempCByIndex(0);
// Si7021 temperatura espejo
mirrorTemp = si7021.measureTemperature();
// Lectura óptica
optical = getOptical();
relativeHumidity = calculateHumidity(dewPoint, ambientTemp);
/* Formato legible
Serial.print("dewPoint: "); Serial.println(dewPoint, 2);
Serial.print("mirrorTemp: "); Serial.println(mirrorTemp, 2);
Serial.print("ambientTemp: "); Serial.println(ambientTemp, 2);
Serial.print("relativeHumidity: "); Serial.println(relativeHumidity, 2);
*/
// Para Serial Plotter
Serial.print(mirrorTemp, 2); Serial.print(" ");
Serial.print(optical, 2); Serial.print(" ");
Serial.println(dewPoint, 2);
// Serial.print(" "); Serial.println(relativeHumidity, 2);
// Esperar a que desaparezca condensación
if (!cooling && !noiseSampling && (optical >= noiseSampleLowest)) {
startNoiseSampling();
}
}
void loop() {
wdt_reset(); // Watchdog
TimerManager::instance().update();
}
Esquemáticos

Proceso de manufactura
- La Ciencia y el Arte de los Espejos Modernos
- Construye un Spybot controlado por Bluetooth con Arduino
- FlickMote: Mando IR por gestos para Smart Home
- TV‑B‑Gone DIY con Arduino: Mando universal para apagar cualquier TV
- Espejo infinito caleidoscopio DIY: Construye una impresionante pantalla de luces LED
- Construye un Reloj Maestro LED Personalizado con Alarma – Visible desde 12 Metros
- Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
- Soluciones de Alimentación Optimizadas para Proyectos Arduino
- Tres en raya con Arduino, matriz LED MAX7219 y carcasa de cartón
- Construye un Robot Cuadrúpedo Inteligente con Arduino: Guía Paso a Paso
- Construye un volante joystick personalizado con Arduino para gaming