10. Arduino-Projekt: Temperaturmessung mit digitalem IC DS18B20
Der digitale Temperatursensor DS18B20 ist ein IC (Integrated Circuit), das die Temperaturwerte über einen seriellen Datenbus an den Arduino weitergibt. Laut Datenblatt arbeitet der Sensor in einem Temperaturbereich von -55°C bis +125°C.
Durch die serielle digitale Datenleitung kann der Sensor auch über eine relativ lange Leitung (ein Meter und mehr) ohne Messwertverfälschung angeschlossen werden.
Es gibt im Internet verschiedene "vergossene" Varianten mit Verbindungskabel, z. B. hier: https://www.az-delivery.de:
Quelle: https://www.az-delivery.de
Hardware
Die Verdrahtung des Sensors ist sehr einfach:
Für die Funktion wird der Widerstand R1 (Pullup-Widerstand genannt, weil er die Spannung bei fehlendem Signal auf die Versorgungsspannung hochzieht) benötigt, was im Datenblatt so nicht gleich ersichtlich ist.
Hier der Steckbrettaufbau:
Und so eine reale Verdrahtung:
Programmierung
Der serielle Datenbus (1-Wire-Bus) und das vom Sensor verwendete Protokoll erfordern erheblichen Programmieraufwand, zum Glück kann die Arduino-IDE um externe Zusatzmodule (Libraries) erweitert werden und für den Sensor gibt es eine solche. Es werden folgende Libraries benötigt:
/** * Temperaturmessung mit dem Sensor D18B20 */ // Die benötigten Libraries werden eingebunden #include <OneWire.h> #include <DallasTemperature.h> // Definition des Pin, an dem der Sensor hängt #define SENSOR 9 // Jetzt wird ein OneWire-Instanz mit dem Namen "wire" erzeugt. // Das ist eine Variable, die alle Funktionen der Klasse // OneWire enthält, wie sie in der OneWire-Library definiert ist. // Die Instanz erhält gleich die Pinnumber mitgeteilt an der // der Sensor hängt. Das ist die One-Wire-Bus-Verbindung. OneWire wire(SENSOR); // Jezt wird eine Instanz der Klasse DallasTemperature // erzeugt, wie sie in der gleichnamigen Library definiert // ist. Die Instanz heißt "sensors" und bekommt bei der // Erzeugung eine Referenz (Zeiger) auf die wire-Variable. // Dass es sich um eine Referenz handelt, wird durch das // vorangestellte "&" deutlich gemacht. DallasTemperature sensors(&wire); // Die setup()-Funktion void setup(void) { // Serielle Verbindung initialisieren Serial.begin(9600); // Die Library initialisieren sensors.begin(); } // In der loop()-Funktion werden die Temperaturwerte eingelesen und // über die serielle Schnittstelle ausgegeben. void loop(void) { // Die Sensoren am Bus (es sind auch mehrere möglich!) werden // angewiesen die Temperaturwerte zu eruieren sensors.requestTemperatures(); // Send the command to get temperatures // Nun werden die Temperaturwerte in Grad Celsius vom ersten (und // einzigen) Sensor geholt, der den Index 0 hat. float temperature = sensors.getTempCByIndex(0); // Hier wird geprüft, ob eine sinnvolle Temperatur zurückgegeben // wird oder der Wert -127 (der in der DallasTemperature-Library // als DEVICE_DISCONNECTED_C definiert ist). if(temperature != DEVICE_DISCONNECTED_C) { // anzeige der Temperatur Serial.print("Grad Celsius: "); Serial.println(temperature); } else { // Ausgabe einer Fehlermeldung Serial.println("Error: Die Temperatur kann nicht gelesen werden!"); } }
Einige Erläuterungen:
// Die benötigten Libraries werden eingebunden #include <OneWire.h> #include <DallasTemperature.h>
Damit der Arduino-Sketch Zugriff auf die Funktionen der Libraries hat, müssen diese ins Programm eingebunden werden, was diese beiden Anweisungen bewirken.
// Definition des Pin, an dem der Sensor hängt #define SENSOR 9
Das ist ein Variante zu Definition einer Konstante und wirkt im Wesentlichen wie eine const-Definition.
OneWire wire(SENSOR);
In C++ kann man Objekte definieren, die verschiedene Variablen, Konstanten und Funktionen beinhalten. Wir haben das bei der Klasse "Serial" gesehen. Im Gegensatz zur Serial-Klasse wird bei der OneWire-Klasse aber nicht direkt auf die Funktion in der Klasse zugegriffen, sondern es wird zuerst eine Instanz (Objekt) der Klasse mit dem Namen "wire" definiert. Auf diese Weise könnten auch mehrere unabhängige Instanzen der Klasse "OneWire" definiert werden, z. B. wireOne, wireTwo, was notwendig wäre, wenn mehrere Sensoren am Arduino hingen.
Die Klasseninstanz "wire" erhält die Pinnummer SENSOR (Pin 9) gleich bei der Erzeugung mitgeteilt.
DallasTemperature sensors(&wire);
Genauso ist "sensors" eine Instanz der Klasse "DallasTemperature", die in der gleichnamigen Library definiert ist. Die Instanz "sensors" erhält bei der Erzeugung ebenfalls gleich einen Wert übergeben, der allerdings durch das vorangestellte & etwas Besonderes ist, nämlich eine Referenz oder Zeiger auf eine Klasse. Im speziellen Fall eine Referenz auf die Instanz von "wire".
Referenzen sind nicht die Objekte selber, sondern nur Verweise darauf, ähnlich wie Adressen oder Internet-Links. Die Referenz spart Speicherplatz, da das referenzierte Objekt (hier die Instanz "wire") nur einmal mit allem Drum und Dran im Speicher existiert und die Funktionen der Instanz "sensors" trotzdem darauf zugreifen können.
Kniffliges
1. Modifizieren Sie die Hard- und Software so, dass ein zweiter Sensor desselben Typs angeschlossen werden kann.
2. Kombinieren Sie einen analogen Sensor des Typs TMP36 wie hier beschrieben und vergleichen Sie die Messwerte.
Screenshots wurden mit Fritzing erstellt, falls nicht anders angegeben (https://fritzing.org)
9. Arduino-Projekt: Helligkeitsmessung mit Fotowiderstand
Ein Fotowiderstand, auch LDR - Light Dependend Resistor - genannt, ändert seinen Widerstandswert mit dem einfallenden Licht: Je mehr Licht, desto geringer ist der Widerstand.
Hardware
Wird ein Fotowiderstand wie in der vorgeschlagenen Schaltung unten als Spannungsteiler geschaltet, ist die gemessene Spannung am Teiler (U2) umso größer, je mehr Licht auf den Widerstand fällt, d. h. je geringer sein Wert ist (vgl. die Formel):
Der Steckbrettaufbau kann wie folgt aussehen:
Programmierung
Das folgende Programm misst die Rohwerte der Spannung an A1, d. h. Werte im Bereich von 0 - 1023, denn der Arduino Analog-Digital-Wandler, der für die Messung verwendet wird, hat eine Auflösung von 10 Bit in der Standardeinstellung. Wird als Referenzspannung die Versorgungsspannung von 5V verwendet entspricht das einem Wertebereich von 0V - 5V.
Wir müssen uns mit den Rohwerten begnügen, da in den seltesten Fällen ein Lichtmessgerät (Luxmeter o. Ä.) zum Eichen zur Verfügung steht.
/** * Helligkeitsmessung mit einem Fotowiderstand */ // Pinbezeichnung des analogen Messeingang const byte lightSensor = A1; // In der setup()-Funktion wird die serielle // Schnittstelle zum Anzeigen der Werte initialisiert // und der Pin "lightSensor" auf INPUT geschaltet (braucht es // eigentlich nicht, denn nach dem Reset sind alle // Pins auf INPUT. void setup() { Serial.begin(9600); pinMode(lightSensor,INPUT); } // Im loop() wird die Spannung am Pin "sensor" gemessen // und in eine Tempteraturangabe in °C umgerechnet und // über die serielle Anzeige (USB-Kabel übernimmt diese // Funktion) ausgegeben. void loop() { // Messwert als Rohwert im Bereich 0 - 1023 // einlesen int light = analogRead(lightSensor); // Rohwerte ausgeben Serial.print("Helligkeit: "); Serial.println(light); // und etwas warten für die nächste Messung delay(1000); }
Kniffliges
1. Verändern Sie die Schaltung so, dass die Messlogik umgekehrt funktioniert, d. h. bei weniger Licht steigt der gemessene Wert.
2. Sie können die Schaltung in Kombination mit der für die Albedomessung vorgeschlagenen Temperaturmessung verwendung um die Bestrahlungsleistung der Heizquelle (Lampe) in beiden Versuchen konstant zu halten.
Screenshots wurden mit Fritzing erstellt, falls nicht anders angegeben (https://fritzing.org)