====== WWW CO2-Messungen BIO ====== ===== Basilikum ===== * [[https://wiki.gymsas.de/doku.php?id=www-fuer-alle:arduino|Arduinos im Unterricht - Informatik, Physik, Technik, ...]] * NW-Projekt Klassenstufe 8 * [[lehrer:nwt:co2-messgeraet|intern: LEHRER]] * [[lehrer:arduino:p48-nano-messbox]| LEHRER: P48-Nano-Messbox]] * {{ :www-fuer-alle:arduino:nw-8-2024-09-09-musterauswertung.ods |Auswertungshilfe}} Fragen und Anregungen an: [[Makerspace@GymSAS.de]] ===== Messgerät ===== * ARDUINO-NANO * 3D-Druckgehäuse {{:www-fuer-alle:arduino:2023-10-26-nw-co2-handmessgeraet.png?400 |}} {{:www-fuer-alle:arduino:2023-10-17-co2-sd-bmp180-oled.png?400 |}} ===== Aufbau ===== {{:www-fuer-alle:arduino:2023-11-29-co2-basikikum-aufbau.jpg?200 |}} ===== Ergebnis ===== ==== Vorversuch ==== {{:www-fuer-alle:01-co2-2023-12-20-nwt8-wachstumslampe.png?800 |}} ====== 48-Stunden-Messung ====== * 2 Stunden Licht * 6 Stunden Dunkelheit * 2 halbe Pflanzen * 1 LED {{:www-fuer-alle:arduino:basilikum-Topf.jpg?200|}}{{:www-fuer-alle:arduino:basilikum-2-teile.jpg?300|}} === CO2-07 === {{:www-fuer-alle:arduino:basilikum-08.png?800|}} === CO2-08 === {{:www-fuer-alle:arduino:basilikum-09.png?800|}} ==== Analyse der Daten: ==== === CO2-Erzeugung (ohne Licht) === Die Daten herausfiltern, in denen die Temperatur konstant und niedrig ist (Lampe aus). In diesen Zeiträumen wird der CO2-Anstieg pro Minute berechnet. === CO2-Aufnahme (mit Licht) === Die Daten herausfiltern, in denen die Temperatur höher ist (Lampe an). In diesen Zeiträumen wird der CO2-Abfall pro Minute berechnet. === Berechnung: === * Die Rate der CO2-Veränderung (ppm pro Minute) für beide Zustände berechnen. * Mit dem Volumen des Gefäßes (5 Liter) wird die CO2-Menge in Mikromol umgerechnet * unter Verwendung der idealen Gasgleichung. === Ergebnisse: === Die CO2-Produktion und -Aufnahme pro Minute in relevanten Einheiten angeben. === Beispiel === {{:www-fuer-alle:arduino:co2-berechnung-01.png?600|}} {{:www-fuer-alle:arduino:co2-berechnung-02.png?600|}} {{:www-fuer-alle:arduino:co2-berechnung-03.png?600|}} {{:www-fuer-alle:arduino:co2-berechnung-04.png?800|}} ====== Nachbau ====== ===== 1. Grundfunktion - UNO mit Sensoren ===== ==== Material ==== * Mikrocontroler ARDUINO UNO ([[https://www.berrybase.de/kompatibler-arduino-uno-mit-atmel-mega-328p-prozessor?utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=21582945112&gclid=Cj0KCQjwjJrCBhCXARIsAI5x66WoZonZllkIIUrHZWs-EI6MgMJrqfKx18rFMD6vKDiGpvgeduENqgwaAhVtEALw_wcB|5 bis 20 EURO]]) * Co2-Sensor [[https://www.winsen-sensor.com/d/files/MH-Z19B.pdf|MHZ 19B (10 bis 40 Euro]] - [[https://www.blikk.it/forum/blog.php?bn=neuemedien_fb&lang=de&id=1575901160|Funktionsweise MHZ-19]] * Erweiterung: Lufttemperatur und Luftdruck * BMP180 (1 bis 4 EURO) * Laptop (zum Programmieren und als Anzeige) * Steckverbindungen * 20 bis 40 EURO (Asien/Europa) ==== Steckplan ==== {{:www-fuer-alle:arduino:uno-mhz-19-bmp180.png?direct&400|}} {{:www-fuer-alle:arduino:nano-mhz-bmp.png?direct&400|}} ==== Code ==== * Co2-Messung mit MHZ-19B über PWM-Kommunikation /********************************************************************************************************* * * MHZ-19B, BMP 180 2025-06-12 * *********************************************************************************************************/ #define ALTITUDE 8.0 // BMP 180 Borgfelde liegt 8 m ueber dem Meer #include // BMP 180 #include // BMP 180 SFE_BMP180 pressure; // BMP 180 - Creating an object pressure float StartZeit, LaufZeit; // Zeitpunkt der Messung String dataString = ""; // Ausgabestring int LeerZeile = 0; /************************************** * 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; /************************************** * für den Betrieb des BMP 180 * **************************************/ double T, P, p0; // Speicher fuer temp, Druck relativer Druck /************************************** * Festlegung Messintervall * **************************************/ const int SchreibPause = 29998; // naechste Messung erst nach ca. 30 Sekunden int WarteZeit; void setup() { StartZeit = millis(); /************************************** * für den Betrieb der Ausgaben * **************************************/ Serial.begin(9600); // Serieller Monitor mit 9600 bit/s /************************************** * für den Betrieb des MH-Z19B * **************************************/ pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen /************************************** * für den Betrieb des BMP-180 * **************************************/ if (!pressure.begin()) { delay(3000); Serial.println("BMP-180 init failed!"); // while(true); // wartet, bis der Sensor sich meldet } Serial.print("Provided altitude: "); Serial.print(ALTITUDE, 0); Serial.println(" meters"); } /********************************************************************************************************* * * H A U P T P R O G R A M M - Loop * *********************************************************************************************************/ void loop() { DatenAuslesen(); SerialAusgabe(); } /******************************************************************************************************** * * Prozedur Datenauslesen * *********************************************************************************************************/ void DatenAuslesen(){ LaufZeit = millis() - StartZeit; ppm_pwm = readCO2PWM(); // Messung der PWM-Länge mittels einer eigenen Funktion DruckUndTemperaturMessung(); } /******************************************************************************************************** * * Ausgabe am seriellen Monitor * *********************************************************************************************************/ void SerialAusgabe(){ Serial.print(LaufZeit/1000,0); Serial.print(" s | "); Serial.print(ppm_pwm); Serial.print(" ppm | "); Serial.print(T,1); Serial.print(" C | "); Serial.print(p0); Serial.print(" hPa | "); Serial.print(P); Serial.print(" hPa Luftdruck gemessen in Borgfelde 6 m ueber NN"); Serial.println(); } /******************************************************************************************************** * * 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. } /******************************************************************************************************** * * Prozedur zum Auslese des BMP-180 (Druck- und Temperatursensor) * ********************************************************************************************************/ void DruckUndTemperaturMessung(){ char status; status = pressure.startTemperature(); if (status != 0) { delay(status); status = pressure.getTemperature(T); if (status != 0) { status = pressure.startPressure(3); if (status != 0) { delay(status); status = pressure.getPressure(P, T); if (status != 0) { p0 = pressure.sealevel(P, ALTITUDE); } } } } } ===== 2. Nano mit Sensoren und OLED-Display ===== ==== Material ==== * Mikrocontroler ARDUINO NANO (oder UNO) ([[https://www.berrybase.de/kompatibler-arduino-uno-mit-atmel-mega-328p-prozessor?utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=21582945112&gclid=Cj0KCQjwjJrCBhCXARIsAI5x66WoZonZllkIIUrHZWs-EI6MgMJrqfKx18rFMD6vKDiGpvgeduENqgwaAhVtEALw_wcB|5 bis 20 EURO]]) * Co2-Sensor [[https://www.winsen-sensor.com/d/files/MH-Z19B.pdf|MHZ 19B (10 bis 40 Euro]] - [[https://www.blikk.it/forum/blog.php?bn=neuemedien_fb&lang=de&id=1575901160|Funktionsweise MHZ-19]] * Breadbord 400 * Lufttemperatur und Luftdruck * BMP180 (1 bis 4 EURO) * OLED zur Datenanzeige * Laptop (zum Programmieren) * Steckverbindungen * 21 bis 45 EURO (Asien/Europa) ==== Schltplan ==== {{ :www-fuer-alle:arduino:co2-bmp180-oled-2025-06-11.png?direct&600 |}} ==== Steckplan ==== {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-1.jpg?direct&200|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-2.jpg?direct&200|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-3.jpg?direct&200|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-4.jpg?direct&200|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-5.jpg?direct&200|}} ==== Code ==== * Co2-Messung über PWM-Kommunikation mit dem Sensor /********************************************************************************************************* * * MHZ-19B, BMP 180 und OLED 2025-06-13 * *********************************************************************************************************/ #include // OLED #include "SSD1306Ascii.h" // OLED #include "SSD1306AsciiWire.h" // OLED #define I2C_ADDRESS 0x3C // OLED SSD1306AsciiWire oled; // OLED #define ALTITUDE 8.0 // BMP 180 Borgfelde liegt 8 m ueber dem Meer #include // BMP 180 #include // BMP 180 SFE_BMP180 pressure; // BMP 180 - Creating an object pressure float StartZeit, LaufZeit; // Zeitpunkt der Messung String dataString = ""; // Ausgabestring int LeerZeile = 0; /************************************** * 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; /************************************** * für den Betrieb des BMP 180 * **************************************/ double T, P, p0; // Speicher fuer temp, Druck relativer Druck /************************************** * Festlegung Messintervall * **************************************/ const int SchreibPause = 29998; // naechste Messung erst nach ca. 30 Sekunden int WarteZeit; void setup() { StartZeit = millis(); /************************************** * für den Betrieb des OLEDs * **************************************/ Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, I2C_ADDRESS); oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); // Loeschen der aktuellen Displayanzeige oled.println("+ Klimakoffer LMU +"); delay(1000); /************************************** * für den Betrieb der Ausgaben * **************************************/ Serial.begin(9600); // Serieller Monitor mit 9600 bit/s /************************************** * für den Betrieb des MH-Z19B * **************************************/ pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen /************************************** * für den Betrieb des BMP-180 * **************************************/ if (!pressure.begin()) { delay(3000); Serial.println("BMP-180 init failed!"); // while(true); // wartet, bis der Sensor sich meldet } Serial.print("Provided altitude: "); Serial.print(ALTITUDE, 0); Serial.println(" meters"); } /********************************************************************************************************* * * H A U P T P R O G R A M M - Loop * *********************************************************************************************************/ void loop() { DatenAuslesen(); DatenAnzeigen(); SerialAusgabe(); delay(5000); } /******************************************************************************************************** * * Prozedur Datenauslesen * *********************************************************************************************************/ void DatenAuslesen(){ LaufZeit = millis() - StartZeit; ppm_pwm = readCO2PWM(); // Messung der PWM-Länge mittels einer eigenen Funktion DruckUndTemperaturMessung(); } /******************************************************************************************************** * * Prozedur Daten auf dem OLED anzeigen * *********************************************************************************************************/ void DatenAnzeigen(){ oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); // Loeschen der aktuellen Displayanzeige oled.print("CO2: "); oled.print(ppm_pwm); oled.println(" ppm"); oled.println("-------------------"); oled.print("Temp. "); oled.print(T,1); oled.println(" C"); oled.println("-------------------"); oled.print("Druck "); oled.print(p0,0); oled.println(" hPa"); oled.println("-------------------"); oled.print("Zeit "); oled.print(LaufZeit/1000,0); oled.println(" s"); oled.println(" MB-2025-06-13"); } /******************************************************************************************************** * * Ausgabe am seriellen Monitor * *********************************************************************************************************/ void SerialAusgabe(){ Serial.print(LaufZeit/1000,0); Serial.print(" s | "); Serial.print(ppm_pwm); Serial.print(" ppm | "); Serial.print(T,1); Serial.print(" C | "); Serial.print(p0); Serial.print(" hPa | "); Serial.print(P); Serial.print(" hPa Luftdruck gemessen in Borgfelde 8 m ueber NN"); Serial.println(); } /******************************************************************************************************** * * 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. } /******************************************************************************************************** * * Prozedur zum Auslese des BMP-180 (Druck- und Temperatursensor) * ********************************************************************************************************/ void DruckUndTemperaturMessung(){ char status; status = pressure.startTemperature(); if (status != 0) { delay(status); status = pressure.getTemperature(T); if (status != 0) { status = pressure.startPressure(3); if (status != 0) { delay(status); status = pressure.getPressure(P, T); if (status != 0) { p0 = pressure.sealevel(P, ALTITUDE); } } } } } ===== 3. Nano mit Sensoren, OLED-Display und SD-Karten-Speicher ===== ==== Material ==== * Mikrocontroler ARDUINO NANO (oder UNO) ([[https://www.berrybase.de/kompatibler-arduino-uno-mit-atmel-mega-328p-prozessor?utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=21582945112&gclid=Cj0KCQjwjJrCBhCXARIsAI5x66WoZonZllkIIUrHZWs-EI6MgMJrqfKx18rFMD6vKDiGpvgeduENqgwaAhVtEALw_wcB|5 bis 20 EURO]]) * Co2-Sensor [[https://www.winsen-sensor.com/d/files/MH-Z19B.pdf|MHZ 19B (10 bis 40 Euro]] - [[https://www.blikk.it/forum/blog.php?bn=neuemedien_fb&lang=de&id=1575901160|Funktionsweise MHZ-19]] * Breadbord 400 * Lufttemperatur und Luftdruck * BMP180 (1 bis 4 EURO) * OLED zur Datenanzeige * SD-Kartenspeicher * Laptop (zum Programmieren) * Steckverbindungen * 22 bis 48 EURO (Asien/Europa) ==== Steckplan ==== {{ :www-fuer-alle:arduino:co2-sd-bmp180-oled-2025-06-11.png?direct&600 |}} ==== Code ==== * Co2-Messung über PWM-Kommunikation mit dem Sensor ===== 4. Nano mit Sensoren, OLED-Display und SD-Karten-Speicher im 3D-Druck-Gehäuse ===== ==== Material ==== * Mikrocontroler ARDUINO NANO (oder UNO) ([[https://www.berrybase.de/kompatibler-arduino-uno-mit-atmel-mega-328p-prozessor?utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=21582945112&gclid=Cj0KCQjwjJrCBhCXARIsAI5x66WoZonZllkIIUrHZWs-EI6MgMJrqfKx18rFMD6vKDiGpvgeduENqgwaAhVtEALw_wcB|5 bis 20 EURO]]) * Co2-Sensor [[https://www.winsen-sensor.com/d/files/MH-Z19B.pdf|MHZ 19B (10 bis 40 Euro]] - [[https://www.blikk.it/forum/blog.php?bn=neuemedien_fb&lang=de&id=1575901160|Funktionsweise MHZ-19]] * Breadbord 400 * Lufttemperatur und Luftdruck * BMP180 (1 bis 4 EURO) * OLED zur Datenanzeige * SD-Kartenspeicher * Laptop (zum Programmieren) * Steckverbindungen * 22 bis 48 EURO (Asien/Europa) ==== Schaltplan ==== {{ :www-fuer-alle:arduino:co2-sd-bmp180-oled-2025-06-11.png?direct&600 |}} ==== Steckplan ==== {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-sd-1.jpg?direct&100|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-sd-2.jpg?direct&200|}} {{:www-fuer-alle:arduino:nano-mhz-bmp-oled-sd-3.jpg?direct&300|}} ==== Code ==== * Co2-Messung über PWM-Kommunikation mit dem Sensor /********************************************************************************************************* * * SD-Karte, MHZ-19B, BMP 180 und OLED 2025-06-13 * *********************************************************************************************************/ #include // OLED #include "SSD1306Ascii.h" // OLED #include "SSD1306AsciiWire.h" // OLED #define I2C_ADDRESS 0x3C // OLED SSD1306AsciiWire oled; // OLED /********************************************************************************************************* * * SD card datalogger * MOSI - pin 11 * MISO - pin 12 * CLK - pin 13 * CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN) by Tom Igoe * ********************************************************************************************************/ #include // SD-Karte #include // SD-Karte In diesem Sketch verwenden wir die library #define ALTITUDE 8.0 // BMP 180 Borgfelde liegt 8 m ueber dem Meer #include // BMP 180 #include // BMP 180 SFE_BMP180 pressure; // BMP 180 - Creating an object pressure const int chipSelect = 4; // CS-Pin der SD-Karte bool SchreibZugriff = false; // Funktionsfaehigkeit beim Datensichern float StartZeit, LaufZeit; // Zeitpunkt der Messung String dataString = ""; // Ausgabestring int LeerZeile = 0; /************************************** * 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; /************************************** * für den Betrieb des BMP 180 * **************************************/ double T, P, p0; // Speicher fuer temp, Druck relativer Druck /************************************** * Festlegung Messintervall * **************************************/ const int SchreibPause = 29998; // naechste Messung erst nach ca. 30 Sekunden int WarteZeit; void setup() { StartZeit = millis(); /************************************** * für den Betrieb des OLEDs * **************************************/ Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, I2C_ADDRESS); oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); // Loeschen der aktuellen Displayanzeige oled.println("+ Klimakoffer LMU + "); delay(1000); /************************************** * für den Betrieb der Ausgaben * **************************************/ Serial.begin(9600); // Serieller Monitor mit 9600 bit/s Serial.print("Initializing SD card..."); if (!SD.begin(chipSelect)) { // SD-Karte suchen Serial.println("SD-Karte fehlt"); // Keine SD-Karte gefunden SchreibZugriff = false; oled.setFont(System5x7); // Auswahl der Schriftart for (int i=20; i > 0; i--){ oled.clear(); // Loeschen der aktuellen Displayanzeige oled.println(" NWP 2024 "); oled.println(" ----------------------"); oled.println(" "); oled.println(" KEINE SD-Karte "); oled.println(" "); oled.println(" GEFUNDEN!! "); oled.println(" "); oled.println(i); delay(1000); } } else { Serial.println("card initialized."); // alles ok SchreibZugriff = true; } /************************************** * für den Betrieb des MH-Z19B * **************************************/ pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen /************************************** * für den Betrieb des BMP-180 * **************************************/ if (!pressure.begin()) { delay(3000); Serial.println("BMP-180 init failed!"); // while(true); // wartet, bis der Sensor sich meldet } Serial.print("Provided altitude: "); Serial.print(ALTITUDE, 0); Serial.println(" meters"); } /********************************************************************************************************* * * H A U P T P R O G R A M M - Loop * *********************************************************************************************************/ void loop() { DatenAuslesen(); DatenStringErstellen(); DatenSichern(); DatenAnzeigen(); SerialAusgabe(); delay(5000); } /******************************************************************************************************** * * Prozedur Datenauslesen * *********************************************************************************************************/ void DatenAuslesen(){ LaufZeit = millis() - StartZeit; ppm_pwm = readCO2PWM(); // Messung der PWM-Länge mittels einer eigenen Funktion DruckUndTemperaturMessung(); } /******************************************************************************************************** * * Prozedur String mit allen Informationen Zusammenstellen * *********************************************************************************************************/ void DatenStringErstellen(){ // make a string for assembling the data to log: dataString = ""; dataString += String(LaufZeit/1000,0); dataString += String(";s;"); dataString += String(ppm_pwm); dataString += String(";ppm;"); dataString += String(T,1); dataString += String("; C;"); dataString += String(p0); dataString += String(";hPa;"); dataString += String(P); dataString += String(";hPa"); } /******************************************************************************************************** * * Prozedur Daten auf der SD-Karte Sichern * *********************************************************************************************************/ void DatenSichern(){ // open the file. note that only one file can be open at a time, File dataFile = SD.open("nwp-9-1.csv", FILE_WRITE); // so you have to close this one before opening another. if (dataFile) { // if the file is available, write to it: dataFile.println(dataString); dataFile.close(); //Serial.println(dataString); // print to the serial port too: SchreibZugriff = true; } else { // if the file isn't open, pop up an error: Serial.println("error opening nwp-9-1.csv"); SchreibZugriff = false; } } /******************************************************************************************************** * * Prozedur Daten auf dem OLED anzeigen * *********************************************************************************************************/ void DatenAnzeigen(){ oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); // Loeschen der aktuellen Displayanzeige oled.print("CO2: "); oled.print(ppm_pwm); oled.println(" ppm"); oled.println("-------------------"); oled.print("Temp. "); oled.print(T,1); oled.println(" C"); oled.println("-------------------"); oled.print("Druck "); oled.print(p0,0); oled.println(" hPa"); oled.println("-------------------"); oled.print("Zeit "); oled.print(LaufZeit/1000,0); oled.println(" s"); oled.print("SD "); if (SchreibZugriff == true){ oled.print("ok "); } else { oled.print("no "); } oled.println("MB-2025-06-13"); } /******************************************************************************************************** * * Ausgabe am seriellen Monitor * *********************************************************************************************************/ void SerialAusgabe(){ Serial.print(LaufZeit/1000,0); Serial.print(" s | "); Serial.print(ppm_pwm); Serial.print(" ppm | "); Serial.print(T,1); Serial.print(" C | "); Serial.print(p0); Serial.print(" hPa | "); Serial.print(P); Serial.print(" hPa Luftdruck gemessen in Borgfelde 6 m ueber NN"); if (SchreibZugriff == true) { Serial.print(" SD ok"); } else { Serial.print(" SD fehlerhaft"); } Serial.println(); } /******************************************************************************************************** * * 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. } /******************************************************************************************************** * * Prozedur zum Auslese des BMP-180 (Druck- und Temperatursensor) * ********************************************************************************************************/ void DruckUndTemperaturMessung(){ char status; status = pressure.startTemperature(); if (status != 0) { delay(status); status = pressure.getTemperature(T); if (status != 0) { status = pressure.startPressure(3); if (status != 0) { delay(status); status = pressure.getPressure(P, T); if (status != 0) { p0 = pressure.sealevel(P, ALTITUDE); } } } } } ===== 5. Nano mit Sensoren, OLED-Display und SD-Karten-Speicher im 3D-Druck-Gehäuse mit Steckverbindungen ===== ==== Material ==== * Mikrocontroler ARDUINO NANO (oder UNO) ([[https://www.berrybase.de/kompatibler-arduino-uno-mit-atmel-mega-328p-prozessor?utm_source=google&utm_medium=cpc&gad_source=1&gad_campaignid=21582945112&gclid=Cj0KCQjwjJrCBhCXARIsAI5x66WoZonZllkIIUrHZWs-EI6MgMJrqfKx18rFMD6vKDiGpvgeduENqgwaAhVtEALw_wcB|5 bis 20 EURO]]) * Co2-Sensor [[https://www.winsen-sensor.com/d/files/MH-Z19B.pdf|MHZ 19B (10 bis 40 Euro]] - [[https://www.blikk.it/forum/blog.php?bn=neuemedien_fb&lang=de&id=1575901160|Funktionsweise MHZ-19]] * Lufttemperatur und Luftdruck * BMP180 (1 bis 4 EURO) * OLED zur Datenanzeige * SD-Kartenspeicher * Laptop (zum Programmieren) * Steckverbindungen/Platine/direkt gelötet * 3D-Druck (eigener Drucker oder im Makerspace in der Nähe oder ...) * 22 bis 48 EURO (Asien/Europa) * Powerbank (optional) {{:www-fuer-alle:arduino:2023-10-26-nw-co2-handmessgeraet.png?400 |}} ==== Steckplan ==== * Mit Taster {{:www-fuer-alle:arduino:2023-10-17-co2-sd-bmp180-oled.png?400 |}} ==== Code ==== * mit Taster * Co2-Messung über PWM-Kommunikation mit dem Sensor /************************************************** * * SD-Karte, CO2-Sensor, BMP 180 und OLED 2023-10-17 * ***************************************************/ #include // OLED #include "SSD1306Ascii.h" // OLED #include "SSD1306AsciiWire.h" // OLED #define I2C_ADDRESS 0x3C // OLED SSD1306AsciiWire oled; // OLED /* SD card datalogger ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN) by Tom Igoe */ #include // SD-Karte #include // SD-Karte In diesem Sketch verwenden wir die library #define ALTITUDE 8.0 // BMP 180 Borgfelde liegt 8 m ueber dem Meer #include // BMP 180 #include // BMP 180 SFE_BMP180 pressure; // BMP 180 - Creating an object pressure const int Taster = 2; // Der Taster zur OLED-Steuerung wurde an Pin 2 angeschlossen const int chipSelect = 4; // CS-Pin der SD-Karte bool SchreibZugriff = false; // Funktionsfaehigkeit beim Datensichern bool Oledan = true; // Status der OLED-Anzeige bool AnzeigenWechsel = false; // Wurde die Anzeige umgeschaltet float StartZeit, LaufZeit; // Zeitpunkt der Messung String dataString = ""; // Ausgabestring int LeerZeile = 0; volatile int TasterStatus = 0; // Variable die den Status des Taster ausliest, wird der sog. "Vektor" 0 zugewiesen // Taster Anschluss an Pin 2 entspricht dem Vektor 0 (hier der Fall) // Taster Anschluss an Pin 3 entspricht dem Vektor 1 /************************************** * 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; /************************************** * für den Betrieb des BMP 180 * **************************************/ double T, P, p0; //Creating variables for temp, pressure and relative pressure /************************************** * Festlegung Messintervall * **************************************/ const int SchreibPause = 29998; // nächste Messung erst nach ca. 30 Sekunden int WarteZeit; void setup() { StartZeit = millis(); pinMode(Taster, INPUT); // Hier wird der Taster als INPUT definiert attachInterrupt(0, TasterUnterbricht, FALLING); // Hier findet die Einbindung unseres Interrupt-Befehls statt /************************************** * für den Betrieb des OLEDs * **************************************/ Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, I2C_ADDRESS); oled.setFont(System5x7); // Auswahl der Schriftart oled.clear(); // Loeschen der aktuellen Displayanzeige oled.println(" NW-Projekt 2023 "); delay(1000); /************************************** * für den Betrieb der Ausgaben * **************************************/ Serial.begin(9600); // Open serial communications and wait for port to open: Serial.print("Initializing SD card..."); if (!SD.begin(chipSelect)) { // see if the card is present and can be initialized: Serial.println("Card failed, or not present"); // don't do anything more: SchreibZugriff = false; oled.setFont(System5x7); // Auswahl der Schriftart for (int i=20; i > 0; i--){ oled.clear(); // Loeschen der aktuellen Displayanzeige oled.println(" NW-Projekt 2023 "); oled.println(" ---------------------- "); oled.println(" "); oled.println(" KEINE SD-Karte "); oled.println(" "); oled.println(" GEFUNDEN!! "); oled.println(" "); oled.println(i); delay(1000); } } else { Serial.println("card initialized."); // alles ok SchreibZugriff = true; } /************************************** * für den Betrieb des MH-Z19B * **************************************/ pinMode(pwmpin, INPUT); // PWM-Pin auf Eingang setzen /************************************** * für den Betrieb des BMP-180 * **************************************/ if (!pressure.begin()) { Serial.println("BMP-180 init failed!"); //while(true); } Serial.print("Provided altitude: "); Serial.print(ALTITUDE, 0); Serial.println(" meters"); } /********************************************************************************************************** * * H A U P T P R O G R A M M - Loop * ***********************************************************************************************************/ void loop() { // Messen DatenAuslesen(); DatenStringErstellen(); DatenSichern(); if (Oledan == 0) {DatenAnzeigenAus();} else {DatenAnzeigen();} SerialAusgabe(); WarteZeit =0; while (WarteZeit