MQ 系列感測器又稱為半導體式感測器一般都是用二氧化錫(SnO2) 為基材,二氧化錫在清潔空氣中(含80的氮氣20%的氧氣與少許CO2)導電率非常低,氧化物特點就是本身的活性常低,可長時間保持在同一種狀態,MQ系列感測器壽命可超過20年,二氧化錫(SnO2) 在可燃氣體的催化導電率會升高。MQ系列的結構如下 H 是加溫結構,在加溫後活性氣體通過二氧化錫(SnO2) 時就會改變導電率,只要監測導電率就能判別氣體濃度。
這是Winsensor 出品的 MQ8 感測器的導電率曲線,MQ8是針對氫氣開發出來的感測器,這圖表能看到紅色的空氣不管濃度多高都不會影響MQ8的導電率,氫氣濃度增加時導電率也會跟著升高,其他顏色是所謂的干擾氣體,也就是乙醇、一氧化碳、甲烷等都會干擾到MQ8的導電率。
下圖是MQ8的溫溼度與導電率的曲線,由此表可看出溫度濕度會影響MQ8的導電率。
這張圖表是指出當氣體濃度增加時感測器輸出的電壓值,在這張圖表可發現當氣體濃度增加到300ppm後曲線開始平緩到1500ppm時幾乎快成直線。
這是反應時間曲線。
這是時間變化曲線,把MQ8放在300ppm濃度的氫氣下的輸出電壓變化,由此圖再配合輸出電壓曲線可知MQ8的在300ppm後幾乎不可使用。
MQ 系列雖然在高濃度時超級不準確但是還有以下優點
1.壽命超長
2.使用簡單
3.價格便宜
也就是有以上這些優點MQ系列感測器大量應用在氣體洩漏、煙霧感測警報器,這些本來自然界就不該存在的氣體一但洩漏在空氣中超過200ppm~300ppm就發出警報很多人都能接受,只是要拿來當定量使用幾乎不太可能,以下的程式還是照著Datasheet 的曲線期望解出MQ系列的濃度曲線,注意這只是理論!!在上圖MQ8的輸出曲線可得知當超過1500ppm後的電壓變化輸入到只有10bit A/D 轉換器的Arduino根本沒意義。
// 載入 LCD Library
#include <LiquidCrystal.h>
// LCD 接腳: rs, enable, d4, d5, d6, d7
LiquidCrystal lcd(13, 12, 11, 10 , 9, 8);
/********************* 硬體設定 *************************************/
#define MQ_3_PIN (0) // MQ_3 輸入腳
#define MQ_8_PIN (1) // MQ_8 輸入腳
#define MQ_4_PIN (2) // MQ_4 輸入腳
#define RL_VALUE (5) // RL電阻為 10K歐姆
#define MQ_3_Ro_CLEAN_AIR_FACTOR (1) //MQ_3在乾淨空氣中的電阻/MQ_3_Ro,
#define MQ_8_Ro_CLEAN_AIR_FACTOR (1) //MQ_8在乾淨空氣中的電阻/MQ_8_Ro,
#define MQ_4_Ro_CLEAN_AIR_FACTOR (1) //MQ_4在乾淨空氣中的電阻/MQ_4_Ro,
/*********************** 軟體設定 ************************************/
#define CALIBARAION_SAMPLE_TIMES (50) //設定校準時樣品讀取次數
#define CALIBRATION_SAMPLE_INTERVAL (100) //設定較準時每次讀取採樣的時間間隔(ms)
#define READ_SAMPLE_INTERVAL (50) //測試時用幾次的檢測值的平均值
#define READ_SAMPLE_TIMES (5) //測試時每次取樣的間隔時間(ms)
#define GAS_Alcohol (0)
#define GAS_H2 (1)
#define GAS_CH4 (2)
/*****************************Globals***********************************************/
float AlcoholCurve[3] = {1.7, -0.77,-1}; // 這斜率參考MQ-3的 Datasheet
float MQ_3_Ro = 10; //MQ_3_Ro 的預設值
float H2Curve[3] = {2, -0.6,-1}; // 這斜率參考MQ-8的 Datasheet
float MQ_8_Ro = 10; //MQ_8_Ro 的預設值
float CH4Curve[3] = {2.48, -0.62,-0.4}; // 這斜率參考MQ-4的 Datasheet
float MQ_4_Ro = 10; //MQ_4_Ro 的預設值
void setup()
{
lcd.begin(20, 4); //設定 LCM 為 20*4
lcd.print("Calibrating.."); //LCM 輸出 Calibrating...
MQ_3_Ro = MQ_3Calibration(MQ_3_PIN); //開機校正要確保這段時間內為乾淨空氣
MQ_8_Ro = MQ_8Calibration(MQ_8_PIN); //開機校正要確保這段時間內為乾淨空氣
MQ_4_Ro = MQ_4Calibration(MQ_4_PIN); //開機校正要確保這段時間內為乾淨空氣
}
void loop()
{
lcd.setCursor(0, 0); // LCM 游標移到位置 0,0
lcd.print("Alcohol: "); //顯示文字 Alcohol
lcd.setCursor(8,0); //LCM 游標移到位置 8,0
lcd.print(MQ_3GetGasPercentage(MQ_3Read(MQ_3_PIN)/MQ_3_Ro,GAS_Alcohol )); //顯示測到的Alcohol值
lcd.print(" ppm "); //LCM 顯示 PPm
lcd.setCursor(0, 1); // LCM 游標移到位置 0,0
lcd.print(" H2 : "); //顯示文字 H2
lcd.setCursor(8,1); //LCM 游標移到位置 8,0
lcd.print(MQ_8GetGasPercentage(MQ_8Read(MQ_8_PIN)/MQ_8_Ro,GAS_H2 )); //顯示測到的H2值
lcd.print(" ppm "); //LCM 顯示 PPm
lcd.setCursor(0, 2); // LCM 游標移到位置 0,0
lcd.print(" CH4 : "); //顯示文字 CH4
lcd.setCursor(8,2); //LCM 游標移到位置 8,0
lcd.print(MQ_4GetGasPercentage(MQ_4Read(MQ_4_PIN)/MQ_4_Ro,GAS_CH4 )); //顯示測到的CH4值
lcd.print(" ppm "); //LCM 顯示 PPm
delay(1000);
}
/****************** MQ_Sensor 電阻值換算 ****************************************/
float MQ_3ResistanceCalculation(int raw_adc)
{
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}
float MQ_8ResistanceCalculation(int raw_adc)
{
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}
float MQ_4ResistanceCalculation(int raw_adc)
{
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}
/***************************** MQ_Sensor 校正 ****************************************/
float MQ_3Calibration(int MQ_3_pin)
{
int i;
float val=0;
for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {
val += MQ_3ResistanceCalculation(analogRead(MQ_3_pin));
delay(CALIBRATION_SAMPLE_INTERVAL);
}
val = val/CALIBARAION_SAMPLE_TIMES;
val = val/MQ_3_Ro_CLEAN_AIR_FACTOR;
return val;
}
float MQ_8Calibration(int MQ_8_pin)
{
int i;
float val=0;
for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {
val += MQ_8ResistanceCalculation(analogRead(MQ_8_pin));
delay(CALIBRATION_SAMPLE_INTERVAL);
}
val = val/CALIBARAION_SAMPLE_TIMES;
val = val/MQ_8_Ro_CLEAN_AIR_FACTOR;
return val;
}
float MQ_4Calibration(int MQ_4_pin)
{
int i;
float val=0;
for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {
val += MQ_4ResistanceCalculation(analogRead(MQ_4_pin));
delay(CALIBRATION_SAMPLE_INTERVAL);
}
val = val/CALIBARAION_SAMPLE_TIMES;
val = val/MQ_4_Ro_CLEAN_AIR_FACTOR;
return val;
}
/***************************** MQ_Sensor 讀取*********************************************/
float MQ_3Read(int MQ_3_pin)
{
int i;
float rs=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
rs += MQ_3ResistanceCalculation(analogRead(MQ_3_pin));
delay(READ_SAMPLE_INTERVAL);
}
rs = rs/READ_SAMPLE_TIMES;
return rs;
}
float MQ_8Read(int MQ_8_pin)
{
int i;
float rs=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
rs += MQ_8ResistanceCalculation(analogRead(MQ_8_pin));
delay(READ_SAMPLE_INTERVAL);
}
rs = rs/READ_SAMPLE_TIMES;
return rs;
}
float MQ_4Read(int MQ_4_pin)
{
int i;
float rs=0;
for (i=0;i<READ_SAMPLE_TIMES;i++) {
rs += MQ_4ResistanceCalculation(analogRead(MQ_4_pin));
delay(READ_SAMPLE_INTERVAL);
}
rs = rs/READ_SAMPLE_TIMES;
return rs;
}
/***************************** MQ_Sensor 換算ppm **********************************/
int MQ_3GetGasPercentage(float rs_MQ_3_Ro_ratio, int gas_id)
{
if ( gas_id == GAS_Alcohol) {
return MQ_3GetPercentage(rs_MQ_3_Ro_ratio,AlcoholCurve);
}
return 0;
}
int MQ_8GetGasPercentage(float rs_MQ_8_Ro_ratio, int gas_id)
{
if ( gas_id == GAS_H2) {
return MQ_8GetPercentage(rs_MQ_8_Ro_ratio,H2Curve);
}
return 0;
}
int MQ_4GetGasPercentage(float rs_MQ_4_Ro_ratio, int gas_id)
{
if ( gas_id == GAS_CH4) {
return MQ_4GetPercentage(rs_MQ_4_Ro_ratio,CH4Curve);
}
return 0;
}
/***************************** 計算RS MQ_Ro 百分比 **********************************/
int MQ_3GetPercentage(float rs_MQ_3_Ro_ratio, float *pcurve)
{
return (pow(10,( ((log(rs_MQ_3_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}
int MQ_8GetPercentage(float rs_MQ_8_Ro_ratio, float *pcurve)
{
return (pow(10,( ((log(rs_MQ_8_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}
int MQ_4GetPercentage(float rs_MQ_4_Ro_ratio, float *pcurve)
{
return (pow(10,( ((log(rs_MQ_4_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}
上傳後就會顯示個感測器的值,注意這是沒校正過的只能當參考 !!
當然還有其他氣體感測器可選擇,比如有比較好的高濃度曲線的平面半導體製程MP系列,催化燃燒的MC系列,幾乎可線性輸出的電化學系列,還有使元紅外線的NDIR技術。會常用來半定量使用的是電化學與NDIR技術,只是電化學感測器(NT$ 1500~4000 )壽命只有兩年!!不管有沒有使用出廠後就只有兩年壽命,NDIR技術雖然貴一點(NT$ 3000~5000 ) 可用5年,MQ售價只要 NT$ 50~3002。