In diesem Teil des Arduino-Kurses werden wir zwei Konzepte für Sensoren vergleichen. Wir werden analoge und digitale Thermometer in der Praxis testen!
Dazu werden wir die sehr beliebten LM35– und DS18B20-Sensoren verwenden. Die Kombination dieser Schaltungen mit den kennengelernten programmierbaren Dioden wird es uns ermöglichen, ein interessantes Haus-Thermometer zu bauen!
Bestellen Sie ein Set mit Elementen und beginnen Sie mit dem Lernen in der Praxis! Hier gehts zum Shop >>
In diesem Teil des Arduino-Kurses werden wir uns mit Temperatursensoren beschäftigen, die für viele Projekte nützlich sein können. Dieses Mal wird der elektronische Teil sehr einfach sein. Das Wichtigste, was man sich nach dieser Lektion merken sollte, ist der Unterschied zwischen analogen und digitalen Sensoren.
Analoger Sensor vs. digitaler Sensor
Es gibt eine große Anzahl von Sensoren auf dem Markt. Farbsensoren, Tonsensoren, Abstandssensoren, Positionssensoren – die Auswahl ist wirklich groß! Allerdings lassen sich zwei Gruppen von Sensoren eindeutig unterscheiden:
- Digitale Sensoren,
- Analoge Sensoren.
Analoge Sensoren wandeln die gemessene Größe (z. B. die Temperatur) in eine elektrische Größe um, die proportional zu dem gemessenen Wert ist. Steigt zum Beispiel die Temperatur, so steigt die Spannung oder der Widerstand am Sensorausgang.
Digitale Sensoren senden Informationen in Form einer Folge von Bits. Um sie auszulesen, werden digitale Schaltungen benötigt, in der Regel Mikrocontroller – also z. B. unser Arduino.
Digitale Sensoren erfreuen sich heutzutage zunehmender Beliebtheit. Sie können immer komplexere Messungen durchführen, und das Ablesen und korrekte Interpretieren der Ergebnisse solcher Sensoren ist manchmal einfacher als bei ähnlichen analogen Systemen.
Viele Menschen entscheiden sich jedoch nach wie vor für analoge Sensoren, weil sie preiswerter sind. Außerdem ist ein Sensor mit analogem Ausgang für einfache Temperaturmessungen oft einfach praktischer (man muss ihn nur an einen analogen Eingang anschließen).
Gehen wir also zur Praxis über!
Fertige Sets für Forbot-Kurse
Die Komponenten für die Übungen aus dem Arduino-Kurs (Stufe 2) sind als fertige Sets erhältlich! Darin enthalten sind programmierbare Dioden, analoge und digitale Thermometer, 7-Segment-Anzeigen und ein Bewegungssensor (PIR).
Analoges Thermometer: LM35
Zunächst werden wir uns das beliebte LM35-Thermometer ansehen. Der Sensor befindet sich in einem TO-92-Gehäuse, das wir normalerweise mit Transistoren in Verbindung bringen. Natürlich haben seine Leitungen hier einen ganz anderen Zweck. Im Fall des LM35 versorgen die äußeren Anschlüsse die Stromversorgung, und am mittleren Anschluss wird die Temperatur abgelesen (durch Messung der Spannung).
Die wichtigsten Informationen über das analoge Thermometer LM35:
- kalibriert für die Celsius-Skala (10 mV/°C),
- Messung von 0 bis 100°C
- Versorgungsspannung von 4 bis 30V,
- Für Details verweise ich auf das LM35.
Wie man sieht, ist der zulässige Versorgungsspannungsbereich enorm. Wir werden die Sensoren natürlich mit den auf dem Arduino-Board verfügbaren standardmäßigen 5 V versorgen. Der LM35-Sensor ist linear, d. h. jedes Mal, wenn die Ausgangsspannung um 10 mV ansteigt, entspricht dies einer zusätzlichen Temperatur von 1 °C.
Weitere Informationen über den LM35 sind in der zugehörigen Dokumentation zu finden.
Anschließen des LM35 an den Arduino
Beginnen wir mit dem Anschluss eines Sensors. Wir schließen die Stromversorgung an, wie sie im Bild oben markiert wurde. Dann verbinden wir das mittlere Kabel direkt mit dem analogen Pin des Arduino (z.B. A5).
Dies ist bei weitem eine der einfachsten Verbindungen, die während des Kurses erforderlich sind, möge es immer wieder so einfach sein! Jetzt kannst du mit dem Programm weitermachen…
Temperaturmessung: analoger Sensor
Die Aufgabe des Programms wird es sein, die Spannung an Pin A5 zu lesen und entsprechend umzurechnen. Wie in der Dokumentation beschrieben, entspricht 1°C 10 mV. Daher muss der ADC-Wert zunächst in Spannung umgewandelt werden. Zur Erinnerung: Wir tun dies, indem wir den Messwert mit 5 multiplizieren und dann dieses Ergebnis durch 1024 teilen (der Betriebsbereich des Senders ist 0…1023). Um am Ende Grad Celcius zu erhalten, multiplizieren wir den resultierenden Wert mit 100 (weil jede 10 mV, 1 Grad ist).
Im Programm kann dies in eine einzige Zeile geschrieben werden:
#define LM35 A5
void setup(){
Serial.begin(9600);
}
void loop(){
//Umrechnung des ADC-Messwerts in Temperatur wie im Kurs beschrieben
float Temperatur = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
//Senden der aktuellen Temperatur über UART
Serial.print("Aktuelle Temperatur: ");
Serial.print(Temperatur);
Serial.println("*C");
delay(200);
}
Nach dem Start des oben genannten Programms erhalten wir im seriellen Monitor die aktuellen Temperaturmesswerte. Die folgende Animation zeigt die Funktionsweise des Sensors nach seiner Erwärmung.
Wenn wir versuchen, den Sensor abzukühlen (zum Beispiel mit einem Eiswürfel), wird auf dem Bildschirm nur 0°C angezeigt. Leider muss die Verkabelung des LM35 geändert werden, damit er negative Temperaturen messen kann. Genauere Informationen dazu findest du im Datenblatt!
Sicherheitshinweis!
Wenn jemand auf die Idee kommt, Sensoren mit Druckluft abzukühlen und sie dann mit einem Feuerzeug zu erhitzen, möchte ich daran erinnern, dass die meisten Druckluftdosen brennbare Gase enthalten!
Es ist sicherer, den Sensor zu testen, indem man etwas Kaltes darauf legt (zum Beispiel einen Eiswürfel in einer Plastiktüte, um zu verhindern, dass Wasser die Elektronik beschädigt).
Zusätzliche Aufgabe 7.1
Erweitere das Programm, um 2 Temperatursensoren zu unterstützen und ihre Ergebnisse nebeneinander anzuzeigen. Der dritte angezeigte Wert (in einer neuen Zeile) sollte die Differenz zwischen den 2 Messungen sein.
Thermometer mit MAX/MIN-Funktion
Angenommen, die Messung der Temperatur im Bereich von 0-100°C reicht uns aus. Lassen Sie uns ein Raumthermometer mit der Funktion zur Speicherung der minimalen und maximalen Temperatur erstellen.
Beginnen wir mit dem Speichern des Höchstwerts. Dafür müssen wir einfach eine Variable erstellen, zum Beispiel:
float tempMAX = 0; //Aktuelle maximale Temperatur
Natürlich muss diese Variable ganz am Anfang deklariert werden (vor setup()/loop()), denn wir wollen nicht, dass jede loop() sie zurücksetzt. Nun müssen wir prüfen, ob gerade die höchste Temperatur erreicht ist. Wie machen wir das?
Wir müssen nur in jedem Schleifendurchlauf prüfen, ob die aktuelle Temperatur größer als der gespeicherte Höchstwert ist, und dann:
- wenn die Bedingung erfüllt ist,
dann soll der aktuelle Wert als Höchstwert gespeichert werden, - wenn die Bedingung nicht erfüllt ist,
dann machen wir nichts!
In der Praxis wird das ganze Programm wie folgt aussehen:
#define LM35 A5
float tempMAX = 0; //Aktuelle maximale Temperatur
void setup(){
Serial.begin(9600);
}
void loop(){
//Umrechnung des ADC-Messwerts in Temperatur wie im Kurs beschrieben
float Temperatur = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
if (Temperatur > tempMAX) { //Wenn die aktuelle Temperatur höher ist als die maximale Temperatur
tempMAX = Temperatur; //dann setze die aktuelle Temperatur als Maximum.
}
//Senden der Maximaltemperatur über UART
Serial.print("Max: ");
Serial.print(tempMAX);
Serial.println("*C");
delay(200);
}
Diesmal werden nur Informationen über den höchsten Wert im Monitor der seriellen Schnittstelle angezeigt. Es ist nicht möglich, dass der nächste Wert, der angezeigt wird, kleiner ist als der vorherige:
Versuchen wir nun analog dazu, den Mindestwert zu speichern. Wir erstellen eine neue Variable:
float tempMIN = 0; //Aktuelle Mindesttemperatur
Anschließend prüfen wir, ob der aktuelle Wert kleiner ist als der zuvor gespeicherte Wert, d.h.:
if (Temperatur < tempMIN) { //Wenn die aktuelle Temperatur niedriger ist als die Mindesttemperatur
tempMIN = Temperatur; //dann setze die aktuelle Temperatur als Minimum.
}
Na toll, nur die oben beschriebene Suche nach der niedrigsten Temperatur wird nicht funktionieren! Als wir die neue Variable erstellt haben, haben wir ihr den Wert „0“ zugewiesen, so dass es nicht möglich ist, jemals eine noch niedrigere Temperatur zu messen (unser Sensor kann keine negativen Werte messen).
Dieser Fehler wird von vielen Programmieranfängern gemacht!
Bei der Initialisierung der Variablen, die die Information über die Mindesttemperatur enthält, sollten wir ihr eine akzeptable Höchsttemperatur zuweisen, z. B. 150. Dann besteht die Möglichkeit, dass der gemessene Wert darunter liegt.
Das ist die eine Möglichkeit, dieses Problem zu lösen.
Die andere werden wir prüfen, wenn wir das zweite Thermometer testen.
Nach der Änderung wird das gesamte Programm wie folgt aussehen:
#define LM35 A5
float tempMAX = 0; //Aktuelle Maximaltemperatur
float tempMIN = 150; //Aktuelle Minimaltemperatur
void setup(){
Serial.begin(9600);
}
void loop(){
//Umrechnung des ADC-Messwerts in Temperatur wie im Kurs beschrieben
float Temperatur = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
if (Temperatur > tempMAX) { //Wenn die aktuelle Temperatur höher ist als die maximale Temperatur
tempMAX = Temperatur ; //dann setze die aktuelle Temperatur als Maximum.
}
if (Temperatur < tempMIN) { //Wenn die aktuelle Temperatur niedriger ist als die minimale
tempMIN = Temperatur ; //dann setze die aktuelle Temperatur als Minimum.
}
// Senden der maximalen Temperatur über UART
Serial.print("Max: ");
Serial.print(tempMAX);
Serial.println("*C");
// Senden der minimalen Temperatur über UART
Serial.print("Min: ");
Serial.print(tempMIN);
Serial.println("*C");
delay(200);
}
Zur besseren Lesbarkeit schlage ich jedoch vor, die Codeabschnitte zu verschieben, die für das Senden des Textes an den Computer zuständig sind. Es hat keinen Sinn, ständig Höchst- und Mindestwerte zu senden. Es ist besser, dies nur zu tun, wenn sie sich ändern:
#define LM35 A5
float tempMAX = 0; //Aktuelle Maximaltemperatur
float tempMIN = 150; //Aktuelle Minimaltemperatur
void setup(){
Serial.begin(9600);
}
void loop(){
//Umrechnung des ADC-Messwerts in Temperatur wie im Kurs beschrieben
float Temperatur = ((analogRead(LM35) * 5.0) / 1024.0) * 100;
if (Temperatur > tempMAX) { //Wenn die aktuelle Temperatur höher ist als die maximale Temperatur
tempMAX = Temperatur ; //dann setze die aktuelle Temperatur als Maximaltemperatur.
//Senden der Maximaltemperatur über UART
Serial.print("Neuer Max-Wert: ");
Serial.print(tempMAX);
Serial.println("*C");
}
if (Temperatur < tempMIN) { //Wenn die aktuelle Temperatur niedriger ist als die minimale Temperatur
tempMIN = Temperatur ; //dann setze die aktuelle Temperatur als Minimum.
//Senden der Minimaltemperatur über UART
Serial.print(" Neuer Min-Wert: ");
Serial.print(tempMIN);
Serial.println("*C");
}
delay(200);
}
Wenn nun der Monitor der seriellen Schnittstelle gestartet wird, erhalten wir nur Informationen über die Änderungen. In der folgenden Animation sieht man, welche Auswirkungen es hat, wenn der Sensor sanft erwärmt und dann schnell abgekühlt wird:
Vor- und Nachteile des LM35
Auf der einen Seite haben wir einen relativ billigen und einfach zu bedienenden Sensor. Andererseits hat er aber auch seine Nachteile. Erstens kann das Auslesen durch den ADC umständlich sein, vor allem bei langen Messkabeln, die „Störungen aus der Luft“ einfangen können. Außerdem wird für jeden Sensor ein weiterer ADC-Kanal benötigt.
Wenn wir die Temperatur in 6 Räumen messen wollten,
hätten wir bereits zu wenig freie ADC-Pins.
Zweitens ist der Messbereich recht begrenzt, und der LM35-Sensor ist in einer solchen Basisversion nicht geeignet, um beispielsweise die Temperatur zu messen, die in Deutschland herrschen kann. Es ist also an der Zeit, sich nach einem digitalen Sensor umzusehen, der die oben genannten Probleme löst!
Zusätzliche Aufgabe 7.2
Das Thermometer soll alle 2 Sekunden Informationen über die aktuelle Temperatur an den Computer senden. Mit der Betätigung von zwei Tasten sollen die aktuell gespeicherten Extremtemperaturen angezeigt werden.
Digitales Thermometer: DS18B20
Wir werden uns nun den sehr, sehr beliebten digitalen Sensor DS18B20 ansehen, der mit dem Arduino über eine 1-wire-Schnittstelle kommuniziert, über die man auf Wikipedia mehr lesen kann.
Auch dieser Sensor wird in einem TO-92-Gehäuse hergestellt, und wie zuvor werden wir Daten aus dem mittleren Beinchen auslesen. Aber Vorsicht mit der Stromversorgung! Bei diesem Sensor muss die Stromversorgung in umgekehrter Richtung erfolgen (im Vergleich zum LM35)! Die korrekte Beschreibung der Anschlüsse sieht wie folgt aus:
Die wichtigsten Informationen über das Digitalthermometer DS18B20:
- Messung von -50 bis 125°C,
- Versorgungsspannung von 3 bis 5,5V,
- Genauigkeit: +/- 0,5 °C im Bereich von -10 °C bis 85 °C,
- Einzelheiten siehe Datenblatt.
Anschließen eines digitalen Thermometers an einen Arduino
Der Anschluss dieses Sensors sieht ähnlich aus. Die beiden äußersten Anschlüsse sind mit der Stromversorgung verbunden (wie oben gezeigt), und das mittlere Bein ist mit dem Arduino verbunden (in meinem Fall der A5). Es ist jedoch wichtig, einen 4,7-kΩ-Widerstand zwischen dem Ausgang (mittleres Bein) und der positiven Schiene der Stromversorgung hinzuzufügen.
Der Einbau dieses Widerstands ist unverzichtbar!
Beispiel für eine Verbindung:
Temperaturmessung: digitaler Sensor
Man sollte mit dem Sensor über die 1-wire-Schnittstelle kommunizieren. Dazu muss man jedoch das Datenblatt studieren, um zu wissen, welche Informationen man an den Sensor senden muss und wie man das, was zurückkommt, interpretieren kann. Solche Experimente sind für diejenigen empfehlenswert, die keine Angst vor langen Programmen haben.
In diesem Kurs werden wir uns jedoch auf die Bibliothek konzentrieren: Arduino-Temperature-Control-Library. Dazu wird die OneWire-Bibliothek benötigt, damit sie richtig funktioniert. Der Prozess der Installation neuer Pakete wurde bereits mehrmals im Kurs behandelt (zumindest in Teil 2), daher werde ich ihn nicht wiederholen.
Denk daran, die oben genannten Bibliotheken zu installieren, bevor du weitermachst!
Wir beginnen, wie beim analogen Sensor, mit dem Lesen in einer Schleife des aktuellen Wertes der Umgebungstemperatur. Zunächst fügen wir zwei Zeilen hinzu, die den Compiler über Bibliotheken informieren:
#include
#include
Die erste ist für die Kommunikation über 1-Wire zuständig und die zweite ist die gerade installierte Bibliothek von Temperatursensoren. Als nächstes müssen wir die Sensorverbindung deklarieren:
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Übertragung von Informationen an die Bibliothek
Die erste Zeile ist für den Start der 1-Wire-Kommunikation auf Pin Nr. A5 zuständig, und die zweite Zeile übergibt diese Informationen an die installierte Bibliothek, die unsere Sensoren verwaltet.
In der Funktion setup() starten wir die Übertragung über den UART und initialisieren die Sensoren:
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
}
In der Schleife loop() „fragen“ wir den Sensor nach der aktuellen Temperatur und zeigen sie dann an:
void loop(void) {
sensors.requestTemperatures(); // Abrufen der Sensortemperatur
Serial.print("Aktuelle Temperatur: ");
Serial.println(sensors.getTempCByIndex(0)); //Informationen anzeigen
delay(500);
}
Die rätselhafte Bezeichnung sensors.getTempCByIndex(0) bedeutet, dass die Temperatur des ersten Sensors (sie sind von 0 an nummeriert) in Grad Celsius gemessen wird. Das Ablesen der Informationen vom zweiten Sensor würde also wie folgt aussehen: sensors.getTempCByIndex(1). Wir werden uns jedoch etwas später mit dem Anschluss mehrerer Sensoren befassen.
Der Aufruf von sensors.getTempFByIndex(0) gibt einen Wert in der Fahrenheit-Skala zurück.
Zusammengefasst sieht das gesamte Programm derzeit wie folgt aus:
#include
#include
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Übertragung von Informationen an die Bibliothek
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
}
void loop(void) {
sensors.requestTemperatures(); //Temperatur der Sensoren auslesen
Serial.print("Aktuelle Temperatur: ");
Serial.println(sensors.getTempCByIndex(0)); //Anzeigen der Informationen
delay(500);
}
Der Effekt auf dem seriellen Protokollmonitor:
Übrigens ist es möglich, das zu überprüfen, was bei der Verwendung des analogen Sensors nicht möglich war, nämlich die Messung von negativen Temperaturen. Zu diesem Zweck habe ich die „Kühlmöglichkeiten“ einer umgedrehten Druckluftdose genutzt. Wie man sieht, wurde eine Temperatur von -27ºC erreicht!
Allerdings rate ich euch ausdrücklich davon ab, mit komprimiertem, brennbarem Gas zu spielen. Es ist sicherer, den Sensor zu testen, indem man etwas Kaltes auf ihn legt (z. B. einen Eiswürfel in einer Plastiktüte, damit Wasser die Elektronik nicht beschädigt).
Thermometer mit MAX/MIN-Funktion - Version 2
Wie versprochen, kehren wir nun zum Thema der Messung der Minimal- und Maximaltemperatur zurück. Diesmal lösen wir das „Problem“ der Vorbelegung der Werte der Variablen anders. Außerdem deklarieren wir zu Beginn zwei neue Variablen.
Diesmal ist ihr Wert nicht wichtig!
float tempMAX = 0; //Aktuelle Maximaltemperatur
float tempMIN = 0; //Aktuelle Minimaltemperatur
Um ihren Wert brauchen wir uns nicht kümmern, denn etwas weiter unten in der Funktion setup() werden wir ihnen einen einmaligen Wert für die erste Ablesung zuweisen:
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Intialisierung der Sensoren
//den ersten Messwert als MAX und MIN einstellen
sensors.requestTemperatures();
tempMAX = sensors.getTempCByIndex(0);
tempMIN = sensors.getTempCByIndex(0);
}
Auf diese Weise müssen wir uns keine Gedanken über den Betriebsbereich des Sensors machen. Wir werden immer mit dem Wert beginnen, den der Sensor aufgezeichnet hat, also sowohl niedrigere als auch höhere Temperaturen erfassen.
Das ganze Programm sieht nun wie folgt aus:
#include
#include
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Informationen an die Bibliothek übertragen
float tempMAX = 0; //Aktuelle Maximaltemperatur
float tempMIN = 0; //Aktuelle Minimaltemperatur
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Intialisierung der Sensoren
//Den ersten Messwert als MAX und MIN festlegen
sensors.requestTemperatures();
tempMAX = sensors.getTempCByIndex(0);
tempMIN = sensors.getTempCByIndex(0);
}
void loop(void) {
sensors.requestTemperatures(); // Abrufen der Sensortemperatur
float Temperatur = sensors.getTempCByIndex(0); //Temperatur in Variable schreiben
if (Temperatur > tempMAX) { //wenn die aktuelle Temperatur höher ist als die maximale
tempMAX = Temperatur; //dann aktuelle Temperatur als Maximum einstellen.
//Senden der Maximaltemperatur über UART
Serial.print("Neuer Max-Wert: ");
Serial.print(tempMAX);
Serial.println("*C");
}
if (Temperatur < tempMIN) { //Wenn die aktuelle Temperatur niedriger als die Minimaltemperatur ist
tempMIN = Temperatur; //dann aktuelle Temperatur als Minimum festlegen.
//Senden der Minimaltemperatur über den UART
Serial.print("Neuer Min-Wert: ");
Serial.print(tempMIN);
Serial.println("*C");
}
delay(500);
}
Der Effekt ist der gleiche wie im vorherigen Fall:
Lesen der Informationen von mehreren Sensoren
Der große Vorteil digitaler Sensoren ist, dass sie über ausgefeiltere Mechanismen kommunizieren, die viele Vorteile mit sich bringen. Zum Beispiel können in diesem Fall mehrere Sensoren an denselben Pin angeschlossen werden.
In diesem Test bespreche ich nur eine von mehreren Möglichkeiten
der Verwendung des DS18B20!
Für einen Test kann man also einfach einen zweiten Sensor in denselben Reihen auf der Kontaktplatte anbringen oder die Anschlüsse mit Leitungen versetzen. Ich habe mich aus Gründen der besseren Lesbarkeit für die letztere Variante entschieden:
Wenn du einen weiteren Sensor anschließt, musst du keinen weiteren Widerstand hinzufügen!
Einer für die gesamte Datenlinie ist genug!
Wie bereits erwähnt, muss man, um die Temperatur vom nächsten Sensor zu lesen, sensors.getTempCByIndex(1) aufrufen. Das gesamte Testprogramm sieht also wie folgt aus:
#include
#include
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Übertragung von Informationen an die Bibliothek
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
}
void loop(void) {
sensors.requestTemperatures(); //Temperatur der Sensoren abrufen
Serial.print(" Erste: ");
Serial.println(sensors.getTempCByIndex(0)); //Informationen anzeigen
Serial.print("Zweite: ");
Serial.println(sensors.getTempCByIndex(1)); //Informationen anzeigen
delay(500);
}
In der Praxis funktioniert der Code wie folgt:
Jeder Sensor hat eine Adresse!
Der Anschluss von Sensoren an eine einzige Datenleitung ist möglich, da der Produzent jedem hergestellten Sensor eine eindeutige Adresse zugewiesen hat. Für umfangreichere Projekte lohnt es sich, diese Adressen zu verwenden. Dann können wir unsere Sensoren eindeutig identifizieren.
Die Adresse ist natürlich nicht auf dem Gehäuse zu finden, sondern muss über die Software ausgelesen werden.
Hier können wir das Demoprogramm Datei → Beispiele → OneWire → DS18x20 verwenden, aber wir müssen daran denken, die Sensoranschlussinformationen ganz am Anfang zu ändern, d. h:
OneWire ds(10);
Zu ersetzen durch:
OneWire ds(A5);
Nach der Ausführung des Programms erscheint die folgende Information im Monitor der seriellen Schnittstelle. Ich habe die eindeutigen Sensoradressen, die in hexadezimaler Form gespeichert sind, farblich hervorgehoben:
Verwendung der Sensoradressen des DS18B20
Es wird nun möglich sein, im Programm auf bestimmte Sensoren zu verweisen. Dazu legen wir vor der Funktion setup() ein Objekt vom Typ DeviceAddress mit dem Namen ThermometerExtern an und geben die Adresse unseres Sensors ein:
Achtung! Jeder muss hier die individuelle Adresse seines Sensors angeben!
DeviceAddress ThermometerExtern = { 0x10, 0x7A, 0x31, 0x99, 0x1, 0x8, 0x0, 0x4A };
Im weiteren Verlauf des Programms werden die von diesem Sensor aufgezeichneten Temperaturdaten durch den Aufruf des Befehls sensors.getTempC(ThermometerExtern) abgerufen.
Das gesamte Programm sieht dann wie folgt aus:
#include
#include
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Übertragung von Informationen an die Bibliothek
DeviceAddress ThermometerExtern = { 0x10, 0x7A, 0x31, 0x99, 0x1, 0x8, 0x0, 0x4A };
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
}
void loop(void) {
sensors.requestTemperatures(); //Temperatur der Sensoren abrufen
Serial.print("Aktuelle Temperatur: ");
Serial.println(sensors.getTempC(ThermometerExtern)); //Informationen anzeigen
delay(500);
}
Diese Lösung ist bei einer größeren Anzahl von Sensoren sehr praktisch. Würden wir diese Sensoren z.B. in einer ganzen Wohnung einrichten, wäre es viel einfacher, im Programm Namen wie „ThermometerExtern“, „ThermometerKüche“ usw. zu verwenden.
Das Programm ist dann auch unempfindlich gegenüber Änderungen in der Reihenfolge, in der die Sensoren angeschlossen sind!
Visualisierung der Temperatur auf RGB-LEDs
Schließlich wäre es sinnvoll, unser Thermometer um eine weitere Temperaturanzeige zu erweitern. Die Streifen mit RGB-LEDs, die wir zu Beginn des Kurses kennengelernt haben, sind dafür ideal. Nehmen wir an, dass jede der 8 LEDs 5ºC symbolisiert.
Wenn sie nacheinander von unten her rot aufleuchten, zeigen sie positive Werte an:
Leuchten sie hingegen von oben, also blau, auf, handelt es sich um negative Werte:
Ich habe den RGB-Streifen standardmäßig angeschlossen, wie ich es im zweiten Teil dieses Kurses getan habe. Daher werde ich dies hier nicht beschreiben. Zur Sicherheit stelle ich nur Bilder bereit.
Am Anfang des Programms, das wir zuvor geschrieben haben, müssen wir Informationen über die neue Bibliothek hinzufügen und den RGB-Streifen deklarieren:
#include //Einfügen der Bibliothek
#include
#include
//Konfiguration des Streifens
Adafruit_NeoPixel Streifen = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800);
OneWire oneWire(A5); // Anschluss an A5
DallasTemperature sensors(&oneWire); //Übertragung von Informationen an die Bibliothek
DeviceAddress ThermometerExtern = { 0x10, 0x7A, 0x31, 0x99, 0x1, 0x8, 0x0, 0x4A };
In der Funktion setup() muss die Initialisierung des zuvor deklarierten Streifens hinzugefügt werden:
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
line.begin(); //Initialisierung
}
In der Schleife loop() senden wir nicht nur die Temperaturdaten an den Computer, sondern legen auch eine neue Variable vom Typ int an, in die wir die abgelesene Temperatur überschreiben. Die Variable wird als int deklariert, d. h. als ganze Zahlen, da wir hier ohnehin keine Nachkommastellen verwenden werden.
Eine solche Zahl wird an die Funktion thermometerRGB() übergeben, die für die Steuerung des Streifens zuständig ist:
void loop(void) {
sensors.requestTemperatures(); // Abrufen der Sensortemperatur
Serial.print("Aktuelle Temperatur: ");
Serial.println(sensors.getTempC(ThermometerExtern)); //Informationen anzeigen
int tempStreifen = sensors.getTempC(ThermometerExtern);
thermometerRGB(tempStreifen);
delay(500);
}
Funktion thermometerRGB()
Wir gehen davon aus, dass die angezeigte Mindesttemperatur -40ºC und die Höchsttemperatur +40ºC beträgt. Daher überprüfen wir zu Beginn der Funktion die Bedingungen, ob der erhaltene Wert diesen Bereich nicht überschreitet.
Wenn dies der Fall ist, gehen wir davon aus, dass die Temperatur den Höchstwert erreicht hat:
void thermometerRGB(int Temperatur) {
//Prüfen, ob die Temperatur im richtigen Bereich liegt
if (Temperatur > 40) {
Temperatur = 40;
} else if (Temperatur < -40) {
Temperatur = -40;
}
[...]
}
Nun müssen wir uns mit der Anzeige von Informationen auf den LEDs befassen. Zunächst schalten wir alle LEDs mit dem Befehl Streifen.clear() aus. Dann überprüfen wir, ob der Wert, den wir anzeigen sollen, größer oder gleich Null ist oder nicht. Wir werden auch gleich die Temperatur in Werte umwandeln, die unser Thermometer anzeigen kann (von 1 bis 8 LEDs):
//Streifen Löschen
Streifen.clear();
if (Temperatur >= 0) {
//Für positive Werte
Temperatur = map(Temperatur, 0, 40, 1, 8);
} else {
//Für negative Werte
Temperatur = map(Temperatur, -40, 0, 1, 8);
}
Anschließend verwenden wir die for-Schleife, um die entsprechenden LEDs zum Leuchten zu bringen. Bei positiven Werten wollen wir die LEDs von unten her einschalten, also muss die Schleife von i=0 bis zu dem Wert laufen, der die aktuelle Temperatur beschreibt.
Im Falle eines negativen Wertes wollen wir die LEDs von oben nach unten einschalten, daher ist es am bequemsten, wenn die for-Schleife in umgekehrter Richtung läuft – vom Maximalwert i=8 bis zu dem Wert, der die aktuelle Temperatur angibt. Zum Schluss rufen wir noch die Funktion Streifen.show() auf.
Das fertige Programm sieht also wie folgt aus:
#include //Hinzufügung der Bibliothek
#include
#include
//Konfiguration des Streifens
Adafruit_NeoPixel Streifen = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800);
OneWire oneWire(A5); //Anschluss an A5
DallasTemperature sensors(&oneWire); //Übermittlung von Informationen an die Bibliothek
DeviceAddress ThermometerExtern = { 0x10, 0x7A, 0x31, 0x99, 0x1, 0x8, 0x0, 0x4A };
void setup(void) {
Serial.begin(9600);
sensors.begin(); //Initialisierung der Sensoren
Streifen.begin(); //Initialisierung
}
void loop(void) {
sensors.requestTemperatures(); //Abruf der Sensortemperatur
Serial.print("Aktuelle Temperatur: ");
Serial.println(sensors.getTempC(ThermometerExtern)); //Informationen anzeigen
int tempStreifen = sensors.getTempC(ThermometerExtern);
ThermometerRGB(tempStreifen);
delay(500);
}
void ThermometerRGB(int Temperatur) {
//Prüfen, ob die Temperatur im richtigen Bereich liegt
if (Temperatur > 40) {
Temperatur = 40;
} else if (Temperatur < -40) {
Temperatur = -40;
}
//Streifen löschen
Streifen.clear();
if (Temperatur >= 0) {
//Für positive Werte
Temperatur = map(Temperatur , 0, 40, 1, 8);
int i = 0;
for (i = 0; i < Temperatur; i++) {
Streifen.setPixelColor(i, Streifen.Color(255, 0, 0)); //Diode Nr i leuchtet rot
}
} else {
//Für negative Werte
Temperatur = map(Temperatur, -40, 0, 1, 8);
int i = 0;
for (i = 8; i > Temperatur; i--) {
Streifen.setPixelColor(i, Streifen.Color(0, 0, 255)); //Diode Nr i leuchtet blau
}
}
Streifen.show();
}
Wenn das Programm in Betrieb ist, zeigt der RGB-LED Streifen die aktuelle Temperatur an!
Was habe ich noch nicht über den DS18B20 geschrieben?
In diesem Artikel habe ich nur die Grundkonfiguration für den Einsatz dieser Sensoren besprochen. In der Praxis lassen sie viele weitere Operationen zu. Zum Beispiel ist es möglich, die Auflösung der Temperaturmessung einzustellen.
Es sind auch andere Anschlussmöglichkeiten der Sensoren möglich, z. B. mit nur zwei Leitungen. Dieser Artikel sollte nur einen grundlegenden Überblick über analoge und digitale Thermometer geben, daher wollte ich nicht ins Detail gehen.
Bei Interesse verweise ich auf die Dokumentation für den Sensor und die anderen Beispiele, die in den hier verwendeten Bibliotheken enthalten sind.
Vor- und Nachteile des DS18B20
Im Vergleich zu dem zuvor besprochenen analogen Sensor erwies sich das DS18B20-Thermometer als wesentlich „schwieriger“ zu handhaben. Man muss ihm etwas mehr Zeit widmen. Leider ist es auch teurer als sein Vorgänger.
Der Vorgang der Temperaturmessung erzeugt eine minimale Erwärmung der Sensorstruktur,
daher kann ein häufiges Abfragen der Ergebnisse zu einer Verfälschung der Messungen führen!
Auf der anderen Seite ist dieser Sensor deutlich vielseitiger. Die digitale Übertragung über die 1-Wire-Schnittstelle erweist sich als unverzichtbar, wenn man einen größeren Bereich mit Sensoren abdecken will.
Wenn die Anzahl der Sensoren steigt, brauchen wir die Anzahl der Leitungen nicht zu erhöhen.
Darüber hinaus lassen sich die Thermometer dank eindeutiger Adressen leicht identifizieren.
Zusammenfassung
Die Verwendung der besprochenen Sensoren ist nicht auf den Bau eines einfachen Haushaltsthermometers beschränkt. Die Messung der atmosphärischen Bedingungen ist auch für die Kontrolle des Betriebs komplexerer Geräte nützlich. Bei einem mobilen Roboter kann man zum Beispiel überprüfen, ob die Motoren oder Batterien eine zu hohe Temperatur erreicht haben. Eine solche Diagnose kann das Gerät vor Schäden bewahren!
Im nächsten Teil des Arduino-Kurses werden wir weiter auf atmosphärische Sensoren eingehen. Diesmal geht es jedoch um den beliebten DHT11, einen Temperatur- und Feuchtigkeitssensor in einem Gehäuse.
Bestellen Sie ein Set mit Elementen und beginnen Sie mit dem Lernen in der Praxis! Hier gehts zum Shop >>
Anlagen
LM35 (pdf, 342 KB)
LM35-Dokumentation.
DS18B20 (pdf, 256 KB)
DS18B20 Dokumentation.