2022年2月3日 星期四

MQ Sensor - How to get PPM

MQ7 Carbon Monoxide GAS Sensor Module

How to get the value of PPM

近日帶學生研究 MQ-7,我們發現要讀取 MQ-7 的值很容易,就是一個類比訊號,用一個 analogRead(A0) 就可以完成的事,同時我們也知道,讀出來的數據越大,代表空氣中一氧化碳的濃度越高。但接下來,如何從 MQ-7 的電壓值轉換為 PPM,這可就搞死了我。

MQ-7 一氧化碳 CO 氣體感測器
用於家庭、環境的一氧化碳探測裝置。適宜於一氧化碳、煤氣等的探測。
MQ-7 氣體傳感器所使用的氣敏材料是在清潔空氣中電導率較低的二氧化錫 (SnO2)。採用高低溫循環檢測方式低溫(1.5V加熱)檢測一氧化碳,傳感器的電導率隨空氣中一氧化碳氣體濃度增加而增大,高溫(5.0V加熱)清洗低溫時吸附的雜散氣體。使用簡單的電路即可將電導率的變化,轉換為與該氣體濃度相對應的輸出信號。MQ-7 氣體傳感器對一氧化碳的靈敏度高,這種傳感器可檢測多種含一氧化碳的氣體,是一款適合多種應用的低成本傳感器

在我查詢到的資料裡面

https://www.teachmemicro.com/use-mq-7-carbon-monoxide-sensor/

是我比較認真研究的一篇文章。這篇文章中有提到,根據 MQ-7 的 DataSheet,它可以檢測空氣中一氧化碳 20~2000 PPM 的濃度。這是他的靈敏度特性曲線圖:

我們欲將電壓讀數轉換為 ppm,在仔細觀察特性曲線圖之後會發現,這是一個對數圖。它是 Rs/R0 與以 ppm 為單位的氣體濃度的關係圖。 Rs 是傳感器在目標氣體中的電阻,而 R0 是在清潔空氣中的電阻。未來我們的程式碼將依照這關係圖來實作。

其中 F1, x1 和 F0, x0 是我們在圖中可以任意選擇的兩個點。例如:

圈出的兩點近似為:>

F1 = 0.25 , x1 = 10
F0 = 0.065, x0 = 100

因此,使用上面的等式:

或者,以 ppm 為單位的濃度與 RS/R0 之間的關係現在為:

求解 ppm:

在我們可以在程式中使用這個公式之前,我們需要先確定 MQ-7 傳感器的 R0。 這因設備而異,因此需要進行實際測試。

從 log-log 圖中,我們可以看到 RS/R0 在空氣中是恆定的,等於 1。由於根據定義,R0 是傳感器在清潔空氣中的電阻,因此每種氣體只有 RS 變化。

RS 是傳感器電阻,與電阻 R2 形成分壓器(見上圖)。 因此,如果原理圖中的串聯電阻 R2 已知,則可以確定 RS。 大多數電路闆對 R2 使用 2 千歐電阻。

然後我們可以使用下面這段程式碼來獲得 R0:

float sensor_volt;
float RS_gas; 
float R0;
int R2 = 2000;
          
void setup()
{
    Serial.begin(9600);
}
         
void loop()
{
    int sensorValue = analogRead(A0);
    sensor_volt = (float)sensorValue / 1024 * 5.0;
    RS_gas = ((5.0 * R2) / sensor_volt) - R2;
    R0 = RS_gas / 1;
    Serial.print("R0: ");
    Serial.println(R0);
}

一旦確定了 R0,我們就可以使用這個程式碼來顯示 C0 的 ppm 濃度:

float RS_gas = 0;
float ratio = 0;
float sensorValue = 0;
float sensor_volt = 0;
float R0 = 7200.0;
         
void setup()
{
    Serial.begin(9600);
}
         
void loop()
{
    sensorValue = analogRead(A0);
    sensor_volt = sensorValue / 1024 * 5.0;
    RS_gas = (5.0 - sensor_volt) / sensor_volt;
    ratio = RS_gas / R0; //Replace R0 with the value found using the sketch above
    float x = 1538.46 * ratio;
    float ppm = pow(x, -1.709);
    Serial.print("PPM: ");
    Serial.println(ppm);
    delay(1000);
}

上面的網站說明了如何將 MQ7 的電壓轉換為 PPM 的計算過程,可以算是相對完整的學習範例,缺點是必須先用第一隻程式計算出你手上的 MQ7 的 R0 的值。當然在無遠弗屆的網路資源,我又找到一篇 MQ2 和 MQ7 電壓值與 PPM 的轉換公式的文章,網址是:

https://blog.csdn.net/qq_43313535/article/details/106389539

特點是直接把 code 貼出來,觀察這段程式碼後會發現,計算原理跟上面描述的是大同小異。對於想直接把程式碼複製貼上的人來說,是方便多了。底下就是程式碼。

#defines CAL_PPM  10  // 校準環境中 PPM 值
#define RL 10 // RL阻值
static float R0 = 8.00;
    
// 得到 ADC 採樣内部傳感器的值
// 取 10 次,然後平均

vu16 Get_ADCValue_MQ7(void)
{
    u32 val = 0;
    u8 times = 10;
    u8 count;
    
    for(count = 0; count < times; count++)
    {
        val += ADC_ConvertedValue[2];
        delay_ms(5);
    }
    return val / times;
} 
    
// 傳感器校準函數
void MQ7_PPM_Calibration(float RS)
{
        
    R0 = RS / pow(CAL_PPM / 98.322, 1 / -1.458f);
}
     
// 獲取傳感器的值
float MQ7_GetPPM(void)
{
    float Vrl = 3.3f * Get_ADCValue_MQ7() / 4096.f;
    Vrl = ( (float)( (int)( (Vrl + 0.005) * 100 ) ) ) / 100;
    float RS = (3.3f - Vrl) / Vrl * RL;
    // printf("MQ7_VRL = %.2f\n", Vrl);

    if(times_mq < 6000) // 獲取系統執行時間,3s 前進行校準
    {
        MQ7_PPM_Calibration(RS);
    }
        
    float ppm = 98.322f * pow(RS/R0, -1.458f);
    
    return ppm;
}

MQ Sensor Library

研究了這麼多,這才只是一個 MQ-7 傳感器,MQ 系列有將近 10 多個傳感器,若要一個一個研究、編寫程式碼,工程太浩大,於是我就想到了尋找函式庫。經歷了一段時間的上網搜尋,在這裡介紹一個 MQ 系列的通用函式庫,網址是:

https://github.com/miguel5612/MQSensorsLib

這個函式庫為 MQ 傳感器提供了一個統一的庫,該庫允許從 Arduino、Genuino、ESP8266、ESP-32 板輕鬆讀取 MQ 信號,支援的模組包含了 MQ2、MQ3、MQ4、MQ5、MQ6、MQ7、MQ8、MQ9、MQ131、MQ135 ,MQ303A,MQ309A。

我們現在就來說一下這個函式庫的使用方式。

Getting Started
//Include the library
#include <MQUnifiedsensor.h>
/*************** Hardware Related Macros ******************/
#define  Board             ("Arduino UNO")
#define  Pin               (A4)
                           //Analog input 4 of your arduino
/*************** Software Related Macros ******************/
#define  Type              ("MQ-4")
                           //MQ4
#define  Voltage           (5)
#define  ADC_Bit           (10)
                           // For arduino UNO/MEGA/NANO
#define  RatioMQ4CleanAir  (4.4)
                           //RS / R0 = 60 ppm
/*************** Globals **********************************/
//Declare Sensor
MQUnifiedsensor MQ4(Board, Voltage, ADC_Bit, Pin, Type);
// Setup
//_PPM =  a*ratio^b
MQ4.setRegressionMethod("Exponential");
// Configurate the ecuation values to get CH4 concentration
MQ4.setA(1012.7); MQ4.setB(-2.786);
// Value getted on calibration
MQ4.setR0(3.86018237);
// Loop
MQ4.init();
MQ4.update();
float ppmCH4 = MQ4.readSensor();
Wiring

Points you should identify

  • VCC -> 5V Power supply (+) wire
  • GND -> GND Ground (-) wire
  • AO -> Analog Output of the sensor

Data of board that you should have

  • RL Value in KOhms
  • RS/R0 value (From datasheet of your sensor)
    RS/R0 (Clean air - English) -> (Aire puro - Spanish)

Note:RS/R0 is equal to Ratio variable on the program

Arduino Wiring

ESP8266、ESP32 Wiring

User Manual (v2.0) 04.2020

MQSensor Manual

Sensor manufacturers
SensorManufactureURL Datasheet
MQ-2Pololuludatasheet
MQ-3Sparkfundatasheet
MQ-4Sparkfundatasheet
MQ-5Parallaxdatasheet
MQ-6Sparkfundatasheet
MQ-7Sparkfundatasheet
MQ-8Sparkfundatasheet
MQ-9Haoyuelectronicsdatasheet
MQ-131Sensorsportaldatasheet
MQ-135HANWEI Electronicsdatasheet
MQ-303AHANWEI Electronicsdatasheet
MQ-309AHANWEI Electronicsdatasheet

Info of datasheet:folderwebsite

Installation

Clone this repository into your desktop machine

git clone https://github.com/miguel5612/MQSensorsLib

一氧化碳感測器 CO sensor 範例

/*
  MQUnifiedsensor Library - reading an MQ7

  Demonstrates the use a MQ7 sensor.
  Library originally added 01 may 2019
  by Miguel A Califa, Yersson Carrillo, Ghiordy Contreras, Mario Rodriguez
 
  Added example
  modified 23 May 2019
  by Miguel Califa 

  Updated library usage
  modified 26 March 2020
  by Miguel Califa 

  Wiring:
  https://github.com/miguel5612/MQSensorsLib_Docs/blob/master/static/img/MQ_Arduino.PNG
  Please take care, arduino A0 pin represent the analog input configured on #define pin

 This example code is in the public domain.
 Soure: https://github.com/miguel5612/MQSensorsLib
*/

#include <MQUnifiedsensor.h>
MQUnifiedsensor MQ7("Arduino UNO", 5, 10, A0, "MQ-7");

void setup()
{
  
  Serial.begin(9600);

  MQ7.setRegressionMethod(1);
  //_PPM =  a*ratio^b
  MQ7.setA(99.042);
  MQ7.setB(-1.518);
  // Configurate the ecuation values to get CO concentration
  MQ7.init(); 

  Serial.print("Calibrating please wait.");
  float calcR0 = 0;
  for(int i = 1; i<=10; i ++)
  {
    MQ7.update();
    // Update data, the arduino will be read the voltage on the analog pin
    calcR0 += MQ7.calibrate(27.5);
    Serial.print(".");
  }
  MQ7.setR0(calcR0/10);
  Serial.println("  done!.");
  if(isinf(calcR0))
  {
    Serial.println("Warning: Conection issue founded, R0 is infite (Open circuit detected) please check your wiring and supply");
    while(1);
  }
  if(calcR0 == 0)
  {
    Serial.println("Warning: Conection issue founded, R0 is zero (Analog pin with short circuit to ground) please check your wiring and supply");
    while(1);
  }
  MQ7.serialDebug(true);
  
}

void loop()
{
  
  MQ7.update();
  // Update data, the arduino will be read the voltage on the analog pin
  float COppm =MQ7.readSensor();
  // Sensor will read PPM concentration using the model and a and b values setted before or in the setup
  Serial.print("CO= ");
  Serial.print(COppm);
  Serial.println(" ppm");
  delay(500); //Sampling frequency
  
}

參考資料:

  1. 台中市政府環境保護局空氣品質監測網
    台中測站:http://taqm.epb.taichung.gov.tw/TQAMNEWAQITABLE.ASPX
    台中-忠明測站:http://taqm.epb.taichung.gov.tw/aqi/aqiNEW.ASPX?name=2
    中央監測資料:https://airtw.epa.gov.tw/CHT/EnvMonitoring/Central/CentralMonitoring.aspx
  2. https://earth.nullschool.net/#current/chem/surface/level/overlay=cosc/orthographic=-243.45,24.42,3000/loc=120.742,24.209