7973| 6
|
[进阶] 你知道什么是AQI吗?PM2.5传感器的正确使用方法 |
最近朋友圈已经被空气污染刷屏了。确实空气的污染已经愈演愈烈,人们对于空气这种日常必需品的关注也已经越来越多。 本着科学的态度,避免为黑而黑(也许我们应该事实确凿的黑。。)特地查了下关于空气质量指数AQI的知识,先科普一下。 科普部分: 一、什么是空气质量指数 环境空气污染物的种类有很多,常见的有二氧化硫(SO2)、二氧化氮(NO2)、一氧化碳(CO)、臭氧(O3)和悬浮颗粒物。悬浮颗粒物中,直径小于等于10μm的称为PM10,直径小于等于2.5μm的称为PM2.5。 环境监测部门每天发布的空气质量报告中,会包含各种污染物的浓度值,比如SO2浓度为20.5μg/m3、PM10浓度为150.8μg/m3、PM2.5浓度为130.7μg/m3等等。但是,人们很难从这么多个抽象的浓度数据中判断出到底当前的空气质量处在什么水平。于是就有人想出了一个办法,将各种不同污染物含量折算成一个统一的指数,这就是空气质量指数。 空气质量指数(Air Quality Index,简称AQI),是一个用来定量描述空气质量水平的数值。AQI的取值范围位于0 – 500 之间。 空气质量指数的值在不同的区间,就代表了不同的空气质量水平。比如0 – 50之间,代表“良好”;51 – 100之间,代表“中等”;101 – 150之间,代表“对敏感人群不健康”……等等。为了更直观起见,每个区间都有一个固定的颜色值与它对应: 这样,只需要根据报告的AQI值,甚至只看颜色,即可直观判断空气质量水平。 二、空气质量指数是怎么算出来的 如前所述,空气质量指数是根据各种污染物的浓度值换算出来的。要计算AQI,就需要事先确定各污染物在不同空气质量水平下的浓度限值。例如,美国环保局(EPA)针对PM2.5的限值定义如下: AQI的计算公式如下: 其中: I = 空气质量指数,即AQI,输出值; C = 污染物浓度,输入值; Clow= 小于或等于C的浓度限值,常量; Chigh= 大于或等于C的浓度限值,常量; Ilow= 对应于Clow的指数限值,常量; Ihigh= 对应于Chigh的指数限值,常量。 参照这个公式,根据污染物浓度C,可以方便地计算出空气质量指数I。比如要计算PM2.5浓度等于68.5μg/m3对应的AQI,查浓度限值表可知,它在65.5和150.4之间。所以Clow = 65.5,Chigh = 150.4,对应的Ilow = 151, Ihigh = 200,套入公式计算: 取整即得AQI=153。各种污染物的AQI值分别算出来后,取数值最大的那个即为最终报告的AQI值。比如SO2浓度为20.5μg/m3,算出来对应的AQI为29;PM10浓度为150.8μg/m3,对应的AQI为98;PM2.5浓度为130.7μg/m3,对应的AQI为189。最终报告的AQI值就是189,而贡献了那个最大值的PM2.5则称为首要污染物。 严格来说,PM2.5对应的AQI是针对24小时平均的PM2.5浓度计算出来的。也就是说,并没有对应于实时PM2.5浓度的AQI。但是为了报告的方便,通常也将实时PM2.5浓度按24小时平均浓度计算出AQI值。这样算有一个假设的前提,就是如果这个浓度持续24小时的话,对应的AQI才成立。 值得一提的是,当污染物浓度超出最高上限时,AQI的值最高也只能是500,因为在这之上的指数是不存在的。这种情况下,称为“爆表”或”Beyond Index”,也就是用空气质量指数已经无法描述这糟糕的空气质量了。某些手机应用上显示的AQI值超过了500,达到了700多,这其实是不正确的,至少是不严谨的。 三、我国的空气质量指数标准 我国目前尚无正式的空气质量指数标准。配合GB 3095-2012的推出,我国环保部制订了一份试行的环境空气质量指数(AQI)技术规定,同样将于2016年1月1日实施。 在这份试行的技术规定中,AQI的级别和美国标准一样分为6个等级,采用相同的颜色标识。各级别对应的AQI值也完全一致。只是每个级别的描述有所不同,从好到差依次称为优、良、轻度污染、中度污染、重度污染和严重污染。但各级别对应的健康影响和建议措施,又基本等同。 此外,计算AQI使用的公式也和美国标准一样,但是每个级别对应的污染物浓度限值是不同的。同样以PM2.5的限值为例,两国标准中规定的浓度限值对比如下: 结合AQI的计算公式可以看出,在PM2.5浓度高于150μg/m3时,两国标准计算出来的AQI基本等同;而在PM2.5浓度低于150μg/m3时,两国标准计算出来的AQI有明显差异。所以有些新闻中会看到美国大使馆对于空气质量的检测AQI要高于我国监测的值,很多新闻工作者由于不清楚这些,认为是中国故意降低了检测到的浓度,其实真实原因是我国的标准和美国不同。我国采用了更加宽松的标准。 例如当PM2.5浓度等于32.5μg/m3时,我国标准计算出的AQI值为47,属于“优”的级别;而按照美国标准计算出来的AQI为93,属于“中等”的级别。又如当PM2.5浓度等于68.5μg/m3时,我国标准计算出的AQI值为92,属于“良”的级别;而按照美国标准计算出来的AQI为153,属于“不健康”的级别。 根据世界卫生组织公布的《空气质量准则》,各国在制订标准的过程中,需要考虑当地条件的限制、能力和公共卫生的优先重点问题,并且以实现最低的颗粒物浓度为目标。从这个角度看,在GB 3095—2012标准中定义较高的浓度限值(即世卫组织的过渡时期目标-1)是允许的、合理的。但这仅指空气质量改善需要达到的目标而言。同样的污染物浓度对人们的健康影响应该认为是一致的,不会因国家而异。 由于我国试行的技术标准中,在浓度限值的设置上与美国标准存在差异,使得同样的污染物浓度换算出来的AQI值偏低。但是另一方面,它规定的AQI级别,和针对各AQI级别给出的健康影响及建议措施又基本上等同于美国标准,这就难免会给人们造成困扰了。比如上面例子中那个PM2.5浓度等于68.5μg/m3的情况,到底是该按照中国标准算出“良”,认为空气质量可以接受,放心外出呢?还是该按照美国标准算出“不健康”,认为对所有人都有健康危害,减少外出呢?这也是目前面临的问题。。。 创客部分: 空气问题如此严重,身为一个创客,能做点什么呢?最简单的最基本的莫过于在家自制一个空气检测仪了。而只做一台在本地显示的模块显得太LOW,于是我决定做一个可以在WEB上随时查看家里PM2.5数据并保存每天数据的监视器。实际制作相当简单,当然只是个范例,没进行包装呢。 材料: WIDO * 1 激光PM2.5传感器 * 1 选用WIDO的原因是因为PM2.5传感器使用的是串口通信,而WIDO正好是一款少有的不需要用串口的Arduino带WIFI的板子,正好试用于我们的应用。现在来看看连线。 可以看出,连线非常简单,只需要简单的插线即可。 下面给出程序使用程序 [mw_shl_code=applescript,true]#include "Arduino.h" #include "serialReadPMValue.h" #define receiveDatIndex 32 uint8_t receiveDat[receiveDatIndex]; //receive data from the air detector module uint16_t PM2_5Value=0; //define PM2.5 value of the air detector module const float Ihigh[7]= {50,100,150,200,300,400,500}; const float Ilow[7] = {0,51,101,151,201,301,401}; const float Chigh[7]= {15.4,40.4,65.4,150.4,250.4,350.4,500.4}; const float Clow[7] = {0,15.5,40.5,65.5,150.5,250.5,350.5}; #include <Adafruit_CC3000.h> #include <ccspi.h> #include <SPI.h> #define Wido_IRQ 7 #define Wido_VBAT 5 #define Wido_CS 10 Adafruit_CC3000 Wido = Adafruit_CC3000(Wido_CS, Wido_IRQ, Wido_VBAT, SPI_CLOCK_DIVIDER); #define WLAN_SECURITY WLAN_SEC_WPA2 #define WLAN_SSID "1207" #define WLAN_PASS "liudao1207" #define TCP_TIMEOUT 3000 //#define CC3000_TINY_DRIVER #define WEBSITE "api.yeelink.net" #define API_key "59a4ea38a9909344b0ebfaff59e58933" uint32_t ip = 0; void setup() { Serial.begin(115200); //set the serial's Baudrate of the air detector module Serial1.begin(9600); //set the serial1's Baudrate of the air detector module Serial.println(F("Hello, CC3000!\n")); /* Initialise the module */ Serial.println(F("\nInitialising the CC3000 ...")); if (!Wido.begin()) { Serial.println(F("Unable to initialise the CC3000! Check your wiring?")); while(1); } char *ssid = WLAN_SSID; /* Max 32 chars */ Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid); if (!Wido.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) { Serial.println(F("Failed!")); while(1); } Serial.println(F("Connected!")); /* Wait for DHCP to complete */ Serial.println(F("Request DHCP")); while (!Wido.checkDHCP()) { delay(100); // ToDo: Insert a DHCP timeout! } } int flag = 7; int AQI = 0; void loop() { int length = serialRead(Serial1,receiveDat,receiveDatIndex,5); int checkSum=checkValue(receiveDat,receiveDatIndex); if(length&&checkSum) { PM2_5Value=transmitPM2_5(receiveDat);//count PM2.5 value of the air detector module if (PM2_5Value>Chigh[6])flag=7; else if (PM2_5Value>Chigh[5])flag=6; else if (PM2_5Value>Chigh[4])flag=5; else if (PM2_5Value>Chigh[3])flag=4; else if (PM2_5Value>Chigh[2])flag=3; else if (PM2_5Value>Chigh[1])flag=2; else if (PM2_5Value>Chigh[0])flag=1; else flag=0; AQI=(Ihigh[flag]-Ilow[flag])*((float)PM2_5Value-Clow[flag])/(Chigh[flag]-Clow[flag])+Ilow[flag]; } static Adafruit_CC3000_Client WidoClient; static unsigned long RetryMillis = 0; static unsigned long uploadtStamp = 0; static unsigned long sensortStamp = 0; if(!WidoClient.connected() && millis() - RetryMillis > TCP_TIMEOUT){ // Update the time stamp RetryMillis = millis(); Serial.println(F("Try to connect the cloud server")); WidoClient.close(); // Get Yeelink IP address Serial.print(F("api.yeelink.net -> ")); while (ip == 0) { if (!Wido.getHostByName(WEBSITE, &ip)) { // Get the server IP address based on the domain name Serial.println(F("Couldn't resolve!")); } delay(500); } Wido.printIPdotsRev(ip); Serial.println(F("")); // Connect to the Yeelink Server WidoClient = Wido.connectTCP(ip, 80); // Try to connect cloud server } if(WidoClient.connected() && millis() - uploadtStamp > 10000){ uploadtStamp = millis(); Serial.print("PM2.5: "); //send PM1.0 data to bluetooth Serial.println(PM2_5Value); Serial.print("AQI: "); //send PM1.0 data to bluetooth Serial.println(AQI); Serial.println(""); int length = 0; char lengthstr[3]; // Create Http data package char httpPackage[60] = ""; strcat(httpPackage,"{\"value\":"); itoa(AQI,httpPackage+strlen(httpPackage),10); // push the data(temp) to the http data package strcat(httpPackage,"}"); length = strlen(httpPackage); // get the length of data package itoa(length,lengthstr,10); // convert int to char array for posting Serial.print(F("Length = ")); Serial.println(length); Serial.println(F("Connected to Yeelink server.")); // Send headers Serial.print(F("Sending headers")); WidoClient.fastrprint(F("POST /v1.1/device/")); WidoClient.fastrprint(F("342563/sensor/381667/datapoints")); WidoClient.fastrprintln(F(" HTTP/1.1")); Serial.print(F(".")); WidoClient.fastrprintln(F("Host: api.yeelink.net")); Serial.print(F(".")); WidoClient.fastrprint(F("U-ApiKey: ")); WidoClient.fastrprintln(API_key); Serial.print(F(".")); WidoClient.fastrprint("Content-Length: "); WidoClient.fastrprintln(lengthstr); WidoClient.fastrprintln(""); Serial.print(F(".")); Serial.println(F(" done.")); // Send data Serial.print(F("Sending data")); WidoClient.fastrprintln(httpPackage); Serial.println(F(" done.")); unsigned long rTimer = millis(); Serial.println(F("Reading Cloud Response!!!\r\n")); while (millis() - rTimer < 2000) { while (WidoClient.connected() && WidoClient.available()) { char c = WidoClient.read(); Serial.print(c); } } delay(1000); // Wait for 1s to finish posting the data stream WidoClient.close(); // Close the service connection RetryMillis = millis(); } }[/mw_shl_code] 下载程序 OK。 接着登陆Yeelink网站 就可以看见我们上传的AQI的值啦。 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed