Temperatur und Feuchte Sensor DHT11
Der Sensor mißt die Temperatur mit einer Genauigkeit von ± 2°C und die relative Luftfeuchtigkeit mit einer Genauigkeit von ± 5 %. Beide Messwerte werden jeweils in einem Datenpaket über ein Eindraht Protokoll an den Microcontroler übertragen.
Sowohl der Arduino als auch der DHT11 Sensor haben einen Open-Collector Ausgang der auch als Eingang genutzt werden kann. Der im Arduino eingebaute Pullup Widerstand wird gemeinsam genutzt. Um die Übertragung einzuleiten schaltet der Arduino den Ausgang für mindestens 18 ms auf LOW und schaltet dann den Pin auf Eingang um. Wenn der Sensor dieses LOW Signal am Data Pin erkennt, beginnt er die Übertragung der Daten. Er schaltet den Data Pin als Ausgang und legt diesen für 80µs auf LOW und dann wieder für 80 µs auf HIGH. Anschließend folgen 40 Daten bits. Um die Datenbits zu unterscheiden ist für ein 0 Bit der Ausgang 50 µs auf LOW und 28 µs auf HIGH während er für ein 1 Bit 50 µs auf LOW und 70 µs auf HIGH ist. Die 40 Daten Bits teilen sich auf 5 Bytes auf. Feuchtigkeit High-Byte, Feuchtigkeit Low-Byte, Temperatur High-Byte, Temperatur Low-Byte und Prüfsumme.
Aber keine Angst die Ansteuerung des Arduino-Ports muss man nicht selber implementieren, dazu existiert bereits eine fertige Bibliothek, die man in das eigene Programm einbinden kann.
Es gibt zwei Bibliotheken für den Arduino und eine für den ESPx. Ich habe mich für die SimpleDHT entschieden.
Schaltung und Testprogramm:
Wir verbinden den Data-Pin des DHT11 mit Pin 2 am Arduino. Es kann aber auch jeder andere Digital Pin verwendet werden.
#include
const byte dataPin = 2; //Daten pin des DHT11
SimpleDHT11 dht11;
void setup() {
//start der seriellen Schnittstelle um Messwerte auszugeben
Serial.begin(115200);
}
void loop() {
Serial.println("=================================");
Serial.println("Messwerte vom DHT11");
//lesen der Werte
byte temperatur = 0;
byte feuchte = 0;
//wir prüfen ob ein Fehler auftrat
int err = SimpleDHTErrSuccess;
err = dht11.read(dataPin, &temperatur, &feuchte, NULL);
if (err != SimpleDHTErrSuccess) {
Serial.print("Fehler beim Lesen vom DHT11. Fehler = ");
Serial.println(err);
} else {
Serial.print((int)temperatur);
Serial.println(" °C ");
Serial.print((int)feuchte);
Serial.println(" %H ");
}
// warte 1.5 s Der DHT11 mach 1 Messung / s
delay(1500);
}
Zum Testen kann man zum Beispiel den Sensor anhauchen, das sollte die Temperatur und besonders die Feuchte anheben.
Temperatur Sensor DS18B20
Dieser Temperatur Sensor ist ebenfalls ein intelligenter Temperatur Sensor der die Messwerte über ein Eindraht Protokoll in °C übermittelt. Im Gegensatz zum DHT 11 mißt der DS18B20 nur die Temperatur diese aber mit einer höheren Genauigkeit. Die Genauigkeit beträgt ± 0.5 °C in einem Temperaturbereich von -10 bis +85 °C. Die Meßzeit beträgt 0.75s bei 12 Bit Auflösung.
Im Gegensatz zum DTH11 ist das Eindraht-Protokoll wesentlich flexibler. Jeder Sensor hat eine eindeutige Seriennummer, sodass beliebig viele Sensoren am selben Eindraht Bus betrieben werden können. Es gibt auch andere Sensoren die das gleiche Protokoll benützen, die dann alle über einen Bus angesteuert werden können.
Über ein Such Kommando kann der Microcontroler nach der Initialisierung ermitteln welche Sensoren am Bus angeschlossen sind. Die eindeutige Seriennummer enthält auch eine Information über den Typ des Sensors um ihn zu identifizieren. Zum Auslesen der Werte muss immer zuerst die Seriennummer gesendet werden, damit nur einer der Sensoren den Bus belegt.
Eine weitere Besonderheit des DS18B20 ist die Möglichkeit die intern benötigte Stromversorgung aus der Datenleitung zu gewinnen (parasitärer Modus), sodass nur eine Zweidraht Verkabelung benötigt wird.
Natürlich stehen für den DS18B20 auch Arduino Bibliotheken zur Verfügung, und zwar eine für das Eindraht Protokoll und eine weitere für den Temperatur Sensor.
Schaltung und Testprogramm
Für die Schaltung verwenden wir zusätzlich eine Siebensegment-Anzeige 4-digit-display um die Temperatur anzuzeigen.
Für das Display brauchen wir ebenfalls eine Library:
Programm:
#include
#include
//Pins für Temperatursensor
const byte bus = 2;
//Pins für Display
const byte takt = 8;
const byte daten = 9;
//Instanzen für die Bibliotheken
OneWire oneWire(bus);
DallasTemperature sensoren(&oneWire);
//Array um Geräteadressen zu speichern
DeviceAddress adressen;
TM1637Display anzeige(takt,daten);
//globale Variable für Minus Zeichen am Display
const uint8_t minus[] = { 0x40 };
const uint8_t plus[] = { 0x00 };
void setup() {
// serielle Schnittstelle starten
Serial.begin(115200);
//Wir ermitteln die Anzah der Sensoren am Eindraht-Bus
sensoren.begin();
Serial.print(sensoren.getDeviceCount(), DEC);
Serial.println(" Sensoren gefunden.");
//Nun prüfen wir ob der Bus im parasitären Modus ist
Serial.print("Parasitärer Modus ist ");
if (sensoren.isParasitePowerMode()) {
Serial.println("EIN");
} else {
Serial.println("AUS");
}
//Nun prüfen wir ob einer der Sensoren am Bus ein Temperatur Sensor ist
if (!sensoren.getAddress(adressen,0)) Serial.println("Kein Temperatursensor vorhanden!");
//adressen anzeigen
Serial.print("Adresse: ");
printAddress(adressen);
Serial.println();
//Nun setzen wir noch die gewünschte Auflösung (9, 10, 11 oder 12 bit)
sensoren.setResolution(adressen, 9);
//Zur Kontrolle lesen wir den Wert wieder aus
Serial.print("Auflösung = ");
Serial.print(sensoren.getResolution(adressen), DEC);
Serial.println();
//Nun schalten wir das Display ein
anzeige.setBrightness(0x0f);
}
// function zumDrucken der Temperatur eines Sensors
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensoren.getTempC(adressen);
Serial.print("Temperatur C: ");
Serial.print(tempC);
Serial.print(" Temperatur F: ");
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Wandelt den Wert in Fahrenheit
//für das Display setzen wir das richtige Vorzeichen
//und geben den Wert dreistellig ab Position 1 aus
if (tempC<0) {
anzeige.setSegments(minus,1,0);
//für negative Temperaturen müssen wir den Wert umkehren
anzeige.showNumberDec(round(tempC*-10),true,3,1);
} else {
anzeige.setSegments(plus,1,0);
anzeige.showNumberDec(round(tempC*10),true,3,1);
}
}
void loop() {
Serial.print("Lese Temperatur ...");
sensoren.requestTemperatures(); // Commando um die Temperaturen auszulesen
Serial.println("Fertig!");
// Nun die Daten ausgeben
printTemperature(adressen);
delay(1000); //wir warten 1 s
}
// function um eine Sensoradresse zu drucken
void printAddress(DeviceAddress adressen)
{
for (uint8_t i = 0; i < 8; i++)
{
if (adressen[i] < 16) Serial.print("0");
Serial.print(adressen[i], HEX);
}
}