2017-1-4 11:20:29 [显示全部楼层]
28923浏览
查看: 28923|回复: 25

[项目] Arduino PM2.5 & CO2 室内空气质量检测

[复制链接]
摘要:采用Arduino开源硬件,搭配PM2.5空气质量传感器和红外CO2二氧化碳传感器,制成一个小型的室内空气质量检测台。

又到一年一度的冬日魔都雾霾季,2017年的第一个工作日就在这样一个“中度污染”日子里到来。这日子没法过了!{:5_149:}
新年第一天上班,你们懂得{:5_198:}
手上刚好有一个闲置的PM2.5传感器(Luna姐姐送的!,感谢Luna),一个红外CO2二氧化碳的传感器(对,就那个599的,壕只挑贵的!),本着不浪费的小市民心理,打算做一个小应用玩玩。搜刮了一圈桌子,找了一块Bluno M3和LCD keypad液晶屏

材料清单:
1. Bluno M3 V2.2 主控板
2. LCD keypad shield
3. SEN0220 红外CO2二氧化碳传感器 (0~50000ppm)
4. SEN0177 PM2.5激光粉尘传感器

号外:商城终于有自己的心愿单了:一键购买链接


说明:Bluno M3 并不是一个常见的Arduino板,它是DF基于STM32开发的Arduino兼容板,优点是便宜,管脚资源多;但缺点也很明显,与一般的Arduino板存在兼容性问题(当然啦,Arduino是8位机,STM32是32位机,有部分不兼容是非常正常的事情)。这边选择M3的一个原因是M3有5个UART口,而这PM2.5和红外传感器又都是串口设备,对于M3来说是完全够了的;带蓝牙(教程不含蓝牙功能,懒);最后就是这个板子放着也是放着~~ 用UNO,Leonardo,Mega2560等其实也完全没问题、

LCD keypad虽然占了很多管脚,但是上面有个PM2.5转接板的专用接口,省去了我接线的麻烦。
_DSC0656.JPG

教程:

硬件操作:
1. 红外二氧化碳用的是双头PH2.0,其中一个要改成XH2.54的接头(用公母头的杜邦线直插也是可以的,就是最好能固定一下)
2. 这边选了Bluno M3的Serial1和Serial5两个串口分别作为PM2.5和CO2的UART通信口,Serial1直接连到的LCD上的 PM2.5的接口,所以不用改动,但UART5还是要把排针弯一下的,方便插。
20170103_181040.jpg

3. 看图连线
20170103_181153.jpg


软件:

在IDE中选择Bluno M3,选择对应串口,烧入以下代
(注意,Bluno M3的串口是从Serial1开始的,烧录代码的时候,为了防止上传出错,先不要插PM2.5转接板,另外,使用UNO,Leonardo的童鞋可以用软串口来读取数据,并不一定要Bluno M3的)

  1. #include <Arduino.h>
  2. #define LENG 31   //0x42 + 31 bytes equal to 32 bytes
  3. unsigned char buf[LENG];
  4. unsigned char hexdata[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; //Read the CO2 gas density command /Don't change the order
  5. long hi, lo, CO2;
  6. int PM2_5Value = 0;       //define PM2.5 value of the air detector module
  7. #include <LiquidCrystal.h>
  8. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);        // select the pins used on the LCD panel
  9. void setup()
  10. {
  11.   Serial1.begin(9600);   //PM2.5 串口1
  12.   Serial5.begin(9600);    //CO2 串口5     使用UNO和Leonardo的童鞋可以用软串口
  13.   Serial1.setTimeout(1500);    //设置超时时间为1500毫秒(大于传感器传送数据周期1秒)
  14.   lcd.begin(16, 2);              // LCD 初始化
  15. }
  16. void loop()
  17. {
  18.   //CO2 value
  19.   Serial5.write(hexdata, 9);
  20.   for (int i = 0, j = 0; i < 9; i++)
  21.   {
  22.     if (Serial5.available() > 0)
  23.     {
  24.       int ch = Serial5.read();
  25.       if (i == 2) {
  26.         hi = ch;    //High concentration
  27.       }
  28.       if (i == 3) {
  29.         lo = ch;    //Low concentration
  30.       }
  31.       if (i == 8) {
  32.         CO2 = hi * 256 + lo; //CO2 concentration
  33.       }
  34.     }
  35.   }
  36.   //PM2.5
  37.   if (Serial1.find(0x42)) {  //检测到0x42时,开始读取
  38.     Serial1.readBytes(buf, LENG);
  39.     if (buf[0] == 0x4d) {
  40.       if (checkValue(buf, LENG)) {
  41.         PM2_5Value = transmitPM2_5(buf); //count PM2.5 value of the air detector module
  42.       }
  43.     }
  44.   }
  45.   // LCD显示
  46.   static unsigned long OledTimer = millis();
  47.   if (millis() - OledTimer >= 1000)
  48.   {
  49.     OledTimer = millis();
  50.     lcd.setCursor(0, 0);                   // set the LCD cursor   position
  51.     lcd.print("PM2.5: ");
  52.     lcd.print(PM2_5Value);
  53.     lcd.println(" ug/m3   ");
  54.     lcd.setCursor(0, 1);                   // set the LCD cursor   position
  55.     lcd.print("CO2:   ");
  56.     lcd.print(CO2);
  57.     lcd.print(" PPM   ");
  58.   }
  59. }
  60. char checkValue(unsigned char *thebuf, char leng)
  61. {
  62.   char receiveflag = 0;
  63.   int receiveSum = 0;
  64.   for (int i = 0; i < (leng - 2); i++) {
  65.     receiveSum = receiveSum + thebuf;
  66.   }
  67.   receiveSum = receiveSum + 0x42;
  68.   if (receiveSum == ((thebuf[leng - 2] << 8) + thebuf[leng - 1])) //check the Serial1 data
  69.   {
  70.     receiveSum = 0;
  71.     receiveflag = 1;
  72.   }
  73.   return receiveflag;
  74. }
  75. //transmit PM Value to PC
  76. int transmitPM2_5(unsigned char *thebuf)
  77. {
  78.   int PM2_5Val;
  79.   PM2_5Val = ((thebuf[5] << 8) + thebuf[6]); //count PM2.5 value of the air detector module
  80.   return PM2_5Val;
  81. }
复制代码

上传成功,等待15s后,PM2.5开始有数据,室内空气还不错,就是二氧化碳浓度有点高(如果CO2浓度一上来是65536,点一下复位先。)
20170104_104057.jpg

魔都当天的PM2.5浓度如下图 ,上午从190掉到180了。(昨天上午)
QQ截图20170104110528.png


拿到窗边,5秒不到CO2是下来了,但这PM2.5,看着好想搬家啊!
20170103_101616.jpg


总结:PM的精度还阔以,CO2除了有点贵外没啥缺点,哈几口气差不多能到30000多,NDIR的检测方式在响应速度上确实有点慢,虽然官网给了90s,但还是有点不能忍。
一键购买链接

你可能需要参考的资料:
LCD keypad 的产品维库(自己下库文件)
PM2.5的产品维库(可以自己研究一下)
红外CO2二氧化碳传感器产品维库
Bluno M3 V2.2 (V2.2公测版,官方还是V2.1,建议换成UNO,Leonardo或者Mega2560,通用一些,用软串口读数据,所以就不给链接了)

2017/1/3 Update:有人问Sharp GP2Y10的传感器怎么样,我只能说那个只能检测PM10,是通过一个固定公式推算出的PM2.5数值,只能说是个估算值(很多空气净化器里面用的就是Sharp的那款,几千块的的机子用的还是十几块的传感器,醉了
2017/3/29 Update:楼主弄了一个甲醛传感器,有没有想看如何测甲醛的?有的就留言哈,不然没动力写教程~

Grey  中级技匠
 楼主|

发表于 2017-6-11 12:40:45

DFCK 发表于 2017-6-10 22:20
这个电源用的是什么啊?

1. PM2.5就是可吸入颗粒物,PM10是更大的颗粒,这个都可以直接检测
2. 这个腕表估计要有点大了,技术上应该可以,不过价格也应该很可以
3. 普通的arduino的电源就好,不过最好外接供电,这个耗电有点厉害
回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 11:28:31

Grey 发表于 2017-6-11 12:40
1. PM2.5就是可吸入颗粒物,PM10是更大的颗粒,这个都可以直接检测
2. 这个腕表估计要有点大了,技术上应 ...

还有这些......
c:/users/lenovo/desktop/dfr0329-bluno m3控制器/arduino ide 1.5.5 bluno m3/arduino-1.5.5/hardware/tools/g++_arm_none_eabi/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld.exe: warning: changing start of section .bss by 4 bytes
c:/users/lenovo/desktop/dfr0329-bluno m3控制器/arduino ide 1.5.5 bluno m3/arduino-1.5.5/hardware/tools/g++_arm_none_eabi/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld.exe: warning: changing start of section .bss by 4 bytes
c:/users/lenovo/desktop/dfr0329-bluno m3控制器/arduino ide 1.5.5 bluno m3/arduino-1.5.5/hardware/tools/g++_arm_none_eabi/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld.exe: warning: changing start of section .bss by 4 bytes

回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 11:12:58

Grey 发表于 2017-6-11 12:40
1. PM2.5就是可吸入颗粒物,PM10是更大的颗粒,这个都可以直接检测
2. 这个腕表估计要有点大了,技术上应 ...

我的代码还总是出现这个warning,是怎么回事呢?
c:/users/lenovo/desktop/dfr0329-bluno m3控制器/arduino ide 1.5.5 bluno m3/arduino-1.5.5/hardware/tools/g++_arm_none_eabi/bin/../lib/gcc/arm-none-eabi/4.4.1/thumb2\libgcc.a(unwind-arm.o): In function `get_eit_entry':
unwind-arm.c:(.text+0x52e): warning: undefined reference to `__exidx_end'
unwind-arm.c:(.text+0x532): warning: undefined reference to `__exidx_start'
unwind-arm.c:(.text+0x536): warning: undefined reference to `__exidx_start'
unwind-arm.c:(.text+0x53a): warning: undefined reference to `__exidx_end'
回复

使用道具 举报

hnyzcj  版主

发表于 2017-1-4 11:50:41

大神,流弊
回复

使用道具 举报

Grey  中级技匠
 楼主|

发表于 2017-1-4 11:58:13


只是拼接了起来,没啥技术含量,突然觉得需要学一下3d打印,做一个外壳就好
回复

使用道具 举报

visionsl  初级技匠

发表于 2017-1-4 16:55:13

红外CO2二氧化碳传感器
这简直是土豪的玩具
回复

使用道具 举报

dsweiliang  初级技神

发表于 2017-1-5 08:36:06

Grey 发表于 2017-1-4 11:58
只是拼接了起来,没啥技术含量,突然觉得需要学一下3d打印,做一个外壳就好 ...

入台Overlord吧
回复

使用道具 举报

Xpimach  见习技师

发表于 2017-1-5 14:23:36

很棒,我来试试
回复

使用道具 举报

Xpimach  见习技师

发表于 2017-1-5 14:25:38

感谢
回复

使用道具 举报

砖头墙  初级技师

发表于 2017-1-6 21:14:23

叼                       牛                       膜拜大神
回复

使用道具 举报

逗比的零次方  学徒

发表于 2017-1-12 22:54:39

赞一个
回复

使用道具 举报

凌风清羽  中级技匠

发表于 2017-1-27 14:14:54

学习一下~~~~~~~
回复

使用道具 举报

shzrzxlee  中级技匠

发表于 2017-4-29 11:30:14

搞个测甲醛的:handshake
回复

使用道具 举报

DFCK  学徒

发表于 2017-6-10 21:57:26

请问这个可以同时安装PM10和可吸入颗粒物的传感器吗?
回复

使用道具 举报

DFCK  学徒

发表于 2017-6-10 21:58:35

我还想问一下这个有什么办法可以做的更小巧吗?我想用3D打印把它包装成一个类似于腕表的形式
回复

使用道具 举报

DFCK  学徒

发表于 2017-6-10 22:20:11

这个电源用的是什么啊?
回复

使用道具 举报

Youyou  初级技匠

发表于 2017-6-13 19:06:34

666,膜拜大神!
回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 10:54:11

Grey 发表于 2017-6-11 12:40
1. PM2.5就是可吸入颗粒物,PM10是更大的颗粒,这个都可以直接检测
2. 这个腕表估计要有点大了,技术上应 ...

谢谢大神。:loveliness:我还想问一下你这个ide用的是什么呢?我下载的arduino都不带Bluno M3这个板子的,该怎么配置呢?(PS 我已经买了Bluno M3了,不想换板子了)

还有我在使用serial.find(0x42)时总是给我报错:
C:\Users\lenovo\Desktop
回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 10:55:19

DFCK 发表于 2017-7-15 10:54
谢谢大神。我还想问一下你这个ide用的是什么呢?我下载的arduino都不带Bluno M3这个板子的, ...

额。。。本地图片没显示出来。。。
sketch_jul15a:47: error: invalid conversion from 'int' to 'char*'
sketch_jul15a:47: error: initializing argument 1 of 'bool Stream::find(char*)'
回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 10:56:54

DFCK 发表于 2017-7-15 10:55
额。。。本地图片没显示出来。。。
sketch_jul15a:47: error: invalid conversion from 'int' to 'char*' ...

不过我看arduino官网的reference上给的serial.find()的接收变量的类型就是char啊,不懂,求解。
回复

使用道具 举报

DFCK  学徒

发表于 2017-7-15 11:02:58

Grey 发表于 2017-6-11 12:40
1. PM2.5就是可吸入颗粒物,PM10是更大的颗粒,这个都可以直接检测
2. 这个腕表估计要有点大了,技术上应 ...

还有serial.readBytes( , )第一个参数也报错,它只接受char*类型的变量,不接受unsigned char*类型的变量,怎么破?
回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2021 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail