Version [93171]
Dies ist eine alte Version von ArduinoBeispielSensorDisplayInterrupt erstellt von ManuelLiebaug am 2019-01-17 17:37:30.
Arduino-Beispielanwendung
In diesem Beispielprojekt sollen mit einem Arduino die Messwerte eines DHT11 Temperatur- und Luftfeuchtigkeitssensors ausgelesen werden und auf einem LC-Display
angezeigt werden. Je nachdem in welchem Bereich sich die Temperatur befindet (<20°C / 20-25°C / >25°C) leuchtet eine von 3 LEDs (blau/grün/rot). Auf dem Display
wird außerdem eine Digitaluhr in der Form 00:00:00 (Stunden:Minuten:Sekunden) angezeigt. Durch das Drücken eines Buttons wird eine Interrupt-Routine ausgelöst,
die das Einstellen der aktuellen Uhrzeit mithilfe eines 4x4-Tastenmoduls erlaubt. Interrupt bedeutet, dass das Programm sofort unterbrochen wird und stattdessen
eine Interrupt-Routine ausgeführt wird. Nach Beendigung der Interrupt-Routine kehrt das Programm wieder zu der Stelle zurück an der es unterbrochen wurde. Die
Messwerte auf dem Display und die Uhrzeit werden im Sekundentakt aktualisiert.
Der verwendete DHT11 ist ein einfacher und kostengünstiger Sensor zur Messung von Temperatur und Luftfeuchtigkeit. In meinem Fall ist er auf einer kleinen
Platine verlötet und wird über 3 Pins verbunden: GND, 5V und ein Pin zum digitalen Auslesen der Messwerte.
Als Display wird ein LCD-Modul 1602 mit 2 Zeilen und 16 Feldern pro Zeile verwendet. Der Kontrast des Displays lässt sich mit einem Potentiometer einstellen.
Die analogen Pins des Arduino können ebenfalls als digitale Pins verwendet werden. Das wird in diesem Fall angewendet, weil die digitalen Pins sonst nicht
ausreichen würden. Die analogen Pins A0 bis A5 können einfach als digitale Pins 14 bis 19 adressiert werden.
Der Button zur Auslösung des Interrupts wird über einen 10k Ohm Widerstand mit 5V verbunden. Der Widerstand ist ein Pull-Up-Widerstand, das bedeutet wenn der
Button nicht gedrückt ist liegt am digitalen Eingang der Wert HIGH an.
In meinem Programm verwende ich Bibliotheken für den Sensor, das Display und das Tastenfeld. Diese stehen nachfolgend zum Download:
SimpleDHT.zip
LiquidCrystal.zip
Keypad.zip
Der Quellcode sieht wie folgt aus:
#include <LiquidCrystal.h> #include <SimpleDHT.h> #include <Keypad.h> LiquidCrystal lcd(13, 12, 11, 10, 9, 8); /* an diesen Pins ist das Display angeschlossen */ byte stunden = 0; byte minuten = 0; byte sekunde_alt = 0; byte sekunde_neu; byte pinDHT11 = 16; /* Pin 16 entspricht Pin A2 */ SimpleDHT11 dht11; byte temperatur; byte luftfeuchtigkeit; /* Das Gradzeichen wird nicht direkt unterstützt, deswegen wird es als eigenes Zeichen hinzugefügt. Dazu wird das Zeichen als Pixelmatrix dargestellt, ein Feld auf dem LCD hat 5 x 8 Pixel. 1 bedeutet der Pixel leuchtet, 0 bedeutet er leuchtet nicht. */ byte grad[8] = {0b00111, 0b00101, 0b00111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000}; /* die Tasten des Tastenfelds als 2-dimensionales Array */ char tasten[4][3] = { {'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'} }; /* Das Tastenfeld hat 8 Pins, jeweils 1 Pin pro Zeile und 1 Pin pro Spalte. Eine Spalte wird in diesem Fall nicht benutzt und deshalb nicht angeschlossen. */ byte zeilenPins[4] = {7, 6, 5, 4}; byte spaltenPins[3] = {2, 1, 0}; Keypad tastenfeld = Keypad(makeKeymap(tasten), zeilenPins, spaltenPins, 4, 3); char gedrueckteTaste; char gedrueckteTaste_2; boolean uhrzeit_einstellen = false; boolean fertig; char ziffern[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; void setup() { /* pinMode(17, OUTPUT); pinMode(18, OUTPUT); pinMode(19, OUTPUT); Diese Programmzeilen werden durch Inline-Assembler ersetzt. Ein Wert wird in das Register r16 geschrieben und an die Adresse 0x07 ausgegeben. Die Nullen in der Binärzahl bedeuten INPUT und die Einsen OUTPUT. */ asm volatile ( "ldi r16,0b00111000\n" "out 0x07,r16\n" ); lcd.clear(); lcd.begin(16, 2); /* 2 Zeilen mit 16 Feldern pro Zeile*/ lcd.createChar(0, grad); /* Das Gradzeichen wird als eigenes Zeichen gespeichert mit Index 0. Später wird es durch Angabe der Indexnummer benutzt. */ /* Pin 3 wird mit einem Interrupt belegt, an den Pin ist ein Button angeschlossen. Durch Drücken des Buttons wird der Interrupt ausgelöst. */ attachInterrupt(digitalPinToInterrupt(3), interrupt, FALLING); } void loop() { sekunde_neu = (millis()/1000) % 60; if (uhrzeit_einstellen) { stunden_einstellen(); minuten_einstellen(); uhrzeit_einstellen = false; } if (sekunde_neu != sekunde_alt) { /* es wird geprüft ob 1 Sekunde vergangen ist */ if (sekunde_neu == 0) { minuten++; } if (minuten == 60) { minuten = 0; stunden++; } if (stunden == 24) { stunden = 0; } /* Ausgabe der Uhrzeit */ lcd.setCursor(0,0); if (stunden < 10) { lcd.print(0); } lcd.print(stunden); lcd.setCursor(2,0); lcd.print(":"); if (minuten < 10) { lcd.print(0); } lcd.print(minuten); lcd.setCursor(5,0); lcd.print(":"); if (sekunde_neu < 10) { lcd.print(0); } lcd.print(sekunde_neu); /* Temperatur und Luftfeuchtigkeit werden vom Sensor gelesen */ dht11.read(pinDHT11, &temperatur, &luftfeuchtigkeit, NULL); if (temperatur < 20) { digitalWrite(17, HIGH); /* blaue LED */ digitalWrite(18, LOW); digitalWrite(19, LOW); } if (temperatur > 19 && temperatur < 26) { digitalWrite(17, LOW); digitalWrite(18, HIGH); /* grüne LED */ digitalWrite(19, LOW); } if (temperatur > 25) { digitalWrite(17, LOW); digitalWrite(18, LOW); digitalWrite(19, HIGH); /* rote LED */ } lcd.setCursor(10, 0); /* Ausgabe des selbst erstellten Zeichens mit dem Index 0, also das Gradzeichen */ lcd.print(temperatur); lcd.write((uint8_t)0); lcd.print("C"); lcd.setCursor(0, 1); lcd.print(luftfeuchtigkeit); lcd.print("% Luftfeucht."); sekunde_alt = sekunde_neu; } } /* dieser Interrupt wird durch Drücken des Buttons ausgelöst*/ void interrupt() { uhrzeit_einstellen = true; } void stunden_einstellen() { lcd.setCursor(0,0); lcd.print("_"); fertig = false; while (!fertig) { gedrueckteTaste = tastenfeld.getKey(); for (int i = 0; i < 2; i++) { if (gedrueckteTaste == ziffern[i]) { stunden = i*10; lcd.setCursor(0,0); lcd.print(i); lcd.setCursor(1,0); lcd.print("_"); while (!fertig) { gedrueckteTaste_2 = tastenfeld.getKey(); for (int k = 0; k < 10; k++) { if (gedrueckteTaste_2 == ziffern[k]) { stunden = stunden + k; lcd.setCursor(1,0); lcd.print(k); fertig = true; } } } } } if (gedrueckteTaste == '2') { /* wenn die erste Ziffer der Stunden 2 ist darf die zweite Ziffer nur 0,1,2 oder 3 sein */ lcd.setCursor(0,0); lcd.print(2); lcd.setCursor(1,0); lcd.print("_"); while (!fertig) { gedrueckteTaste_2 = tastenfeld.getKey(); for (int k = 0; k < 4; k++) { if (gedrueckteTaste_2 == ziffern[k]) { stunden = 20+k; lcd.setCursor(1,0); lcd.print(k); fertig = true; } } } } } } void minuten_einstellen() { lcd.setCursor(3,0); lcd.print("_"); fertig = false; while (!fertig) { gedrueckteTaste = tastenfeld.getKey(); for (int i = 0; i < 6; i++) { if (gedrueckteTaste == ziffern[i]) { minuten = i*10; lcd.setCursor(3,0); lcd.print(i); lcd.setCursor(4,0); lcd.print("_"); while (!fertig) { gedrueckteTaste_2 = tastenfeld.getKey(); for (int k = 0; k < 10; k++) { if (gedrueckteTaste_2 == ziffern[k]) { minuten = minuten + k; lcd.setCursor(4,0); lcd.print(k); fertig = true; } } } } } } }