Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
CO2-Ampel
- Fragen und Anregungen: ARDUINO@GymSAS.de
Varianten
Arduino mit Z19B-Sensor und
- LEDs
- LEDs und Buzzer
- LEDs, Buzzer und OLED-Anzeige
- LEDs, BUZZER, OLED-Anzeige und SD-Speicher (und UHR)
- LEDs, BUZZER, OLED-Anzeige und WLAN-Anbindung an einen Raspi mit Datenbank und Apache
fertige Ampel - LED mit Buzzer und OLED-Anzeige
Sensorbeschaltung
Programmcode
- Zusammenkopierter Sketch
- mit UHR und SD-Kartenschreiber
- Aufgabe: Reduziere den Programmcode auf ein Minimum
/** * CO2-Messung mit Sensor Typ MHZ19B * Messwerterfassung durch PWM-Signal */ /************************************** * für den Betrieb der OLED-Anzeige * **************************************/ #include "SSD1306AsciiAvrI2c.h" // OLED-Bibliothek #define I2C_ADDRESS_OLED 0x3C // 0X3C+SA0 - 0x3C or 0x3D OLED #define RST_PIN -1 // Define proper RST_PIN if required. OLED #include <SD.h> // In diesem Sketch verwenden wir die <SD.h> library #include "RTClib.h" SSD1306AsciiAvrI2c oled; RTC_DS3231 rtc; File Messdaten; // An dieser Stelle wird die Variable "Messdaten" als File (dts. Datei) deklariert. /************************************************ * für den Betrieb der LED-Anzeige und Summer * ************************************************/ const int summer = 4; const int gruen = 7; const int gelb = 8; const int rot = 9; const int blau = 10; /************************************************ * Alarmstufen * *********************************************/ const int guteLuft = 800; const int mittlereQualitaet = 950; const int schlechteLuft = 1200; const int vielzuvielCO2 = 2000; const int luftAlarm = 2500; /************************************** * für den Betrieb des MH-Z19B * **************************************/ const int pwmpin = 6; // Der Sensor hängt an Pin 6 const int range = 5000; // Der eingestellte Messbereich (0-5000ppm) int ppm_pwm = 0; /************************************** * Festlegung Messintervall * **************************************/ const int schreibPause = 12000; // nächste Messung erst nach 12 Sekunden void setup() { /************************************** * für den Betrieb der OLED-Anzeige * **************************************/ #if RST_PIN >= 0 oled.begin(&Adafruit128x64, I2C_ADDRESS_OLED, RST_PIN); #else // RST_PIN >= 0 oled.begin(&Adafruit128x64, I2C_ADDRESS_OLED); #endif // RST_PIN >= 0 oled.setFont(System5x7); // Call oled.setI2cClock(frequency) to change from the default frequency. oled.clear(); oled.println(" CO2 - Ampel "); oled.println(" ------------"); oled.println(" SAS-Projekt 2020"); /************************************** * für den Betrieb der LED-Anzeige * **************************************/ pinMode(gruen, OUTPUT); pinMode(gelb, OUTPUT); pinMode(rot, OUTPUT); pinMode(blau, OUTPUT); tone(summer,600); delay(2000); ledTest(); Serial.begin(9600); /********************************************************************************************************** * * UHR * **********************************************************************************************************/ if (! rtc.begin()) { Serial.println("Couldn't find RTC"); while (1); } if (rtc.lostPower()) { Serial.println("RTC lost power, lets set the time!"); // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } /********************************************************************************************************** * * SD-Kartenleser - Schreibtest * *********************************************************************************************************/ Serial.println("Initialisiere SD-Karte"); if (!SD.begin(5)) { // Wenn die SD-Karte nicht (!SD.begin) gefunden werden kann, ... Serial.println("Initialisierung fehlgeschlagen!"); // ... soll eine Fehlermeldung ausgegeben werden. .... return; } Serial.println("Initialisierung abgeschlossen"); // ... Ansonsten soll die Meldung "Initialisierung abgeschlossen." ausgegeben werden. /********************************************************************************************************** * * SD-Kartenleser - Lesetest NUN WIRD der bisherige Text AUSGELESEN * *********************************************************************************************************/ Messdaten = SD.open("co2.txt"); // Die Textdatei auf der SD-Karte wird wieder geoeffnet... if (Messdaten) { Serial.println("alte Werte: "); // ... und der Name der Datei wird ausgegeben. while (Messdaten.available()) // Anschließend wird die Datei so lange ausgelesen (while)... { Serial.write(Messdaten.read()); // ... bis keine Daten mehr gefunden werden können. } Messdaten.close(); // Im Anschluss wird die Textdatei wieder geschlossen. } else // Sollte keine Textdatei (also test.txt) gefunden werden können... { Serial.println("Textdatei konnte nicht geoeffnet werden"); // ... erscheint eine Fehlermeldung im seriellen Monitor. } /************************************** * für den Betrieb des MH-Z19B * **************************************/ pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen } // ENDE Setup void loop() { ppm_pwm = readCO2PWM(); // Messung der PWM-Länge mittels einer eigenen Funktion messWertSchreibenSD(); // Messwerte auf die SD-Karte schreiben (blaue LED) oledAnzeige(); // Messwerte auf dem OLED ausgeben delay(schreibPause); // PAUSE: nächste Messungen in 12 Sekunden } /********************************************************************************************************** * * Funktionen zum PWM-Auslese des CO2-Wertes * ***********************************************************************************************************/ int readCO2PWM() { unsigned long th; int ppm_pwm = 0; float pulsepercent; do { th = pulseIn(pwmpin, HIGH, 1004000) / 1000; float pulsepercent = th / 1004.0; // Pulslänge in Prozent (%) ppm_pwm = range * pulsepercent; // PPM-Werte bei gegebenem Range } while (th == 0); // Der gemessene Wert wird an die loop()-Funktion zurückgegeben, return ppm_pwm; // wo er dann ausgegeben wird. } /********************************************************************************************************** * * SD-Schreibprocedur * *********************************************************************************************************/ void messWertSchreibenSD() { Messdaten = SD.open("co2.txt", FILE_WRITE); // An dieser Stelle wird die Messdaten erstellt. if (Messdaten) // Wenn die Messdaten ("co2.txt") gefunden wurde.... { ledSD(); // Schreibanzeige - KEINE SD entfernen Serial.println("Schreibe in Messdaten..."); // Meldung im seriellen Monitor für den Schreibvorgang DateTime now = rtc.now(); // altuelle Zeit auslesen Messdaten.print(now.year(), DEC); Messdaten.print('-'); Messdaten.print(now.month(), DEC); Messdaten.print('-'); Messdaten.print(now.day(), DEC); // im Format 2020-10-13 schreiben Messdaten.print(' '); Messdaten.print(now.hour(), DEC); Messdaten.print(':'); Messdaten.print(now.minute(), DEC); Messdaten.print(':'); Messdaten.print(now.second(), DEC); // im Format 10:35:22 schreiben Messdaten.print(' ' ); Messdaten.print(ppm_pwm); Messdaten.println(" ppm CO2"); Messdaten.close(); // Anschließend wird die Messdaten wieder geschlossen... Serial.println("Abgeschlossen."); // ... und eine erneute Meldung im seriellen Monitor ausgegeben. Serial.println(); } else { // Wenn !keine! Messdaten gefunden werden kann ... Serial.println("Messdaten konnte nicht ausgelesen werden"); // ... erscheint eine Fehlermeldung im seriellen Monitor. } } /********************************************************************************************************** * * OLED-Anzeigeprocedur * *********************************************************************************************************/ void oledAnzeige() { DateTime now = rtc.now(); // altuelle Zeit auslesen oled.clear(); oled.println(" CO2 - Ampel "); oled.println("-------------------"); oled.println(" GYPT-HH "); oled.println("-------------------"); oled.println(" "); oled.print(" CO2 Wert: "); oled.print(ppm_pwm); oled.println(" ppm"); oled.println("-------------------"); oled.print(" "); oled.print(now.hour(), DEC); oled.print(':'); oled.println(now.minute(), DEC); ledRot(); if (ppm_pwm < guteLuft) { ledGruen(); } if (ppm_pwm > mittlereQualitaet) { ledGelb(); } if (ppm_pwm > schlechteLuft) { ledRot(); } if (ppm_pwm > vielzuvielCO2) { ledblau(); } if (ppm_pwm > luftAlarm) { alarm(); } Serial.print("PWM-Messung: "); // Ausgabe der Werte über die serielle USB-Verbindung Serial.print(ppm_pwm); Serial.println(" ppm CO2"); } /************************************************************************************************************ * * LED-Anzeige mit Summer * ***************************************************************************************************************/ void ledTest() { digitalWrite(gruen, HIGH); digitalWrite(gelb, HIGH); digitalWrite(rot, HIGH); digitalWrite(blau, HIGH); noTone(summer); } void ledGruen(){ digitalWrite(gruen, HIGH); digitalWrite(gelb, LOW); digitalWrite(rot, LOW); digitalWrite(blau, LOW); noTone(summer); } void ledGelb(){ digitalWrite(gruen, LOW); digitalWrite(gelb, HIGH); digitalWrite(rot, LOW); digitalWrite(blau, LOW); noTone(summer); } void ledRot(){ digitalWrite(gruen, LOW); digitalWrite(gelb, LOW); digitalWrite(rot, HIGH); digitalWrite(blau, LOW); noTone(summer); } void ledblau(){ digitalWrite(gruen, LOW); digitalWrite(gelb, LOW); digitalWrite(rot, HIGH); digitalWrite(blau, HIGH); delay(100); digitalWrite(blau, LOW); delay(200); digitalWrite(blau, HIGH); delay(200); digitalWrite(blau, LOW); delay(200); noTone(summer); } void alarm(){ digitalWrite(gruen, HIGH); digitalWrite(gelb, HIGH); digitalWrite(rot, HIGH); digitalWrite(blau, HIGH); tone(summer,600); } void ledSD(){ digitalWrite(gruen, LOW); digitalWrite(gelb, HIGH); digitalWrite(rot, LOW); digitalWrite(blau, HIGH); noTone(summer); } void ledAus() { digitalWrite(gruen, LOW); digitalWrite(gelb, LOW); digitalWrite(rot, LOW); digitalWrite(blau, LOW); noTone(summer); }