PM2.5檢測儀設計

目前市場上的大多數空氣淨化器的傳感器採用煙塵傳感器,例如夏普的GP2Y1010AU, 該傳感器能夠檢測出大於0.8um直徑的灰塵,因爲我們現在空氣中的主要污染物爲PM2.5,所以通過一定的算法能夠大致讓其表示出當前的空氣質量指數。下圖爲CC2540最小系統與GP2Y1010AU組合起來的PM2.5檢測儀,房間裏計算出來的空氣質量指數似乎比官方通報的差一級。


下面是GPY1010AU的採樣電路與採樣方式,該傳感器通過光探測灰塵濃度,需要MCU一個PIN腳產生低脈衝,然後在低脈衝0.32ms的位置進行ADC的轉換。



下圖爲該傳感器的外圍設計電路,也就是上圖中轉接板的電路


通過一個三極管控制第3個引腳產生低脈衝,將第5引腳輸出的煙塵數據通過R14,R15進行分壓以適應MCU ADC的參考電壓。

下面是GPY1010AU在CC2540裸機上的核心代碼

#include<ioCC2540.h>
#include<stdio.h>

#include "gp2y1010au.h"

int dustPin=0;
 
int ledPower=2;
int delayTime=10;
int delayTime2=3;
int offTime=15000;

void delayMicroseconds(unsigned int microSec)
{
  unsigned int i,j;
  for(i=0;i<microSec;i++)
    for(j=0;j<5;j++);
  return;
}

void InitGp2y1010au(void)
{
  ADCCON1 = 0x33;//軟件啓動轉換
  ADCCON3 = 0x30;//AVIN0
  //TR0 = 0x01; //avin, not internal 
  //ATEST = 0x01;
//  ADCCON1 |= 0x40;//軟件啓動轉換
  
   P1DIR |= 0X01;/*output mode*/
}

void ledPowerSet(unsigned char val)
{
  LED_POWER_CTRL = val;
}

unsigned short somkeValAdcRead(void)
{
  unsigned short AdValue=0;
  unsigned char ADCVal_L,ADCVal_H;
  
  //InitGp2y1010au();
  //ADCCON1 = 0x33;
  ADCCON3 = 0x30;//AVIN0
  ADCCON1 = 0x73;
  while(!(ADCCON1 & 0x80));
  ADCVal_L = ADCL;
  ADCVal_H = ADCH;
  AdValue = ADCVal_L >>2;
  AdValue |= ADCVal_H <<6;
  
  return AdValue; 
}
 
unsigned short smokeDetect(void){
  unsigned short dustVal=0;
  
  // ledPower is any digital pin on the arduino connected to Pin 3 on the sensor
  ledPowerSet(1); 
  delayMicroseconds(delayTime);
  dustVal=somkeValAdcRead(); 
  delayMicroseconds(delayTime2);
  ledPowerSet(0); 
  delayMicroseconds(offTime);
 
  //delayMicroseconds(1000);
  /*if (dustVal>36.455)
    Serial.println((float(dustVal/1024)-0.0356)*120000*0.035);*/
  return dustVal;
}


 

>


上面的代碼讀出的是ADC的碼字,需要轉換爲煙塵的濃度,轉換方法參看datasheet提供的煙塵與電壓關係曲線,如下圖所示



轉換的濃度信息爲mg/m3, 在天氣預報中的空氣質量是叫一種空氣質量指數的指標表示的,也就是AQI.

 

空氣質量指數(Air Quality Index,簡稱AQI),是一個用來定量描述空氣質量水平的數值。AQI的取值範圍位於0 – 500 之間。


空氣質量指數是根據各種污染物的濃度值換算出來的。要計算AQI,就需要事先確定各污染物在不同空氣質量水平下的濃度限值。例如,美國環保局(EPA)針對PM2.5的限值定義如下:



AQI的計算公式如下:



其中:
I = 空氣質量指數,即AQI,輸出值;
C = 污染物濃度,輸入值;
Clow= 小於或等於C的濃度限值,常量;
Chigh= 大於或等於C的濃度限值,常量;
Ilow= 對應於Clow的指數限值,常量;
Ihigh= 對應於Chigh的指數限值,常量。


轉換部分的核心代碼如下


unsigned short rawVal2_to_ugPerM3(unsigned short rawVal)
{
  unsigned int ugPerM3Val;
  unsigned int adc_mVolt;
  unsigned long temp;
  
  temp = (long)2300*(long)rawVal;
  adc_mVolt = (long)temp/(long)8192;
  
  temp = (long)10000*(long)(adc_mVolt - 625);//ug * 10times for float compute
  
  ugPerM3Val = temp/5750;
  
  return (unsigned short)ugPerM3Val;
}

unsigned short ugPerM3_to_AQI(unsigned short ugPerM3)
{
  unsigned short AQI;
  unsigned short Clow, Chigh, Ilow, Ihigh;
  
  
  if((ugPerM3>C_LOW_1)&&(ugPerM3<C_HIGH_1))
  {
    Clow= C_LOW_1;
    Chigh = C_HIGH_1;
    Ilow = I_LOW_1;
    Ihigh = I_HIGH_1;
  }
  else if((ugPerM3>C_LOW_2)&&(ugPerM3<C_HIGH_2))
  {
    Clow= C_LOW_2;
    Chigh = C_HIGH_2;
    Ilow = I_LOW_2;
    Ihigh = I_HIGH_2;
  }
  else if((ugPerM3>C_LOW_3)&&(ugPerM3<C_HIGH_3))
  {
    Clow= C_LOW_3;
    Chigh = C_HIGH_3;
    Ilow = I_LOW_3;
    Ihigh = I_HIGH_3;
  }
  else if((ugPerM3>C_LOW_4)&&(ugPerM3<C_HIGH_4))
  {
    Clow= C_LOW_4;
    Chigh = C_HIGH_4;
    Ilow = I_LOW_4;
    Ihigh = I_HIGH_4;
  }
  else if((ugPerM3>C_LOW_5)&&(ugPerM3<C_HIGH_5))
  {
    Clow= C_LOW_5;
    Chigh = C_HIGH_5;
    Ilow = I_LOW_5;
    Ihigh = I_HIGH_5;
  }
  else if((ugPerM3>C_LOW_6)&&(ugPerM3<C_HIGH_6))
  {
    Clow= C_LOW_6;
    Chigh = C_HIGH_6;
    Ilow = I_LOW_6;
    Ihigh = I_HIGH_6;
  }
  else if((ugPerM3>C_LOW_7)&&(ugPerM3<C_HIGH_7))
  {
    Clow= C_LOW_7;
    Chigh = C_HIGH_7;
    Ilow = I_LOW_7;
    Ihigh = I_HIGH_7;
  }
  else//full
  {
    return I_HIGH_7;
  }
  
  AQI = (long)(Ihigh-Ilow)*(long)(ugPerM3-Clow)/(long)(Chigh-Clow) + (long)Ilow;
  
  return AQI;
}

/***************************
          主函數
***************************/
void main(void)
{
  unsigned short smokeVal;
  unsigned short ugPerM3Val;
  unsigned short AQIval;
  //LED端口初始化
  OLED_Init();			//初始化OLED  
  OLED_Clear();
  InitGp2y1010au();
  
  oledDisplayLabel();
  while(1)
  {
    smokeVal = smokeDetect();
    ugPerM3Val = rawVal2_to_ugPerM3(smokeVal);
    AQIval = ugPerM3_to_AQI(ugPerM3Val);
    gp2y1010auDisplay(AQIval);
  }
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章