Costruisci un sensore di qualità dell'aria con un MQ135 per rilevare fumo e altri gas nocivi con Alexa

In questa sezione ti guideremo nella creazione di un sensore di qualità dell’aria con ESP32 o ESP8266. Potrai poi consultare la qualità dell’aria tramite Amazon Alexa e ricevere una notifica push tramite l’app Sinric Pro quando la qualità dell’aria scende sotto una determinata soglia.

Prerequisiti :

  1. ESP32, ESP8266 x 1.
  2. MQ135 x 1.
  3. Cavetti jumper.

Sinric Pro MQ135 air quality

Breve introduzione all’MQ135

L’MQ135 è un sensore di gas a semiconduttore comunemente usato nelle apparecchiature per il controllo della qualità dell’aria. È sensibile a un’ampia gamma di gas, tra cui ammoniaca, solfuri, benzene e fumo. Il sensore ha due uscite: un’uscita digitale che va a livello alto quando la concentrazione di gas supera una certa soglia e un’uscita analogica che fornisce una tensione proporzionale alla concentrazione di gas.

Il sensore MQ135 richiede un’alimentazione a 5V e assorbe circa 150mA di corrente. L’uscita digitale può essere collegata a un ESP32, ESP8266 o Pico W per misurare la concentrazione di gas.

Come calibrare il sensore MQ135

L’MQ135 non fornisce direttamente i ppm. La sua resistenza (Rs) varia con la concentrazione di gas, e il valore in ppm si calcola dal rapporto tra Rs e R0, la resistenza del sensore in aria pulita. R0 è diversa per ogni sensore, quindi ciascuno va calibrato.

1. Burn-in (una sola volta): metti il sensore all’aperto, dove c’è abbastanza aria fresca (idealmente a 20°C e 33% di umidità secondo il datasheet), e lascialo alimentato per 12-24 ore per eseguire il burn-in e stabilizzarlo.

2. Riscaldamento (a ogni accensione): il sensore ha un riscaldatore. Nei primi minuti dopo l’accensione le letture sono troppo alte, quindi aspetta che si stabilizzino prima di usarle.

3. Misura R0 in aria pulita: con il sensore ancora all’aria fresca, lascia che la libreria TroykaMQ usata in questo tutorial calcoli R0 e la stampi:

#include <TroykaMQ.h>

#define PIN_MQ135 34 // ESP32. Use A0 on ESP8266

MQ135 mq135(PIN_MQ135);

void setup() {
  Serial.begin(115200);
  mq135.calibrate();               // run this in clean air
  Serial.print("Ro = ");
  Serial.println(mq135.getRo());
}

4. Riutilizza il valore: annota la R0 stampata e passala a calibrate(). In questo modo il sensore non ha bisogno di aria fresca a ogni riavvio:

mq135.calibrate(YOUR_RO_VALUE);

Temperatura e umidità influenzano la lettura, quindi esegui la calibrazione in condizioni simili a quelle in cui il sensore verrà usato. L’MQ135 va bene per rilevare che la qualità dell’aria è cambiata, ma non è uno strumento di precisione.

Lettura dell’MQ135 bloccata su valori alti (circa da 3800 a 4095)?

Su un ESP32, analogRead() restituisce valori da 0 a 4095. Una lettura che resta al limite superiore di questo intervallo, o lì vicino, di solito ha una di queste cause:

Scheda tecnica: SNS-MQ135

Cablaggio

Sinric Pro ESP32 ESP8266 MQ135 air quality sensor wiring diagram

MCU Pin A0 Pin VCC
ESP32 34 (Analogico ADC1_CH6) 5V
ESP8266 A0 5V/VIN
Pico W GP26 (ADC0) 5V

Nota: su ESP32, l’ADC2 (GPIO04, GPIO02, GPIO15) è instabile quando il Wi-Fi è in uso.

Verifichiamo che il sensore sia collegato correttamente e funzioni.

#include <TroykaMQ.h> // https://github.com/amperka/TroykaMQ

#if defined(ESP8266)
  #define SENSOR_PIN        A0
#elif defined(ESP32) 
  #define SENSOR_PIN        34
#endif

MQ135 mq135(SENSOR_PIN);

void setup() {
   Serial.begin(9600);
   // before calibrating the sensor, warm it up for 60 seconds calibrate the sensor in clean air
   mq135.calibrate();
   // if you know the resistance of the sensor in clean air
   // you can specify it manually, eg: 160 mq135.calibrate(160);   
   Serial.print("Ro = ");
   Serial.println(mq135.getRo());
}

void loop() {
   // display gas values in ppm
   Serial.print(mq135.readCO2());
   Serial.println("ppm");
   delay(1000);
}

Vedi questo codice su GitHub Gist

Il Monitor seriale di Arduino IDE mostrerà le letture in questo modo:

Sinric Pro mq135 test reading

Rilevare una cattiva qualità dell’aria

#include <TroykaMQ.h> // https://github.com/amperka/TroykaMQ

#if defined(ESP8266)
  #define SENSOR_PIN        A0
#elif defined(ESP32) 
  #define SENSOR_PIN        34
#endif

MQ135 mq135(SENSOR_PIN);

const int AQI_THRESHOLD_SEVERE = 700;
const int AQI_THRESHOLD_VERY_POOR = 600;
const int AQI_THRESHOLD_POOR = 500;
const int AQI_THRESHOLD_MODERATE = 400;

int ppm = 0;

void setup() {
   Serial.begin(9600);
   // before calibrating the sensor, warm it up for 60 seconds calibrate the sensor in clean air
   mq135.calibrate();
   // if you know the resistance of the sensor in clean air
   // you can specify it manually, eg: 160 mq135.calibrate(160);   
   Serial.print("Ro = ");
   Serial.println(mq135.getRo());
}

void loop() {
   ppm = mq135.readCO2();
   
   if (ppm > AQI_THRESHOLD_SEVERE) {
    Serial.print("Air quality is SEVERE!");
   } else if (ppm > AQI_THRESHOLD_VERY_POOR) {
    Serial.print("Air quality is VERY POOR!");
   } else if (ppm > AQI_THRESHOLD_POOR) {
    Serial.print("Air quality is VERY POOR!");
   } else if (ppm > AQI_THRESHOLD_MODERATE) {
    Serial.print("Air quality is MODERATE");
   } else {
    Serial.print("Air quality is GOOD");
   }

   delay(1000);
}

Vedi questo codice su GitHub Gist

Passo 1 : Collegati a Sinric Pro

Passo 1.1 : Creare un tipo di dispositivo personalizzato per il sensore di qualità dell’aria.

Sinric Pro non ha un tipo di dispositivo integrato per un sensore di qualità dell’aria con PPM, quindi creeremo un tipo di dispositivo personalizzato per il sensore di qualità dell’aria usando la funzione Device Template, per ottenere:

  1. Il valore in PPM

  2. La qualità dell’aria: Severe, Very Poor, Poor, Moderate o Good.

Nota: puoi usare la funzione di importazione dei device template descritta più sotto per evitare di creare l’intero template.

Sinric Pro air quality ensor device template

Qui dobbiamo selezionare le funzionalità del nostro sensore di qualità dell’aria. Vogliamo sapere se la qualità dell’aria è Severe, Very Poor, Poor, Moderate o Good. Trasciniamo quindi una capability Range, una Mode e una Push Notification.

Sinric Pro custom device type for MQ135 air quality sensor with range and mode capabilities

Fai clic sul pulsante Configure e imposta le due capability come mostrato sotto.

Sinric Pro moisture sensor template mode and range settings

Fai clic su Save per salvare.

Sinric Pro moisture sensor template mode and range settings

Fai clic su Save per salvare il template.

Ora puoi vedere il template che abbiamo appena creato.

Importare un template esistente?

Se non hai voglia di impostare tutti i valori di Mode e Range, puoi usare la funzione di importazione.

Sinric Pro capacitive soil moisture sensor import template

Incolla questo template:

{
  "name": "Air Quality Sensor",
  "description": "Air Quality Sensor",
  "deviceTypeId": "5ff0b112994fd31b7d5e8065",
  "capabilities": [
    {
      "id": "5ff0b41b994fd31b7d5e8961",
      "mode": {
        "instanceId": "modeInstance1",
        "locale": "en-US",
        "modeName": "Air Quality",
        "nonControllable": true,
        "modeValues": [
          "SEVERE",
          "VERY POOR",
          "POOR",
          "MODERATE",
          "GOOD"
        ]
      }
    },
    {
      "id": "5ff0b45f994fd31b7d5e89c2",
      "range": {
        "instanceId": "rangeInstance1",
        "locale": "en-US",
        "rangeName": "ppm",
        "minimumValue": 1,
        "maximumValue": 1024,
        "precision": 1,
        "unitOfMeasure": "600e7986a7a09c3f3230f8fb",
        "presets": [],
        "nonControllable": true
      }
    },
    {
      "id": "62a707bd9e2f39090569e2d3"
    }
  ]
}

Vedi questo codice su GitHub Gist

Sinric Pro create device alexa

Sinric Pro create device alexa

Sinric Pro copy device id

Sinric Pro copy device id

Passo 2 : Collegati a Sinric Pro

Passo 2.1 Installa la libreria Sinric Pro

Sinric Pro install SinricPro library

Passo 2.2 Installa TroykaMQ

TroykaMQ non è disponibile nel Library Manager di Arduino. Devi quindi scaricarla da https://github.com/amperka/TroykaMQ e copiarla in C:\Users\<your username>\Documents\Arduino\libraries

2.2 Codice completo

AirQualitySensor.h

#ifndef _AIRQUALITYSENSOR_H_
#define _AIRQUALITYSENSOR_H_

#include <SinricProDevice.h>
#include <Capabilities/ModeController.h>
#include <Capabilities/RangeController.h>
#include <Capabilities/PushNotification.h>

class AirQualitySensor 
: public SinricProDevice
, public ModeController<AirQualitySensor>
, public RangeController<AirQualitySensor>
, public PushNotification<AirQualitySensor> {
  friend class ModeController<AirQualitySensor>;
  friend class RangeController<AirQualitySensor>;
  friend class PushNotification<AirQualitySensor>;
public:
  AirQualitySensor(const String &deviceId) : SinricProDevice(deviceId, "AirQualitySensor") {};
};

#endif

sinricpro-air-quality-sensor.ino


// Uncomment the following line to enable serial debug output
//#define ENABLE_DEBUG

#ifdef ENABLE_DEBUG
  #define DEBUG_ESP_PORT Serial
  #define NODEBUG_WEBSOCKETS
  #define NDEBUG
#endif

#include <Arduino.h>
#ifdef ESP8266
  #include <ESP8266WiFi.h>
#endif
#ifdef ESP32
  #include <WiFi.h>
#endif

#include <TroykaMQ.h> // https://github.com/amperka/TroykaMQ
#include <SinricPro.h>
#include "AirQualitySensor.h"

#define WIFI_SSID         ""   // Your WiFI SSID name 
#define WIFI_PASS         ""   // Your WiFi Password.

#define APP_KEY           ""   // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx" (Get it from Portal -> Secrets)
#define APP_SECRET        ""   // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx" (Get it from Portal -> Secrets)
#define DEVICE_ID         ""   // Should look like "5dc1564130xxxxxxxxxxxxxx" (Get it from Portal -> Devices)

#define BAUD_RATE         115200              // Change baudrate to your need (used for serial monitor)
#define EVENT_WAIT_TIME   60000               // send event every 60 seconds


#define BAUD_RATE         115200
#define EVENT_WAIT_TIME   60000               // send event every 60 seconds

#if defined(ESP8266)
  #define SENSOR_PIN        A0
#elif defined(ESP32) 
  #define SENSOR_PIN        34
#endif

MQ135 mq135(SENSOR_PIN);

const int AQI_THRESHOLD_SEVERE = 700;
const int AQI_THRESHOLD_VERY_POOR = 600;
const int AQI_THRESHOLD_POOR = 500;
const int AQI_THRESHOLD_MODERATE = 400;

int ppm = 0;
int lastPPM = 0;
String lastAirQualityLevelStr = "";

AirQualitySensor &airQualitySensor = SinricPro[DEVICE_ID];
 
// ModeController
void updateMode(String mode) {
  airQualitySensor.sendModeEvent("modeInstance1", mode, "PHYSICAL_INTERACTION");
}

// RangeController
void updateRangeValue(int value) {
  airQualitySensor.sendRangeValueEvent("rangeInstance1", value);
}

// PushNotificationController
void sendPushNotification(String notification) {
  airQualitySensor.sendPushNotification(notification);
}

/********* 
 * Setup *
 *********/

void setupAirQualitySensor() {
   // before calibrating the sensor, warm it up for 60 seconds calibrate the sensor in clean air
   mq135.calibrate();
   // if you know the resistance of the sensor in clean air
   // you can specify it manually, eg: 160 mq135.calibrate(160);   
   Serial.print("Ro = ");
   Serial.println(mq135.getRo());
}

void setupSinricPro() {
  SinricPro.onConnected([]{ Serial.printf("[SinricPro]: Connected\r\n"); });
  SinricPro.onDisconnected([]{ Serial.printf("[SinricPro]: Disconnected\r\n"); });
  SinricPro.begin(APP_KEY, APP_SECRET);
};

void setupWiFi() {
  #if defined(ESP8266)
    WiFi.setSleepMode(WIFI_NONE_SLEEP); 
    WiFi.setAutoReconnect(true);
  #elif defined(ESP32)
    WiFi.setSleep(false); 
    WiFi.setAutoReconnect(true);
  #endif

  WiFi.begin(SSID, PASS);
  Serial.printf("[WiFi]: Connecting to %s", SSID);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.printf(".");
    delay(250);
  }
  Serial.printf("connected\r\n");
}

void setup() {
  Serial.begin(BAUD_RATE);
  setupAirQualitySensor();
  setupWiFi();
  setupSinricPro();
}

/********
 * Loop *
 ********/

 void handleAirQualitySensor() {
  if (SinricPro.isConnected() == false) {
    return; 
  }

  static unsigned long last_millis;
  unsigned long        current_millis = millis();
  if (last_millis && current_millis - last_millis < EVENT_WAIT_TIME) return;
  last_millis = current_millis;
    
  ppm = mq135.readCO2();

  Serial.printf("Present ppm: %d\r\n", ppm); 
  
  if (ppm == lastPPM) {
    Serial.printf("PPM did not changed. do nothing...!\r\n");
    return; 
  }

  /* determine air quality level */
  String airQualityLevelStr = "";

  if (ppm > AQI_THRESHOLD_SEVERE) {
    airQualityLevelStr = "SEVERE";
   } else if (ppm > AQI_THRESHOLD_VERY_POOR) {
    airQualityLevelStr = "VERY POOR";
   } else if (ppm > AQI_THRESHOLD_POOR) {
    airQualityLevelStr = "POOR";
   } else if (ppm > AQI_THRESHOLD_MODERATE) {
    airQualityLevelStr = "MODERATE";
   } else {
    airQualityLevelStr = "GOOD";
   }

  /* Update air quality level label if changed */
  if(lastAirQualityLevelStr != airQualityLevelStr) {
    lastAirQualityLevelStr = airQualityLevelStr;
    updateMode(lastAirQualityLevelStr);
  }
  
  delay(500);

  /* update PPM label */
  updateRangeValue(ppm);

  /* send a push notification when air quality level is bad! */
  if (ppm > AQI_THRESHOLD_SEVERE) {
    sendPushNotification("Air quality is SEVERE!");
  } else if (ppm > AQI_THRESHOLD_VERY_POOR) {
    sendPushNotification("Air quality is VERY POOR!");
  } else if (ppm > AQI_THRESHOLD_POOR) {
    sendPushNotification("Air quality is VERY POOR!");
  }

  lastPPM = ppm;  // save to compare next time.
}

void loop() {
  handleAirQualitySensor();
  SinricPro.handle();
}

Vedi questo codice su GitHub Gist

Ora dovresti poter vedere lo stato della qualità dell’aria e il valore in ppm tramite Alexa e l’app Sinric Pro

Alexa, qual è la qualità dell’aria (nome della mode) di air quality sensor (nome del dispositivo)

Alexa, quali sono i ppm (nome del range) di air quality sensor (nome del dispositivo)

Sinric Pro MQ135 air quality sensor in the Alexa app

Sinric Pro MQ135 air quality sensor in the Portal

Passo 3 : Annunci vocali!

✅ Come funziona:

1️⃣ Aggiungi uno Switch in SinricPro (il tuo trigger segreto!)

2️⃣ Crea una routine Alexa che pronunci il tuo messaggio, ad esempio “La qualità dell’aria è pessima!”, quando lo Switch viene acceso

3️⃣ Invia dal tuo codice un evento di stato di accensione per ACCENDERE quello switch

void triggerVoiceAnnouncement() {
    SinricProSwitch& mySwitch = SinricPro[SWITCH_ID];
    mySwitch.sendPowerStateEvent(true);
}

Risoluzione dei problemi

  1. Google Home e SmartThings non sono supportati.

  2. Consulta la nostra pagina Troubleshooting per maggiori dettagli.

Tutorial correlati

Questo documento è open source. Hai trovato un errore di battitura? Crea una issue