Brauchst du einen einfach zu nutzenden digitalen Temperatursensor? Der DS18B20 ist eine beliebte Alternative zu analogen Temperaturmodulen.
Der DS18B20 ist ein digitaler Temperatursensor von Dallas Semiconductors, das inzwischen zu Maxim gehört. Der Sensor bietet eine Genauigkeit von ± 0,5 °C und kann in einem Temperaturbereich von - 55 °C bis 125 °C arbeiten. Er nutzt dabei den 1-Wire-Bus zur Datenübertragung. Dieser Bus wurde ebenfalls von Dallas Semiconductors entwickelt und benötigt, wie der Name schon sagt, nur eine einzige Datenleitung neben den Stromversorgungsleitungen. Will man es auf die Spitze treiben, kann die Versorgungsspannung auch über die Datenleitung zugeführt werden. Dies wird auch als Parasite Power Mode bezeichnet. In diesem Modus benötigt man insgesamt nur zwei Leitungen. Wir werden diesen Modus in diesem Tutorial jedoch nicht behandeln. Die Arduino-Module verwenden typischerweise drei Pins mit einer eigenständigen Zuleitung für die Versorgungsspannung.
Jeder DS18B20 verfügt über eine eindeutige 48-Bit-Adresse, die es ermöglicht, eine schier unbegrenzte Anzahl von Sensoren am selben 1-Wire-Bus zu nutzen. Der einzige Nachteil ist, dass die Kommunikationsgeschwindigkeit äußerst gering ist. Für die Temperaturmessung ist dies jedoch nicht wirklich von Bedeutung. Die Temperatur ändert sich normalerweise nicht so schnell, und der DS18B20 selbst ist auch nicht gerade schnell. Eine Messung bei voller 12-Bit-Auflösung dauert etwa 750 ms. Für schnellere Messungen kann die Auflösung in 1-Bit-Schritten bis auf 9-Bit reduziert werden. Bei 9-Bit-Auflösung dauert eine Messung etwa 100 ms.
Mit der Bibliothek, die wir in diesem Tutorial verwenden, kann man die Auflösung festlegen, indem man z.B. sensors.setResolution(9)
für eine Auflösung von 9-Bit aufruft. In diesem Tutorial werden wir uns an die Standardauflösung von 12 Bit halten und nicht auf Geschwindigkeit zielen. Zu beachten ist, dass die Funktion erneut aufgerufen werden muss, wenn zur Laufzeit neue Sensoren zum Bus hinzugefügt werden.
Es sind mehrere Typen von DS18B20-Sensoren erhältlich. Zunächst gibt es fertige Module wie das links abgebildete KY-001. Diese Module enthalten bereits die erforderlichen Komponenten zur Ansteuerung des 1-Wire-Busses. Sie sind bereits für den Einsatz mit dem Arduino vorbereitet. Zum anderen gibt es einzelne DS18B20-Sensoren in verschiedenen Gehäusen, z.B. in einem transistorähnlichen TO-92-Gehäuse, wie es auf dem Modul verwendet wird, oder in einem wasserdichten Gehäuse, wie es rechts abgebildet ist.
Wenn du die Temperatur von Flüssigkeiten messen möchtest, empfehle ich dir dringend, eine wasserdichte Version zu verwenden, da der Sensor sonst schnell durch Korrosion beschädigt wird. Um einen DS18B20 zu verwenden, der nicht auf einem vorgefertigten Modul geliefert wird, benötigt man einen zusätzlichen Widerstand 4,7 kΩ, der als Pull-up für die 1-Wire-Bus-Datenleitung genutzt wird. Das nachfolgende Bild zeigt, wie man die erforderliche Schaltung auf einem Breadboard aufbaut.
Beginnen wir zunächst damit, ein einziges Modul zusammen mit dem Arduino zu nutzen. Für den Fall, dass du einen separaten DS18B20-Sensor ohne Modul besitzt, nutze die im letzten Abschnitt gezeigte Schaltung mit externem Pull-up-Widerstand. Wenn du ein fertiges Modul hast, brauchst du nur drei Verbindungsdrähte. Ich habe die Datenleitung mit Pin 8
des Arduino verbunden. Auf dem Modul ist der Anschluss mit einem S
markiert. Es ist nicht erforderlich, Pin 8
zu benutzen, jeder Pin ist dafür geeignet. Natürlich muss der Code angepasst werden, wenn ein anderer Pin für die Datenleitung genutzt werden soll. Als Nächstes müssen wir die Stromleitungen anschließen. Verbinde dazu GND
mit dem linken Pin, der mit -
markiert ist, und 5V
mit dem mittleren Pin, so wie es auf dem Bild dargestellt ist.
Um das Modul zusammen mit dem Arduino verwenden zu können, werden wir auf die DallasTemperature-Bibliothek zurückgreifen. Falls du es nicht bereits getan hast, musst du sie zuerst installieren. Öffne einfach den Bibliotheksverwalter unter Werkzeuge
> Bibliotheken verwalten ...
und suche nach dem Sensor. Wähl die DallasTemperature-Bibliothek aus und installiere sie. Es erscheint die Abfrage, ob die OneWire-Bibliothek gemeinsam mit der Dallas-Temperatur-Bibliothek installiert werden soll. Die OneWire-Bibliothek ist erforderlich, um die DallasTemperature-Bibliothek zu verwenden. Sie stellt die erforderlichen Funktionen für die Verwendung des 1-Wire-Busses zur Verfügung.
In diesem Tutorial werden wir den Temperaturwert im seriellen Monitor ausgeben. Direkt am Anfang unseres Programms müssen wir die erforderlichen Bibliotheken einbinden und eine 1-Wire-Bus-Instanz für Pin 8 erzeugen und diese an die DallasTemperature-Bibliothek übergeben:
#include <OneWire.h>
#include <DallasTemperature.h>
// Sensor at pin 8
OneWire bus(8);
DallasTemperature sensors(&bus);
In loop
müssen wir zwei Dinge tun: die Messung starten und dann den Messwert vom Sensor abfragen. Wir können die Messung starten, indem wir die Methode requestTemperatures
aufrufen. In unserem Fall wollen wir nur den ersten Sensor auf dem 1-Wire-Bus verwenden.
Wir können unsere Anfrage auf den ersten Sensor beschränken, indem wir die Methode requestTemperaturesByIndex
mit dem Index 0
aufrufen. Um den Messwert abzurufen, können wir getTempCByIndex
für die Temperatur in Grad Celsius oder getTempFByIndex
für die Temperatur in Grad Fahrenheit aufrufen.
Der folgende Code gibt diese Werte etwa alle 5 Sekunden auf der seriellen Konsole aus (eher alle 6 Sekunden, aufgrund der Zeit, die der Sensor benötigt, um die Messung durchzuführen und die Daten über den 1-Wire-Bus zu übertragen):
#include <OneWire.h>
#include <DallasTemperature.h>
// Sensor at pin 8
OneWire bus(8);
DallasTemperature sensors(&bus);
void setup() {
Serial.begin(9600);
}
void loop() {
// Start the temperature measurement and wait for it
sensors.requestTemperaturesByIndex(0);
// Read and show the result
Serial.print("Temperature (°C): ");
Serial.println(sensors.getTempCByIndex(0));
Serial.print("Temperature (°F): ");
Serial.println(sensors.getTempFByIndex(0));
delay(5000);
}
Sobald der Code auf den Arduino hochgeladen ist, solltest du im seriellen Monitor die aktuelle Temperatur sehen können:
Temperature (°C): 21.44
Temperature (°F): 70.59
Zum Schluss wollen wir uns noch ansehen, wie man mehrere Sensoren am selben Bus verwenden kann. Leider erfordert dies die Verwendung eines separaten DS18B20. Man benötigt nur einen Pull-up-Widerstand für den gesamten Bus. Leider verfügt jedes KY-001-Modul über einen eigenen Pull-up-Widerstand. Wenn man zu viele von ihnen miteinander verbindet, funktioniert der Bus nicht mehr richtig. Bitte verwende daher separate Sensoren ohne integrierte Pull-ups, um sicherzustellen, dass alles wie vorgesehen funktioniert. Das Bild unten zeigt, wie zwei wasserdichte DS18B20-Sensoren am selben Bus angeschlossen werden können. Verbinde dazu einfach die zusammengehörigen Pins miteinander. Natürlich kann man diese Schaltung auch mit DS18B20-Sensoren in einem TO-92-Gehäuse bauen oder sogar mischen. Elektrisch gesehen gibt es keinen Unterschied, nur die Bauform ist bei diesen Sensortypen unterschiedlich.
Wir wissen bereits, wie wir eine Messung für alle angeschlossenen Sensoren auslösen können: Wir rufen einfach requestTemperatures
auf. Um alle Messwerte im seriellen Monitor auszugeben zu können, müssen wir über alle Sensoren iterieren und jeden von ihnen auslesen. Zum Glück kümmert sich die Bibliothek für uns um die Details. Theoretisch könnten wir einfach getTempCByIndex
oder getTempFByIndex
in einer Schleife aufrufen und den Index jedes Mal um eins erhöhen. Sobald wir den letzten Sensor erreichen, wird eine große negative Zahl zurückgegeben, um einen Fehler anzuzeigen. Dies sagt uns, wann wir aufhören müssen. Das Problem dabei ist, dass nur schwer zu erkennen ist, welcher Sensor welcher ist.
Erinnerst du dich, dass wir gesagt haben, dass jeder Sensor eine eindeutige 48-Bit-Adresse besitzt? Durch Aufruf von getAddress
mit dem Sensorindex können wir die Adresse des Sensors abfragen. Um die Adresse zu speichern, muss man der Funktion neben dem Index ein DeviceAddress
-Objekt übergeben. Die Adresse wird in das DeviceAddress
-Objekt geschrieben, das im Grunde ein Array von 8 Bytes ist. Wenn wir das Ende erreichen und es keinen weiteren Sensor für den angeforderten Index mehr gibt, wird die Funktion false
zurückgeben, andernfalls gibt sie true
zurück. Um über alle Geräte zu iterieren, können wir folglich einfach den Index erhöhen und eine Schleife so lange durchlaufen, bis getAddress
den Wert false
zurückgibt. Um die Messwerte zu lesen, können wir dann getTempC
oder getTempF
mit der Adresse des Sensors aufrufen.
Den vollständigen Code kannst du unten sehen. Ich habe zudem eine kleine Hilfsfunktion printAddress
erstellt, die die Adresse des Sensors ausgibt.
#include <OneWire.h>
#include <DallasTemperature.h>
// Sensor at pin 8
OneWire bus(8);
DallasTemperature sensors(&bus);
void setup() {
Serial.begin(9600);
}
void printAddress(DeviceAddress addr) {
for(int i = 0; i < 8; i++) {
if(i != 0) Serial.print(':');
if(addr[i] < 0x10) Serial.print('0');
Serial.print(addr[i], HEX);
}
}
void loop() {
// Start the temperature measurement on all sensors and wait for it
sensors.requestTemperatures();
int index = 0;
DeviceAddress addr;
while(sensors.getAddress(addr, index)) {
// Sensor index and address
Serial.print("Sensor ");
Serial.println(index);
Serial.print(" - Address: ");
printAddress(addr);
Serial.println("");
// Read and show the result
Serial.print(" - Temperature (°C): ");
Serial.println(sensors.getTempC(addr));
Serial.print(" - Temperature (°F): ");
Serial.println(sensors.getTempF(addr));
// Next index
index++;
}
delay(5000);
}
Sobald du den Code auf den Arduino hochgeladen hast, solltest du eine Ausgabe wie diese im seriellen Monitor sehen können:
Sensor 0
- Address: 28:E6:0B:E2:20:19:01:2F
- Temperature (°C): 20.50
- Temperature (°F): 68.90
Sensor 1
- Address: 28:8B:7D:2E:21:19:01:D7
- Temperature (°C): 20.37
- Temperature (°F): 68.68
Die Adresse und die Messwerte für jeden angeschlossenen Sensor werden ausgegeben. Wenn du nur einen einzigen Sensor anschließt, kannst du dessen Adresse leicht ablesen. Beschrifte den Sensor mit der Adresse, um später nachvollziehen zu können, welcher Sensor was misst. Übrigens hast du vielleicht bemerkt, dass die im seriellen Monitor angezeigte Adresse 64-Bit (8 Byte) lang ist und nicht 48-Bit. Das erste Byte ist der Produktfamilien-Code, der das Gerät als DS18B20-Sensor identifiziert. Das letzte Byte ist eine 8-Bit CRC-Prüfsumme. Nur die 48-Bit dazwischen sind für jeden Sensor eindeutig.
Der DS18B20 verfügt über zusätzliche Funktionen wie beispielsweise Alarme. Alarme ermöglichen es, einen Temperaturschwellenwert auf dem Modul einzustellen und später nur die Sensoren auszulesen, bei denen dieser Schwellenwert überschritten wurde. Diese Funktionalität wird für komplexe Lösungen mit vielen Sensoren interessant. In unserem Fall können wir einfach alle Sensoren auslesen. Ich werde daher in diesem Tutorial nicht auf diese weiterführenden Funktionen eingehen.