PM2.5灰尘检测装置灰尘检测 摘要:使用SHARP GP2Y1010灰尘传感器,通过Arduino控制读取灰尘数据,并增加DHT11可以同时进行温湿测量,可将结果显示在1602屏幕上,并可以通过串口接收数据。 缘起 由于近期关于PM2.5的概念比较热,本人也十分好奇到底目前日常的空气中有多少灰尘,另外对某些相关部门(这个部门能干任何事。。。)发布的数据的诚信度没有太多信心;于是谷歌了一下,果然,已经有牛人这么干过了。既然有了参考,那就自己做一个吧,算是造福草民了。所以文中的电路图、源代码可以随意转载使用,同时也公布了成本,大家任意DIY吧。如果有高富帅有专业的PM2.5传感器(例如Dylos DC1100),并愿意帮忙标定,可以在微博上联系我( @bunnybus ) 。 灰尘检测装置的核心是使用了灰尘传感器SHARP GP2Y1010,但是发现这个传感器只能够检测空气中的粉尘浓度,但是却不能判断是哪些粒子的粉尘浓度,比如是Pm10的还是Pm2.5的(不过目前看来,所有的灰尘都是有害的,区别只是是否能被人体排出)。 缺点是没有高精度的检测装置对公式作标定,但是从做的多个传感器的读数看来,还是比较稳定的。 检测标准 首先,灰尘读数参考国外空气的标准(我在日常环境没有读到过20以下,使用空气净化器之后降到过18以下) 开发过程 实际上,我参考的就是这两篇文章:http://www./info/news_show/info_id/169993.htmlhttp://www./arduino/airquality/在具体的设计中,显示使用1602显示屏,增加了温湿度传感器DHT11,可以利用显示屏的其他空间,同时显示温度/湿度。 后来又写了个Windows App,可以通过串口获取数据,保存成CSV;之后可以在Excel中整理得到曲线: 做出来后发现身边有一些朋友对这个挺感兴趣,但是我手工焊线要4Hr以上(没办法,这个手艺无法速成),所以开始了设计电路板的工作(使用软件eagle),一次10个,想要的一人一个哈。 成本 外壳 —— 超市购买的小饭盒一个,5元(促销装) SHARP GP2Y1010 —— 40元 1602显示屏幕 —— 8元 DHT11 —— 8元 Arduino pro mini —— 23元 TTL转USB模块 —— 4.4元 (如果不需要电脑监控数据,可以忽略) 电路板 —— 6元 接头、开关、电阻、电容、LED等 快递 —— 30元 (通常无法在同一家店买到所有器材,通常要从深圳的卖家买2~3家店) 软件和焊接——不算学习研究,大约耗时6~8Hr,我的工时单价不算低,就不列出来了。 硬件总成本100左右吧。 原理图 电路图解释: 印刷板图 自动布线 电路板成品照片(后面一个红色的是第一版): 可以看出,第一版的PCB设计的比较初级,线宽未设置,覆铜没有,电源的引脚画错、开关器件选择错误、可变电阻器件选择错误(器件太多了,随便选了个,造成引脚位置匹配不上);不过经过简单的手工处理还是可以用的,主体电路没问题。 以下是第二版的成品: 内部照片 电路板 灰尘传感器接线: SHARP灰尘传感器的参考电路 DHT11温湿度传感器的参考电路 实际上,读取灰尘数据的核心源代码只有几行: // ledPower is any digital pin on the arduino connected to Pin 3 on the sensor digitalWrite(ledPower,LOW); // power on the LED delayMicroseconds(delayTime); dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor delayMicroseconds(delayTime2); digitalWrite(ledPower,HIGH); // turn the LED off delayMicroseconds(offTime); 源代码 由于我认为大家都了解当前环境的灰尘是件好事,所以公布源代码如下: (说明:源代码没有整理过,比较粗燥,很简单的东西,我也不是软件高手,个人认为也不值得再折腾了) //调用Arduino自带的LiquidCrystal库 #include //温湿度传感器库,定义PM2.5污染指数级别 #include //调用Dht库 const int PM_LV_A = 5; //定义优质空气质量级别 const int PM_LV_B = 9; //定义良好空气质量级别 const int PM_LV_C = 30; //定义通常空气质量级别 const int PM_LV_D = 85; //定义轻度污染空气质量级别 //颗粒物传感器接口定义 const int dustPin=A1; //设置arduino模拟信号接口A1为pm2.5传感器采集口 int dustVal=0; //设置pm2.5传感器初始值 const int ledPower=2; //设置arduino数字信号接口2为pm2.5传感器LED发射口 int delayTime=280; //设置传感器延时 int delayTime2=40; //设置传感器延时 float offTime=9680; //设置pm2.5传感器采样时间 float pm25_val = 0; //设置pm2.5传感器初始值,0.5v电压相当于每立方米0.1mg颗粒物含量:0.1mg/m3 //LCD1602液晶屏接口对arduino端口定义,采用4bit传送,数据分别从D4、D5、D6、D7传输 const int RS = 3; //------------- const int RW = 4; //------------- const int EN = 5; //------------- const int D4 = 6; //-------------数据分别从D4、D5、D6、D7传输 const int D5 = 7; //------------- const int D6 = 8; //------------- const int D7 = 9; //------------- //设置LCD1602液晶接口 LiquidCrystal lcd(RS, RW, EN, D4, D5, D6, D7); //快速刷新模式定义 const int FAST_REFRESH_MODE=10; //定义打开/关闭快速读取(最快3秒)的引脚:支持2种模式,即快速开关模式或者平均值模式 boolean FAST_REFRESH = true; //快速刷新模式(Off) const int AVG_COUNTS = 10; //定义平均值模式每次平均采样次数,例如定义为10,即为每30s获取一次平均值(每3秒读一次) //int pm_list[AVG_COUNTS]; //缓存数组(实际并未使用),可扩展为将历史数据记录在设备中供设备读取 int pm_list_sum; //平均值模式的累积合计变量 int pm_avg ; //PM25平均值//DHT11温湿度传感器dht DHT; #define DHT11_PIN A0 //put the sensor in the digital pin 4 ——重新定义A0为获取DHT11的数据引脚(使用模拟量输入口,可以改为其它温度传感器,例如LM35)//Arduino初始化函数setup() void setup(){ Serial.begin(9600); //串口通讯速率9600 pinMode(ledPower,OUTPUT); //设置ledpower接都为信号输出 pinMode(4, OUTPUT); //设置arduino数字4口为输出端,此处作为10口(快速刷新模式)为开时亮灯 pinMode(FAST_REFRESH_MODE,INPUT); //设置arduino数字10口为输入端 lcd.begin(16, 2); //初始化LCD //lcd.backlight(); //点亮LCD背光灯 delay(1000); //延时1000ms pm_list_sum = 0; //初始化 } //Arduino循环执行函数loop() void loop(){ int pm25int = 0; //设置pm2.5初始值 //--get temperature and humdity if (digitalRead(FAST_REFRESH_MODE) == HIGH) //PM2.5传感器控制程序 { FAST_REFRESH = true; } else { FAST_REFRESH = false; } int chk = DHT.read11(DHT11_PIN); switch (chk) //检测数值串口输出信息 { case 0: Serial.print("OK,\t"); //如果数据为0,串口输出采集正常。 break; case -1: Serial.print("Checksum error,\t"); //如果数据为-1,串口输出--错误。 break; case -2: Serial.print("Time out error,\t"); //如果数据为0,串口输出时间溢出。 break; default: Serial.print("Unknown error,\t"); //串口输出未知错误。 break; } //------------------------------------------------------------------------------- if (!FAST_REFRESH) { pm_list_sum = 0; //--------------- pm_avg = 0; //--------------- for(int i=0;i<AVG_COUNTS;i++) { // ledPower is any digital pin on the arduino connected to Pin 3 on the sensor digitalWrite(ledPower,LOW); //接通颗粒物传感器led灯电源 delayMicroseconds(delayTime); //延时 dustVal=analogRead(dustPin); //读取颗粒物传感器第五模拟口电压数值 delayMicroseconds(delayTime2); //延时 digitalWrite(ledPower,HIGH); //关闭颗粒物传感器led灯电源 delayMicroseconds(offTime); //延时 pm25_val = dustVal * 0.83984375 - 99.9 ; //计算pm2.5采集数值 int pm25int = dustVal * 0.83984375 - 99.9 ; //------------------ if (pm25int < 0) //------------------ { pm25int = 20; //给Pm2.5int变量赋初始值 } pm_list_sum = pm_list_sum + pm25int; //------------------ delay(3000); //延时3000ms } pm_avg = pm_list_sum / AVG_COUNTS; //计算pm2.5数据平均值 } else { // 颗粒物传感器LED电源引脚接在arduino的第D3接口 digitalWrite(ledPower,LOW); //接通颗粒物传感器led灯电源 delayMicroseconds(delayTime); //延时 dustVal=analogRead(dustPin); //读取颗粒物传感器第五模拟口电压数值 delayMicroseconds(delayTime2); //延时 digitalWrite(ledPower,HIGH); //关闭颗粒物传感器led灯电源 delayMicroseconds(offTime); //延时 pm25_val = dustVal * 0.83984375 - 99.9 ; //------------------ pm25int = dustVal * 0.83984375 - 99.9 ; //------------------ delay(3000); //延时3000ms } if (!FAST_REFRESH) { Serial.print("Temperature:"); //串口发送“Temperature:”字符 Serial.print(DHT.temperature); //串口发送温度数值 Serial.print("[C]"); //串口发送“[C]”字符 Serial.print(","); //串口发送“,”字符 Serial.print("Humdity:"); //串口发送“Humdity:”字符 Serial.print(DHT.humidity); //串口发送湿度数值 Serial.print("%"); //串口发送“%”字符 Serial.print(","); //串口发送“,”字符 Serial.print("PM25:"); //串口发送“PM25:”字符 Serial.print(pm25_val); //串口发送PM2.5数值 Serial.println(pm_avg); //串口发送PM2.5平均 Serial.println("[ug/m3]"); //串口发送“[ug/m3]”字符 //LCD液晶显示信息 lcd.clear(); //LCD1602液晶清屏 lcd.setCursor(0,0); //设置LCD1602光标在第一行第一格 lcd.print("D="); //LCD1602输出“D=” lcd.print(pm_avg); //LCD1602输出PM2.5平均采样值 lcd.print(" ug/m3"); //LCD1602输出“D=” //选择输出空气污染指数级别 if (PM_LV_A > pm_avg) //判断采集的平均值是否小于污染A级别 lcd.print(" Fine"); //LCD1602输出优信息 else if (PM_LV_B > pm_avg) //判断采集的平均值是否小于污染D级别 lcd.print(" Good"); //LCD1602输出好信息 else if (PM_LV_C > pm_avg) //判断采集的平均值是否小于污染C级别 lcd.print(" Normal"); //LCD1602输出良信息 else if (PM_LV_D > pm_avg) //判断采集的平均值是否小于污染D级别 lcd.print(" Bad"); //LCD1602输出轻度污染信息 else lcd.print(" Hell"); //LCD1602输出重度污染信息 //LCD液晶显示信息 lcd.setCursor(0,1); //设置光标在第二行第一格 lcd.print("Tmp:"); //LCD1602输出“Tmp:”字符 lcd.print(DHT.temperature); //LCD1602输出温度值 lcd.print("C"); //LCD1602输出“C”字符 lcd.print(" "); //LCD1602输出“ ”字符 lcd.print("Hum:"); //LCD1602输出“Hum:”字符 lcd.print(DHT.humidity); //LCD1602输出湿度值 lcd.print("%"); //LCD1602输出“%字符 } else { // 串口发送数据 Serial.print("Temperature:"); //串口发送“Temperature:”字符 Serial.print(DHT.temperature); //串口发送温度数值 Serial.print("[C]"); //串口发送“[c]”字符 Serial.print(","); //串口发送“,”字符 Serial.print("Humdity:"); //串口发送“Humdity:”字符 Serial.print(DHT.humidity); //串口发送湿度数值 Serial.print("%"); //串口发送“%”字符 Serial.print(","); //串口发送“,”字符 Serial.print("PM25:"); //串口发送“PM25:”字符 Serial.print(pm25_val); //串口发送pm2.5数值 Serial.println("[ug/m3]"); //串口发送“[ug/m3]”字符并换行 //LCD1602液晶显示信息 lcd.clear(); //LCD1602液晶清屏 lcd.setCursor(0,0); //设置光标显示在第一行第一格 lcd.print("D="); //输出“D=”字符 lcd.print(pm25int); //输出pm2.5数值 lcd.print(" ug/m3"); //输出“ ug/m3”字符 //选择输出空气污染指数级别 if (PM_LV_A > pm_avg) //判断采集的平均值是否小于污染A级别 lcd.print(" Fine"); //LCD1602输出优信息 else if (PM_LV_B > pm_avg) //判断采集的平均值是否小于污染B级别 lcd.print(" Good"); //LCD1602输出好信息 else if (PM_LV_C > pm_avg) //判断采集的平均值是否小于污染C级别 lcd.print(" Normal"); //LCD1602输出良信息 else if (PM_LV_D > pm_avg) //判断采集的平均值是否小于污染D级别 lcd.print(" Bad"); //LCD1602输出轻度污染信息 else lcd.print(" Hell"); //LCD1602输出重度污染信息 //LCD1602液晶显示信息 lcd.setCursor(0,1); //设置光标显示在第二行第一格 lcd.print("Tmp:"); //LCD1602输出“Tmp:”字符 lcd.print(DHT.temperature); //LCD1602输出温度数值 lcd.print("C"); //LCD1602输出“C”字符 lcd.print(" "); //LCD1602输出“ ”字符 lcd.print("Hum:"); //LCD1602输出“Hum:”字符 lcd.print(DHT.humidity); //LCD1602输出“DHT.humidity”字符 lcd.print("%"); //LCD1602输出“%”字符 } }
|
|