DIY Taupunkthygrometer (Chilled Mirror) mit Arduino – Präzise Feuchtemessung
Komponenten
| Bauteil | Anzahl | Hinweise |
|---|---|---|
| Arduino UNO | 1 | |
| Netzteil 12 V / 10 A | 1 | Für Peltier & Lüfter |
| 12 V Lüfter 40 mm (High Power) | 1 | Kühlt Kühlkörper |
| Peltier-Element (TEC) 12 V, 40×40 mm | 1 | z. B. TEC1-12706 |
| Kühlkörper 40 mm (Alu, Rippen) | 1 | Auf Peltier-Heißseite |
| Kleiner Spiegel (ca. 4 cm Ø) | 1 | Glas/Metall, reflektierend |
| Wärmeleitkleber / Wärmeleitpaste + Sekundenkleber | 1 | Spiegel ↔ Peltier-Kaltseite |
| BTS7960 Motortreiber (H-Brücke, 43 A) | 1 | Steuert Peltier-Strom (PWM) |
| 3 mm gelbe LED (Lichtquelle) | 1 | Oder Laserdiode |
| OPT101 Lichtsensor (integrierter Photodiode+OpAmp) | 1 | Empfindlich, rauscharm |
| IRF520 MOSFET-Modul | 1 | Steuert Lüfter |
| DS18B20 1-Wire Temperatursensor | 1 | Umgebungstemperatur |
| Si7021 I²C Temp/Feuchte-Sensor | 1 | Spiegeltemperatur (auf Spiegel geklebt) |
Werkzeuge
- Heißklebepistole
Software & Bibliotheken
- Arduino IDE
Si7021Bibliothek (custom)OneWire+DallasTemperature(für DS18B20)TimerBibliothek (brunocalou/Timer)avr/wdt.h(Watchdog für Sicherheit)
Funktionsprinzip: Chilled Mirror Hygrometer
Ein Peltier-Element kühlt einen Spiegel, bis Tau (Kondensat) darauf kondensiert. Eine LED beleuchtet den Spiegel, ein optischer Sensor (OPT101) misst das reflektierte Licht. Bei Taupunkt-Bildung streut das Licht → reflektiertes Signal bricht ein. Die Spiegeltemperatur in diesem Moment = Taupunkttemperatur. Daraus lässt sich mit der Umgebungstemperatur die relative Luftfeuchte berechnen (August-Roche-Magnus-Formel).
Vorteile vs. kapazitive Sensoren: Kein Drift bei Dauerfeuchte, höhere Genauigkeit im hohen Feuchtebereich, absoluter Messwert (kalibrierfrei).
Nachteile: Höherer Aufwand, Strombedarf, langsame Reaktion, Empfindlichkeit gegen Verschmutzung.
Vereinfachungen gegenüber Profi-Geräten
- Kein Platin/Rhodium-Spiegel, sondern normaler Glasspiegel (schlechtere Wärmeleitung).
- SMD-Sensor (Si7021) auf Spiegel geklebt statt eingebettetem Pt100 (verändert Wärmeverteilung).
- Größerer Spiegel (4 cm) & Peltier → mehr Leistung, einfacher verfügbar.
- Kein Lichtschutzgehäuse (Streulicht stört) – 3D-Druck empfohlen.
- Keine Frostpunkterkennung (bräuchte 2. optischen Sensor für Streulicht).
- PWM-Steuerung statt Stromregelung (weniger effizient, aber einfacher).
Mechanischer Aufbau
- Peltier reinigen, Wärmeleitkleber auf Heißseite → Kühlkörper andrücken, aushärten lassen.
- Kaltseite reinigen, Wärmeleitpaste + Kleber → Spiegel aufkleben, gleichmäßig verteilen (keine Lufteinschlüsse!).
- Lüfter auf Kühlkörper montieren (Heißkleber / Schrauben).
- Test: Lüfter & Peltier kurz einschalten → Kondensationsmuster beobachten. Bereich mit gleichmäßiger, früher Kondensation = Messzone für Sensor & Lichtstrahl.
- Si7021 auf Spiegel kleben: Große Paste-Kugel auf Sensor, 4 Heißkleber-Tupfer an PCB-Ecken, schnell auf Messzone drücken, waagerecht ausrichten. Bei Bedarf abziehen & neu versuchen.
- LED/Laser & OPT101 ausrichten: Kupferdraht als Halterung, Heißkleber fixieren. Lichtstrahl auf Messzone richten. Reihenschlusswiderstand an LED/Laser zur Leistungsreduktion (PWM stört Sensor).
- Elektronik verdrahten (siehe Schaltplan).
Elektronik & Steuerung
- Peltier: BTS7960 H-Brücke an Arduino PWM-Pins (Kühl/Heiz-Pins). PWM hochfahren (Rampe) bis Kondensation detektiert.
- Lüfter: IRF520 MOSFET-Modul an PWM-Pin.
- Sensoren: Si7021 (I²C) für Spiegeltemperatur, DS18B20 (1-Wire) für Umgebungstemperatur, OPT101 (Analog) für Reflexion.
- Sicherheit: Watchdog-Timer (2 s) verhindert Überhitzung bei Code-Hänger (Peltier könnte Heizmodus hängen).
Arduino-Code (Kernlogik)
#include <math.h>
#include <avr/wdt.h>
#include "Si7021.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include "timer.h"
#include "timerManager.h"
#define coolingPWM 6
#define heatingPWM 5
#define coolingEnable 13
#define heatingEnable 12
#define tecFan 7
#define opticalSensor A0
#define oneWireBus A3
#define COOLING 0
#define HEATING 1
#define OFF 2
Timer timerMainLoop, timerTecCooling, timerSampleNoise;
Si7021 si7021;
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
float humidity = 0, ambientTemp = 0, opticalDewpoint = 0;
float mirrorTemp = 30, optical = 30, dewPoint = 15, relativeHumidity = 30;
int tecState = OFF;
bool cooling = false;
int intervalTecCooling = 200;
float opticalThreshold = 0.5;
int pwmIncrement = 1, startPwm = 100, maxPwm = 255;
int intervalMainLoop = 200;
int tecPwm = 0;
int noiseSampleIndex = 0, noiseSampleAmount = 10;
float noiseSampleHighest = 0, noiseSampleLowest = 10000;
bool noiseSampling = false;
float calculateHumidity(float TD, float T) {
if (TD > T) TD = T;
return 100.0 * exp((17.625*TD)/(243.04+TD)) / exp((17.625*T)/(243.04+T));
}
void SetTEC(int state, int amount) {
tecState = state;
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;
default:
digitalWrite(coolingEnable, LOW); analogWrite(coolingPWM, 0);
digitalWrite(heatingEnable, LOW); analogWrite(heatingPWM, 0);
}
}
float getOptical() {
return analogRead(opticalSensor) / 30.0;
}
void tecCoolingCallback() {
digitalWrite(tecFan, HIGH);
tecPwm = min(tecPwm + pwmIncrement, maxPwm);
SetTEC(COOLING, tecPwm);
if (optical <= (noiseSampleLowest - opticalThreshold)) {
dewPoint = mirrorTemp;
opticalDewpoint = optical;
stopTec();
}
}
void sampleNoiseCallback() {
if (noiseSampleIndex++ > noiseSampleAmount) {
timerSampleNoise.stop();
noiseSampleIndex = 0;
noiseSampling = false;
startTecCooling();
} else {
noiseSampleHighest = max(noiseSampleHighest, optical);
noiseSampleLowest = min(noiseSampleLowest, optical);
}
}
void startNoiseSampling() {
noiseSampling = true;
noiseSampleHighest = 0; noiseSampleLowest = 10000;
timerSampleNoise.start();
}
void startTecCooling() {
cooling = true; digitalWrite(tecFan, HIGH);
tecPwm = startPwm;
timerTecCooling.start();
}
void stopTec() {
cooling = false; digitalWrite(tecFan, LOW);
timerTecCooling.stop();
SetTEC(OFF, 0);
}
void mainLoop() {
sensors.setResolution(10);
sensors.requestTemperatures();
ambientTemp = sensors.getTempCByIndex(0);
mirrorTemp = si7021.measureTemperature();
optical = getOptical();
relativeHumidity = calculateHumidity(dewPoint, ambientTemp);
// Serial Plotter Format: mirrorTemp optical dewPoint
Serial.print(mirrorTemp, 2); Serial.print(' ');
Serial.print(optical, 2); Serial.print(' ');
Serial.println(dewPoint, 2);
if (!cooling && !noiseSampling && optical >= noiseSampleLowest) {
startNoiseSampling();
}
}
void setup() {
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);
timerMainLoop.setInterval(intervalMainLoop); timerMainLoop.setCallback(mainLoop); timerMainLoop.start();
timerTecCooling.setInterval(intervalTecCooling); timerTecCooling.setCallback(tecCoolingCallback);
timerSampleNoise.setInterval(intervalTecCooling); timerSampleNoise.setCallback(sampleNoiseCallback);
si7021.begin(); sensors.begin();
startNoiseSampling();
}
void loop() {
wdt_reset();
TimerManager::instance().update();
}
Genauigkeit & Kalibrierung
- Taupunkttemperatur ist Absolutwert → Kalibrierung weniger kritisch als bei kapazitiven Sensoren.
- Temperaturdifferenz zwischen Sensorposition (Si7021) & Optikzone → systematischer Fehler. Kalibrierung mit Referenz-Chilled-Mirror möglich.
- Spiegelverschmutzung: Beeinflusst Reflexionsbasislinie, aber Detektion ist relativ zum Zyklusstart → teilweise kompensiert. Regelmäßige Reinigung empfohlen.
- Sensorauflösung entscheidend: Jitter < 0,1 °C nötig. TSYS01 (0,01 °C) wäre besser als DS18B20/Si7021.
- Gute thermische Kopplung Sensor↔Spiegel (Wärmeleitpaste, nicht elektrisch leitend) zwingend.
- Kühlgeschwindigkeit < Sensorantwortzeit, sonst wird Taupunkt „überfahren“.
- Luftdruckeinfluss vernachlässigbar (Innenräume).
- Heißluft vom Kühlkörper nicht über Spiegel führen!
- Langsame Kühlung = genauer, aber träge. Oszillieren um Taupunkt beschleunigt Messung.
Sicherheit
Hardware kann Spiegel auch heizen (Polarität umkehren) → schnelles Abtrocknen. Gefahr: Wenn Code im Heizmodus hängenbleibt → Überhitzung, Schmelzen von Kleber/Kabeln, Brandgefahr. Watchdog (2 s) + Hardware-Sicherung (Thermoschalter) empfohlen.
Schaltplan

Herstellungsprozess
- Wissenschaft und Handwerk moderner Spiegel
- Bluetooth-gesteuerter Arduino-Spybot bauen – Überwachungsroboter mit IP-Kamera
- FlickMote: Gestensteuerung per Ultraschall & IR für Smart Home (Arduino 101)
- DIY Arduino TV-B-Gone: Universelle TV-Aus-Fernbedienung
- DIY Kaleidoskop-Infinity-Mirror – Bauen Sie eine beeindruckende LED-Lichtanzeige
- Einen eigenen LED-Master-Clock mit Alarm bauen – aus 12 Metern Entfernung ablesbar
- Find Me: Smarter Gegenstands-Finder mit Arduino und Bluetooth
- Optimierte Stromversorgungslösungen für Arduino-Projekte
- Arduino Tic Tac Toe mit MAX7219 LED-Matrix und Karton-Gehäuse
- Intelligenten Arduino-Vierbeiner-Roboter bauen: Schritt-für-Schritt-Anleitung