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 (ohne UHR und SD-Karte)
Sensorbeschaltung
- PWM - Pin 6
- GND - Masse
- Vin - +5V
- HD über einen Taster oder ein Steckkabel an Masse zur Kalibrierung
Messbeispiel
Breadboardvariante
Programmcode
- Zusammenkopierter Sketch
- ACHTUNG: der dieser Sketch ist für die kleinste (billigste) NANO-Variente zur groß.
- 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.
int z = 0; // globale Zaehlvariable für die SD-Kartennutzung in der loop
/************************************************
* 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");
tone(summer,444);
// delay(20);
noTone;
/**************************************
* für den Betrieb der LED-Anzeige *
**************************************/
pinMode(gruen, OUTPUT);
pinMode(gelb, OUTPUT);
pinMode(rot, OUTPUT);
pinMode(blau, OUTPUT);
noTone;
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.
digitalWrite(blau, HIGH);
digitalWrite(blau, LOW);
}
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.
}
digitalWrite(blau, LOW);
/**************************************
* für den Betrieb des MH-Z19B *
**************************************/
pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen
} // ENDE Setup
/***********************************************************************************************************************
*
* LOOP
*
***********************************************************************************************************************/
void loop() {
z = z+1;
ppm_pwm = readCO2PWM(); // Messung der PWM-Länge mittels einer eigenen Funktion
if (z > 4) { // erst die 5. Messung wird gesichert, dann ca. pro Minute eine
messWertSchreibenSD(); // jeden 5. Messwert auf die SD-Karte schreiben (blaue LED)
z = 0; // Zaehler zurueck setzen
}
oledAnzeige(); // Messwerte auf dem OLED ausgeben
delay(schreibPause); // PAUSE: nächste Messungen in 12 Sekunden (ca. 5 Messungen pro Minute)
}
/************************************************************************************************************************
*
* LOOP ENDE
*
************************************************************************************************************************/
/*********************************
* *
* Funktionen und Prozeduren *
* *
*********************************/
/**********************************************************************************************************
*
* 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();
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, LOW);
delay(600);
digitalWrite(blau, HIGH);
delay(100);
digitalWrite(gruen, LOW);
digitalWrite(gelb, LOW);
digitalWrite(rot, LOW);
digitalWrite(blau, LOW);
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);
}





