Thermostat mit Arduino bauen: DS18B20 & Relais steuern Lüfter & Heizung

Ein Lüfter, der sich einschaltet, wenn es zu warm wird, und eine Heizung, die bei Kälte anspringt – das Herzstück jedes Thermostats ist verblüffend einfach: Temperatur messen, mit einem Sollwert vergleichen, schalten. In diesem Tutorial baust du genau das mit einem DS18B20 Temperatursensor und einem KY-019 Relais. Damit dein Thermostat am Schaltpunkt nicht nervös klappert, lernst du das wichtigste Konzept gleich mit: die Hysterese.

Warum ein selbstgebauter Thermostat?

Ob Gewächshaus, 3D-Drucker-Gehäuse, Serverschrank, Terrarium oder Bierbrau-Fermenter – überall dort willst du eine Temperatur in einem bestimmten Bereich halten. Fertige Thermostate gibt es zwar, aber deiner kann genau das, was du brauchst: eigene Schaltschwellen, eine Anzeige nach deinem Geschmack, mehrere Sensoren, Datenlogging oder eine Anbindung ans Smart Home. Und das Grundprinzip – messen, vergleichen, schalten – steckt hinter unzähligen Automatisierungen. Wer den Thermostat versteht, versteht Regelungstechnik im Kleinen.

⚠️ Sicherheit zuerst – kein 230 V ohne Erfahrung: Das KY-019 Relais kann zwar Netzspannung schalten, aber Arbeiten an 230 V gehören in erfahrene Hände. Zum Lernen und für dieses Tutorial schaltest du am besten ungefährliche Kleinspannung: einen 5–12-V-Lüfter, eine LED-Lampe oder ein 12-V-Heizelement über ein separates Netzteil. So kann nichts schiefgehen.

So funktioniert der Thermostat

Der DS18B20 liefert über den OneWire-Bus die aktuelle Temperatur – nur eine Datenleitung, sehr genau und in einer wasserdichten Variante sogar für Flüssigkeiten geeignet. Der Arduino vergleicht diese Temperatur mit einer Solltemperatur und schaltet über das KY-019 Relais den Verbraucher. Ein OLED zeigt Ist- und Solltemperatur sowie den Schaltzustand. Das Entscheidende steckt in der Vergleichslogik: Ohne Hysterese würde das Relais am Sollwert im Sekundentakt ein- und ausschalten – mit Hysterese schaltet es sauber mit etwas Abstand.

Das brauchst du

DS18B20 Temperatursensor (wasserdicht) – misst die Temperatur präzise
KY-019 1-Kanal Relais – schaltet Lüfter oder Heizung
UNO R3 Entwicklungsboard (USB-C) – die Steuerzentrale
1,3 Zoll OLED-Display (I2C) – zeigt Ist, Soll und Schaltzustand
Rotary Encoder – Solltemperatur bequem einstellen

Für den DS18B20 brauchst du zusätzlich einen 4,7-kΩ-Widerstand als Pull-up zwischen Datenleitung und 5 V – der steckt im Widerstands-Set.

1Verkabelung

Der DS18B20 hängt mit drei Leitungen am Arduino, dazwischen der Pull-up-Widerstand. Das Relais bekommt seine Versorgung und eine Steuerleitung. Der OLED teilt sich den I2C-Bus mit nichts anderem.

Bauteil / Pin Arduino UNO Hinweis
DS18B20 VCC (rot) 5V Versorgung
DS18B20 GND (schwarz) GND Masse
DS18B20 DATA (gelb) D2 4,7 kΩ nach 5V
Relais VCC 5V Versorgung
Relais GND GND Masse
Relais IN (Signal) D8 Steuerleitung
OLED SDA / SCL A4 / A5 I2C-Bus
OLED VCC / GND 5V / GND Versorgung
Encoder CLK / DT D3 / D4 Solltemp einstellen
Encoder SW D5 Taster (optional)

ℹ️ Warum der 4,7-kΩ-Pull-up? Der OneWire-Bus des DS18B20 braucht einen Pull-up-Widerstand, damit die Datenleitung im Ruhezustand sauber auf HIGH liegt. Ohne ihn liest der Arduino nur Unsinn. Alle Details zum Sensor stehen im DS18B20-Tutorial.

2Temperatur auslesen

Installiere über den Bibliotheksverwalter OneWire und DallasTemperature. Der folgende Sketch liest die Temperatur alle Sekunde aus und gibt sie im Seriellen Monitor aus:

#include <OneWire.h>
#include <DallasTemperature.h>

const int ONE_WIRE = 2;
OneWire oneWire(ONE_WIRE);
DallasTemperature sensoren(&oneWire);

void setup() {
  Serial.begin(115200);
  sensoren.begin();
}

void loop() {
  sensoren.requestTemperatures();
  float t = sensoren.getTempCByIndex(0);

  if (t == DEVICE_DISCONNECTED_C) {
    Serial.println("Sensor nicht gefunden!");
  } else {
    Serial.print(t, 1);
    Serial.println(" Grad C");
  }
  delay(1000);
}

Zeigt der Monitor -127.0, ist der Sensor nicht richtig verdrahtet oder der Pull-up fehlt.

3Das Relais schalten – mit Hysterese

Jetzt kommt das Herzstück. Naiv würde man schreiben: „ist die Temperatur über dem Sollwert, Lüfter an, sonst aus“. Das Problem: Pendelt die Temperatur um genau den Sollwert, schaltet das Relais im Sekundentakt – das nervt, verschleißt das Relais und ist für Motoren schädlich. Die Lösung ist eine Hysterese: Wir schalten erst ein Grad über dem Sollwert ein und erst ein Grad darunter wieder aus.

#include <OneWire.h>
#include <DallasTemperature.h>

const int ONE_WIRE = 2;
const int RELAIS = 8;
OneWire oneWire(ONE_WIRE);
DallasTemperature sensoren(&oneWire);

float sollTemp = 25.0;      // Wunschtemperatur
float hysterese = 1.0;      // Schaltabstand
bool luefterAn = false;

void setup() {
  Serial.begin(115200);
  sensoren.begin();
  pinMode(RELAIS, OUTPUT);
  digitalWrite(RELAIS, LOW);  // Start: aus
}

void loop() {
  sensoren.requestTemperatures();
  float t = sensoren.getTempCByIndex(0);
  if (t == DEVICE_DISCONNECTED_C) { delay(1000); return; }

  // KUEHLEN: ueber Soll+Hysterese einschalten, unter Soll-Hysterese aus
  if (!luefterAn && t > sollTemp + hysterese) {
    luefterAn = true;
    digitalWrite(RELAIS, HIGH);
  } else if (luefterAn && t < sollTemp - hysterese) {
    luefterAn = false;
    digitalWrite(RELAIS, LOW);
  }

  Serial.print(t, 1); Serial.print(" C  Luefter: ");
  Serial.println(luefterAn ? "AN" : "aus");
  delay(1000);
}

💡 Was macht die Hysterese genau? Bei Soll 25 °C und 1 °C Hysterese schaltet der Lüfter bei 26 °C ein und erst bei 24 °C wieder aus. Dazwischen passiert nichts – das Relais bleibt ruhig, statt am Sollwert zu flattern. Größere Hysterese = seltener schalten, aber größere Temperaturschwankung. Ein bis zwei Grad sind meist ein guter Kompromiss.

4Heizen statt Kühlen – die Logik umdrehen

Für eine Heizung ist die Logik genau umgekehrt: Wird es zu kalt, schaltet die Heizung ein. Mit einem Modus-Schalter deckt dein Thermostat beides ab:

bool heizModus = true;    // true = heizen, false = kuehlen
bool ausgangAn = false;

void regele(float t) {
  if (heizModus) {
    // HEIZEN: unter Soll-Hyst ein, ueber Soll+Hyst aus
    if (!ausgangAn && t < sollTemp - hysterese) ausgangAn = true;
    else if (ausgangAn && t > sollTemp + hysterese) ausgangAn = false;
  } else {
    // KUEHLEN: ueber Soll+Hyst ein, unter Soll-Hyst aus
    if (!ausgangAn && t > sollTemp + hysterese) ausgangAn = true;
    else if (ausgangAn && t < sollTemp - hysterese) ausgangAn = false;
  }
  digitalWrite(RELAIS, ausgangAn ? HIGH : LOW);
}

⚠️ High- oder Low-Trigger? Das KY-019 ist ein High-Level-Trigger-Modul: Es schaltet bei HIGH am IN-Pin. Viele andere Relaismodule sind Low-Trigger und schalten bei LOW. Reagiert dein Relais verkehrt herum, drehe die HIGH/LOW-Logik einfach um. Grundlagen dazu im KY-019-Relais-Tutorial.

5OLED-Anzeige und einstellbare Solltemperatur

Zum Schluss bringen wir alles auf das OLED-Display und machen die Solltemperatur über den Rotary Encoder einstellbar. Nutze die Bibliotheken Adafruit GFX und Adafruit SSD1306:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>

Adafruit_SSD1306 display(128, 64, &Wire, -1);
OneWire oneWire(2);
DallasTemperature sensoren(&oneWire);

const int RELAIS = 8;
const int ENC_CLK = 3, ENC_DT = 4;
float sollTemp = 25.0, hysterese = 1.0;
bool ausgangAn = false;
int letzterCLK;

void setup() {
  sensoren.begin();
  pinMode(RELAIS, OUTPUT);
  pinMode(ENC_CLK, INPUT); pinMode(ENC_DT, INPUT);
  letzterCLK = digitalRead(ENC_CLK);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}

void pruefeEncoder() {
  int clk = digitalRead(ENC_CLK);
  if (clk != letzterCLK && clk == LOW) {
    if (digitalRead(ENC_DT) != clk) sollTemp += 0.5;
    else sollTemp -= 0.5;
  }
  letzterCLK = clk;
}

void zeichne(float t) {
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);  display.print("THERMOSTAT");
  display.setTextSize(2);
  display.setCursor(0, 16); display.print(t, 1); display.print(" C");
  display.setTextSize(1);
  display.setCursor(0, 40); display.print("Soll: "); display.print(sollTemp, 1);
  display.setCursor(0, 52); display.print(ausgangAn ? "AUSGANG: AN" : "AUSGANG: aus");
  display.display();
}

void loop() {
  pruefeEncoder();
  sensoren.requestTemperatures();
  float t = sensoren.getTempCByIndex(0);
  if (t != DEVICE_DISCONNECTED_C) {
    if (!ausgangAn && t > sollTemp + hysterese) ausgangAn = true;
    else if (ausgangAn && t < sollTemp - hysterese) ausgangAn = false;
    digitalWrite(RELAIS, ausgangAn ? HIGH : LOW);
    zeichne(t);
  }
}

ℹ️ Encoder sauber auslesen: Der Drehgeber wird hier einfach abgefragt. Für besonders zuverlässiges Zählen – auch bei schnellem Drehen – lohnt sich die Interrupt-Variante aus dem Rotary-Encoder-Tutorial.

Praxistipps für den Dauerbetrieb

  • Solltemperatur im EEPROM speichern: So bleibt sie nach dem Ausschalten erhalten und muss nicht neu eingestellt werden.
  • Mindestlaufzeit für Motoren: Ein Lüfter oder Kompressor sollte nach dem Einschalten einige Minuten laufen. Merke dir die Einschaltzeit mit millis() und verhindere zu frühes Abschalten.
  • Sensor richtig platzieren: Der DS18B20 misst dort, wo er sitzt – nicht direkt am Lüfterausgang, sondern repräsentativ im Raum oder Behälter.
  • Daten loggen: Kombiniere den Thermostat mit einem SD-Datenlogger, um den Temperaturverlauf aufzuzeichnen.
  • Ins Smart Home: Mit einem ESP32 statt UNO schaltest du den Ausgang zusätzlich per MQTT und Home Assistant.

Troubleshooting

⚠️ Temperatur zeigt -127 °C: Der Sensor wird nicht gefunden. Prüfe den 4,7-kΩ-Pull-up zwischen Data und 5 V und die Verdrahtung der drei Leitungen.

⚠️ Relais klappert am Sollwert: Hysterese zu klein oder nicht aktiv. Erhöhe sie auf 1–2 °C und stelle sicher, dass die Ein- und Ausschaltbedingung wirklich unterschiedliche Schwellen nutzen.

⚠️ Relais schaltet genau verkehrt herum: Dein Modul ist ein Low-Trigger. Drehe die HIGH/LOW-Logik am Relais-Pin um.

⚠️ Arduino hängt oder startet neu, wenn das Relais schaltet: Ein Lüfter- oder Motor-Verbraucher zieht Strom-Spitzen. Versorge den Verbraucher über ein eigenes Netzteil und verbinde nur die Masse gemeinsam. Nie einen Motor direkt aus dem Arduino speisen.

⚠️ OLED bleibt schwarz: Adresse 0x3C prüfen und ob SDA/SCL wirklich an A4/A5 hängen – zur Not mit einem I2C-Scanner.

🚀 Dein Thermostat-Starterpaket

Alle Bauteile für dieses Projekt im Shop:

Fazit

Aus einem Temperatursensor, einem Relais und ein bisschen Logik ist ein vollwertiger Thermostat geworden. Du hast gelernt, den DS18B20 über OneWire auszulesen, das KY-019 Relais anzusteuern und – das Wichtigste – mit einer Hysterese ein sauberes, klapperfreies Schalten zu erreichen. Mit dem Modus-Schalter deckt dein Gerät Heizen und Kühlen ab, und die OLED-Anzeige mit einstellbarem Sollwert macht es alltagstauglich.

Von hier aus ist viel möglich: mehrere Sensoren für verschiedene Zonen, eine Mindestlaufzeit für Motoren, Datenlogging oder die Anbindung ans Smart Home per MQTT. Behalte nur immer die Sicherheit im Blick – zum Lernen bleibt es bei ungefährlicher Kleinspannung. Viel Spaß beim Regeln!

Zurück zum Blog