El siguiente post fue enviado por el lector Miguel Torres Gordo. Después de que Bernd Albrecht comenzara la serie de blogs sobre un tema similar con MQ-2 y DHT22 en ESP8266, aquí hay una alternativa para microcontroladores ATmega328 y sensores MQ-135 / DHT11. ¡Que se divierta leyendo y probando!
Como es muy importante conocer el nivel de saturación del ambiente, por ejemplo, en el lugar de trabajo, busqué en internet un sensor que se pueda utilizar con Arduino para medir el contenido de CO2. Afortunadamente, encontré un sensor que mide la calidad del aire. Se trata del MQ-135, que, como se puede ver en la ficha técnica, puede medir determinadas sustancias, tales como NH3, alcohol, benceno, humo, CO2, etc. Así es como me encontré con este sensor.
Sabiendo que existía la posibilidad de utilizarlo junto con nuestro microcontrolador ATmega328, lo primero que hice fue buscar los límites de seguridad de CO2 en partes por millón (ppm) para viviendas, habitaciones y edificios, que según diversos estudios pueden oscilar entre 400 y 800 ppm. Ahora que ya conocía el sensor adecuado y los límites de seguridad, era el momento de diseñar un proyecto útil que nos mostrara esta información y que además nos informara sobre la temperatura y la humedad.
Por tanto, el objetivo de este proyecto es medir la concentración de CO2 en partes por millón, para mostrar los datos en una pantalla y que nos avise con una señal acústica cuando alcance una concentración peligrosa, además de informarnos sobre la temperatura y la humedad. Para alargar la vida útil de la pantalla, pensé que sería una buena opción instalar tres LEDs de diferentes colores para darnos una información visual rápida sobre el nivel de concentración de CO2 sin tener que necesariamente ver los datos. Una vez instalado todo esto, podemos comenzar a trabajar.
Hardware necesario
El software necesario
- Arduino IDE
- MQ135 Calibration Sketch
- CO2 Monitoring Sketch
- Librería MQ135
- Librería DHT-11
- Librería Wire
- Adafruit_GFX y la librería Adafruit_SSD1306
Descripción del funcionamiento del circuito
El funcionamiento de este circuito es muy sencillo. El sensor MQ-135 mide la concentración de CO2 en partes por millón, y el sensor DHT-11 mide la temperatura y la humedad. Estos tres datos se envían a una pantalla OLED de dos tonos de 0,96 pulgadas para mostrar cada valor durante 3 segundos a intervalos de 1 minuto. La pantalla permanece apagada durante este tiempo. Estos valores de tiempo se pueden configurar. Mientras la pantalla permanece apagada, los tres LEDs nos informan visualmente de los valores de CO2 presentes. El LED verde se enciende cuando la concentración es igual o inferior a 550. El LED amarillo se enciende cuando la concentración está entre 551 y 799 partes por millón de CO2 y el LED rojo se enciende junto con un sonido de zumbido cuando la concentración supera las 799 partes por millón. Estos tres valores también se pueden configurar.
Preparación y ajuste de la referencia de resistencia RZERO para el contenido de CO2 atmosférico
En primer lugar, se debe preparar el sensor MQ-135 para que mida los valores correctos que utilizaremos en el siguiente paso. Para este propósito, el sensor debe funcionar a 5 voltios durante aproximadamente 2 horas cuando es nuevo para eliminar las impurezas producidas durante su fabricación. Después, lo mejor es hacer el ajuste de referencia de la resistencia RZEO en el circuito final, ya que se hace con las tensiones de alimentación y funcionamiento normalmente utilizadas y la medición es óptima.
El objetivo de esta calibración es ajustar la resistencia del nivel de CO2 atmosférico para que el sensor MQ-135 mida una concentración entre 300 y 450 ppm, que corresponde a la concentración normal de este gas en el ambiente. Es muy importante alimentar el sensor de forma independiente con 5 VDC, ya que consume 850 mW.
Cuando todo está conectado, iniciamos el Arduino IDE, cargamos y ejecutamos el sketch "MQ135_calibration.ino". Antes se debe instalar la librería MQ135. Abrimos el monitor serie y vemos la lectura de ppm; tenemos que cambiar el valor de RZERO en el archivo MQ135.h de la carpeta librería del Arduino IDE y guardar hasta que la lectura de ppm sea la que queremos dejar como referencia de trabajo del circuito. El valor a modificar es el valor de color verde.
/// resistencia de calibración a nivel de CO2 atmosférico
/// cambiar este valor hasta que el valor de PPM es 450.
Para realizar el ajuste, se debe cambiar el valor de RZERO, guardar los cambios en el archivo MQ135.h de la librería en su carpeta Arduino IDE y volver a cargar el sketch de calibración, comprobar el nuevo valor de concentración de CO2 en el monitor serie y repetir el procedimiento para ajustar RZERO con el valor que queremos dejar como referencia de la concentración de CO2 en el aire para los límites de aviso en el sketch de nuestro proyecto.
Sketch MQ135_Calibration para el ajuste de RZERO (descargar):
MQ135 Gasser = MQ135(A0);
En t Val;
En t sensorpin = A0;
En t SensorValue = 0;
vacío configurar() {
De serie.Empezar(115200);
pinMode(sensorpin, Aporte);
}
vacío círculo() {
Val = analogead(A0);
De serie.impresión ("RAW =");
De serie.println (Val);
flotador cero = Gasser.basura();
De serie.impresión ("Rzero:");
De serie.println (cero);
flotador ppm = Gasser.GETPPM();
De serie.impresión ("PPM");
De serie.println (ppm);
demora(2000);
}
Cuando hemos leído correctamente la concentración de CO2 en partes por millón, es el momento de cargar el sketch CO2_monitor.ino, que nos proporciona la información sobre esta concentración, la humedad y la temperatura en el lugar donde queremos medir los valores.
Sketch CO2_monitor (descargar):
/ ************* BIBLIOTECAS necesario para el proyecto **************************** /
/ ************* parámetros de la pantalla ********************************** *** ********* /
Adafruit_ssd1306 monitor(Screen_width, Screen_height, &Cable, -1);
/ ****** humedad y la temperatura del sensor de DHT-11 parámetros y variables ***** /
DHT DHT(DHTPIN, DHTTYPE);
flotador t, H;
/ ****************** MQ-135 Sensor parámetros y variables *************** /
MQ135 Gasser = MQ135(A0);
En t Val;
En t sensorpin = A0;
En t SensorValue = 0;
flotador ppm, cero;
/ ***************** LEDs ******************************* *********************
no firmado largo Tiempo_anterior; // contador de tiempo
/ *********************** CONFIGURACIÓN DEL BLOQUE ************************ *************** /
vacío configuración( )
{
De serie.empezar(115200);
DHT.empezar(); // DHT-11 de inicialización
si(!monitor.empezar(SSD1306_SWITCHCAPVCC, 0x3C)) { // pantalla Comprobación presente
De serie.println(F("SSD1306 asignación no se pudo"));
por(;;);
}
demora(2000);
monitor.clearDisplay(); // pantalla de inicialización y
monitor.SetTextColor(BLANCO); // color del texto config
pinMode(sensorPin, APORTE); // MQ-135 datos del PIN
pinMode(led_verde, PRODUCCIÓN);
pinMode(led_amarillo, PRODUCCIÓN);
pinMode(led_rojo, PRODUCCIÓN);
digitalWrite(led_verde, BAJO);
digitalWrite(led_amarillo, BAJO);
digitalWrite(led_rojo, BAJO);
}
/ *********************** BUCLE DE BLOQUE ************************ ************* /
vacío círculo( ) {
t = DHT.readTemperature(); // Leer la temperatura
h = DHT.readHumidity(); // Leer Humedad
si (isnan(h) || isnan(t)) { // Si no son la temperatura y
De serie.println("Fallo de lectura del sensor de DHT !!!"); // lectura de humedad, el mensaje espectáculo para informar
}
val = analogRead(A0); // lectura de CO2
cero = gasSensor.getRZero(); // Valor de calibración del sensor MQ-135
ppm = gasSensor.getPPM(); // Fórmula en la biblioteca para obtener el ppm de CO2
chequeo_led (); // Go y correr a LEDs comprobar método
De serie.impresión( "T =" ); // Mostrar los valores por el puerto serie
De serie.impresión(t);
De serie.impresión("ºC, H =");
De serie.impresión(h);
De serie.impresión( "%, " );
De serie.impresión ("= primas");
De serie.impresión (val);
De serie.impresión ("Rzero:");
De serie.impresión (cero);
De serie.impresión ("Ppm:");
De serie.println (ppm);
demora (1000);
si ( Millis()-tiempo_anterior >= 60000) { // Si el tiempo pasado es más o igual que 60 sg
encendido_pantalla(); // Ejecutar la vuelta en el método de pantalla.
tiempo_anterior = Millis(); // Guardar el tiempo real.
}
}
vacío chequeo_led() {
si (ppm >= 800) { // Si la concentración de CO2 es igual o mayor que 800
digitalWrite(led_rojo, ELEVADO); // Activar el LED de color rojo
tono(8, NOTE_C5, 5000); // sonido del zumbador
monitor.clearDisplay(); // establecer los parámetros de la pantalla para mostrar el valor de PPM
monitor.SetTextSize(2);
monitor.setCursor(7,0);
monitor.impresión("CO2 (PPM):");
monitor.SetTextSize(3);
monitor.setCursor(40,35);
monitor.impresión(ppm,0);
monitor.monitor();
demora(10000);
} demás {
digitalWrite(led_rojo, BAJO);
monitor.clearDisplay();
monitor.monitor(); }
si (ppm >= 551 && ppm <= 799) {
digitalWrite(led_amarillo, ELEVADO); // El turno LED amarillo en si la concentración de CO2
} demás {
digitalWrite(led_amarillo, BAJO); } // es de entre 551 y 799
si (ppm <= 550) {
digitalWrite(led_verde, ELEVADO); // El LED verde a su vez en cuando el CO2
} demás {
digitalWrite(led_verde, BAJO); } // concentración es más baja que 551
}
vacío encendido_pantalla() { // Activar el método de pantalla
monitor.clearDisplay(); // establecer los parámetros de la pantalla y mostrar el valor de PPM
monitor.SetTextSize(2);
monitor.setCursor(7,0);
monitor.impresión("CO2 (PPM):");
monitor.SetTextSize(3);
monitor.setCursor(40,35);
monitor.impresión(ppm,0);
monitor.monitor();
demora(3000);
monitor.clearDisplay(); // Establecer los parámetros de la pantalla y mostrar el valor de la humedad
monitor.SetTextSize(2);
monitor.setCursor(20,0);
monitor.impresión("HUMEDAD:");
monitor.SetTextSize(3);
monitor.setCursor(20,35);
monitor.impresión(h,1);
monitor.setCursor(90,35);
monitor.impresión("%");
monitor.monitor();
demora(3000);
monitor.clearDisplay(); // establecer los parámetros de la pantalla y mostrar el valor de la temperatura
monitor.SetTextSize(2);
monitor.setCursor(40,0);
monitor.impresión("TEMPERATURA:");
monitor.SetTextSize(3);
monitor.setCursor(5,35);
monitor.impresión(t,1);
monitor.setCursor(85,35);
monitor.cp437(cierto);
monitor.escribir(167);
monitor.setCursor(107,35);
monitor.impresión("C");
monitor.monitor();
demora(3000);
monitor.clearDisplay();
monitor.monitor();
}
Gracias a Miguel Torres Gordo por su contribución.
12 comentarios
Georg Franke
Fazit vorweg: Der MQ135 kann kein CO2 (Kohlenstoffdioxid, Kohlendioxid) messen.
Ich habe zunächst auch gehofft und geglaubt, dass der MQ135 dies könnte. Ich hatte aus Laubabfällen im Garten Biogas hergestellt, das mitunter brennbar ist oder nicht. Biogas kann u.a. Methan(brennbar) und CO2 enthalten. Um das Gasgemisch zu analysieren, habe ich einen Gaschromatographen(GC) von CMA gekauft und wollte den MQ135 als Gasdetektor verwenden. Der GC trennt die einzelnen Gaskomponenten und führt sie nacheinander zum Detektor. Das hat bei mir bei allen brennbaren Gasen (z.B. Wasserstoff, Propan, Butan, Alkoholdampf, Azetondampf) funktioniert nur eben nicht mit CO2. Im Nachhinein ist mir auch klar geworden, warum es auch theoretisch gar nicht geht: Der MQ135 besitzt eine SnO2-Schicht zur Detektion reduzierender Substanzen. Dieses SnO2 wird dabei teilweise reduziert und dadurch elektrisch leitfähiger, d.h. der Widerstand sinkt. Leider ist CO2 keine reduzierende Verbindung und kann daher nicht mit dem SnO2 reagieren. In einigen früheren Kommentaren wurde bereits darauf hingewiesen, worauf Miguel Torres auf das Datenblatt verwies. Ich habe das Datenblatt gesehen. In einem Diagramm wird der Zusammenhang zwischen Gaskonzentration verschiedener Gase in ppm und dem Widerstand des MQ135 dargestellt. Meine Lehrer hätten mir wahrscheinlich eine glatte 6 gegeben, In der Legende rechts oben stehen einige Gase: Al R oder AI R soll vermutlich Luft (Air) bedeuten, dann kann man mit etwas Fantasie CO2 und CO erkennen, sowie NH4 (soll vielleicht Ammoniak sein, also NH3), den Rest kann ich mir gar nicht zusammenreimen. Es wurden 3 Messpunkte pro Gas eingezeichnet. Über die Messunsicherheit (Toleranzen), sowie Quelle und Reinheit der verwendeten Gase wurden keine Angaben gemacht. Wie gesagt, wir messen im ppm-Bereich, da wirken sich geringste Verunreinigungen stark auf das Messergebnis aus und gaukeln z. B. beim CO2 etwas vor, was gar nicht vorhanden ist.
Übrigens: Anbieter des MQ135, wie AZ-Delivery oder Reichelt verzichten auf die Nennung von CO2 als detektierbares Gas
Mario Bluhm
Hallo,
Ich habe den MQ-135 am Pico-w.
Habe die PI Daten herunter geladen, angeglichen und er liefert werte. Habe zusätzlich einen DHT-11 angeschlossen.
Jetzt komme ich mit den gelieferten Werten nicht klar. was wird mir angezeigt. Temperatur und Luftfeuchte ist mir klar.
DHT11 Temperature: 22 Humidity: 48
MQ135 RZero: 90.50353 Corrected RZero: 92.92871 Resistance: 56.37128 PPM: 261.504 Corrected PPM: 236.589ppm
Was soll da CO2 sein? Das sollte ein Wert um die 412ppm sein.
Andreas Wolter
@Sirko: könnten Sie bitte so nett sein und dazu schreiben, was aus Ihrer Sicht nicht korrekt ist und was Sie geändert haben?
Ich kann das an den Autoren weiterleiten und wir korrigieren das dann im Beitrag.
Vielen Dank.
Grüße,
Andreas Wolter
AZ-Delivery Blog
Sirko
Das ganze mal etwas Richtiger (achte auf die auswahl dhd 11 oder dht 22)
#include
#include
/* MQ135 + DHT Temp Sensor
Combination of the MQ135 air quality sensor and a DHT11/22 temperature sensor to accurately measure ppm values through the library correction. Uses the Adafruit DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library Written by: https://github.com/Phoenix1747/MQ135*/
#define PIN_MQ135 A2 // MQ135 Analog Input Pin
#define DHTPIN 2 // DHT Digital Input Pin
#define DHTTYPE DHT22 // DHT11 or DHT22, depends on your sensor
MQ135 mq135_sensor(PIN_MQ135);
DHT dht(DHTPIN, DHTTYPE);
float temperature, humidity; // Temp and Humid floats, will be measured by the DHT
void setup() {
dht.begin();Serial.begin(9600);
}
void loop() {
// Check if any reads failed and exit early (to try again). if (isnan(humidity) || isnan(temperature)) { Serial.println(F(“Failed to read from DHT sensor!”)); return; } float rzero = mq135_sensor.getRZero(); float correctedRZero = mq135_sensor.getCorrectedRZero(temperature, humidity); float resistance = mq135_sensor.getResistance(); float ppm = mq135_sensor.getPPM(); float correctedPPM = mq135_sensor.getCorrectedPPM(temperature, humidity); Serial.print("MQ135 RZero: "); Serial.print(rzero); Serial.print("\t Corrected RZero: "); Serial.print(correctedRZero); Serial.print("\t Resistance: "); Serial.print(resistance); Serial.print("\t PPM: "); Serial.print(ppm); Serial.print(“ppm”); Serial.print("\t Corrected PPM: "); Serial.print(correctedPPM); Serial.print(“ppm”); Serial.print( "\t T = " ); Serial.print(temperature); Serial.print("\t ºC, H = "); Serial.print(humidity); Serial.println( "%, " ); delay(10000);humidity = dht.readHumidity();
temperature = dht.readTemperature();
}
Andreas Wolter
@Erik Huber: Danke für den Hinweis. Ich habe das an den Autoren weitergegeben. Wir checken das und ändern das dann.
Grüße,
Andreas Wolter
AZ-Delivery Blog
Erik Huber
Hi, Im Code ist ein Fehler.
#define RZERO 1
Es ist zwar definiert, aber nirgends wird es angewendet. Der Korrekte Befehl lautet daher nicht: MQ135 gasSensor = MQ135;
Sondern: MQ135 gasSensor(A0, RZERO);
Erst dann kann man den RZERO Wert nutzen.
Also, den Wert von RZERO auf 1 lassen, dann 12 Stunden den Sensor an der guten Luft lassen mit Stormversorgung. Danach den RZERO Wert ablesen und den Wert im Code bei "#define RZERO " eintragen. Also nur die “1” mit dem Wert austauschen.
iberotecno
Good work, but the problem is the library. The library author Georg Krocker’s says “The library also provides functions to apply the temperature/humidity correction that is shown in Fig 4 of the datasheet, but I do not trust the datasheet there, so this should not be used for the moment.” Source: https://hackaday.io/project/3475-sniffing-trinket/log/12363-mq135-arduino-library I also tryed with this method and the measures are inaccurate. More inaccurate than measures without temperature and humidity correction. We need another solution.
Miguel Torres
Hello Philipp,
The difference in price of the MQ-135 sensor versus the MHZ-19 is very significant for Arduino projects.
Miguel Torres
According to the data sheet for this sensor, this also measures CO2. I leave a link where it shows the sensitivity for different gases.
https://www.olimex.com/Products/Components/Sensors/Gas/SNS-MQ135/resources/SNS-MQ135.pdf
mi
hmmmm – kann es sein, dass der MQ-135 kein CO2 sondern nur CO misst ?
Philipp Landhäußer
Hallo,
ein sehr guter Bericht aber das Problem ist, dass der MG-135 nur CO misst und kein CO2. Dafür wäre eher der MHZ-19 geeignet.
Mfg
Andreas Waldbrenner
Wäre super, wenn man mit einem Knopfdruck alle Teile im Warenkorb hätte. Oder habe ich diese Funktion übersehen? Andi