极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 41982|回复: 29

可以蓝牙4.0通讯的手持式PM2.5检测仪

[复制链接]
发表于 2015-3-18 15:38:18 | 显示全部楼层 |阅读模式
本帖最后由 HuaShine2015 于 2015-3-18 15:58 编辑

        这是自己接触Arduino以来做的第二个作品。 一个手持式PM2.5读取装置,可以远程使用BLE4.0通讯读取检测值。
Arduino源代码和Android通讯apk的源代码都有共享在百度网盘:http://pan.baidu.com/s/1bnGWKMz



       主要材料有:Arduino pro mini    x1
                            GP2Y1010AU  x1
                            GP2Y1010AU配套150欧电阻 x1
                            GP2Y1010AU配套220uF电容 x1
                            CC2540 BLE 模块 x1
                            LCD5110模块 x1
                            DHT模块 x1
                            LED  x2
                            按键 x1

  
      原理框图:

      作品外观:



     Android远程通讯APP界面:


     PM2.5/PM10国家检测标准如下:

    下位机Arduino源码机接线说明:
  1. /*
  2.       PM10/2.5 Auto Tester
  3.                        -- by Shine.Hua 2014.03.13   
  4. PM2.5 GP2Y1010AU Sensor:
  5. Sharp pin 1 (V-LED)   => 5V (connected one 150ohm resister to VCC,and connected one 220uf cap to GND)
  6. Sharp pin 2 (LED-GND) => Arduino GND pin
  7. Sharp pin 3 (LED)     => Arduino pin D5
  8. Sharp pin 4 (S-GND)   => Arduino GND pin
  9. Sharp pin 5 (Vo)      => Arduino A1 pin
  10. Sharp pin 6 (Vcc)     => 5V

  11. DHT11 Sensor:
  12. Dht pin 1 => 5V
  13. Dht pin 2 => Arduino pin 4 (connected one 5K resister to VCC)
  14. Dht pin 3 => NG
  15. Dht pin 4 => Arduino GND pin

  16. CC2540 BLE 4.0 :
  17. pin 1 GND     => Arduino GND pin
  18. pin 2 VCC     => 3.3V
  19. pin 6 EN      => Arduino pin D13
  20. pin 14 BRTS   => Arduino pin D2
  21. pin 16 TX     => Arduino pin D0 RX
  22. pin 17 RX     => Arduino pin D1 TX

  23. LCD5110:
  24.       CLK  - Arduino Pin D8
  25.       DIN  - Arduino Pin D9
  26.       DC   - Arduino Pin D10
  27.       RST  - Arduino Pin D11
  28.       CE   - Arduino Pin D12
  29.       BLK  - Arduino Pin D7
  30.       VCC  - 5V/3.3V
  31.       GND  - Arduino GND pin  
  32.       
  33. PM Value Alert_LED (Red):
  34.       VCC  - Arduino Pin D6 (connected to 220ohm resister)
  35.       GND  - Arduino GND pin
  36. PM Value Warning_LED (Yellow):
  37.       VCC  - Arduino Pin D14 (connected to 220ohm resister)  //D14 = A0;
  38.       GND  - Arduino GND pin
  39.       
  40. Wakeup_Key:
  41.       pin 1 - Arduino Pin D3
  42.       pin 2 - Arduino GND pin  
  43. */

  44. #include <dht11.h>                                              //加载DHT11温湿度模块函数库
  45. #include <LCD5110_Basic.h>                                                //加载LCD模块函数库
  46. #define DHT11PIN 4                                                                //定义MCD对应DHT11的侦测PIN常量       

  47. LCD5110 myGLCD(8,9,10,11,12);                                        //定义MCD对应5110 LCD的连接PIN
  48. extern uint8_t SmallFont[];                                               
  49. extern uint8_t MediumNumbers[];

  50. dht11 DHT11;                                                                        //创建DHT11对象                                                                               

  51. int YLED = 14;                                                                         //定义LED,蓝牙,GP2Y1010AU,相关使能PIN
  52. int BLLED = 7;
  53. int RLED = 6;
  54. int EN = 13;
  55. int WAKEUP = 3;
  56. int BRTS = 2;
  57. int dustPin = A1;
  58. int ledPower = 5;

  59. int blTime = 0;                                                                        //定义相关温湿度颗粒度数据处理变量
  60. int delayTime = 280;
  61. int delayTime2 = 40;
  62. int dustVal = 0;
  63. float offTime = 9680.0;
  64. float voltage = 0.0;
  65. float humidity = 0.0;
  66. float temperature = 0.0;
  67. float dustdensity = 0.0;
  68. float ppmpercf = 0.0;

  69. String inputString = "";                                                 //定义串口接收缓存字符串
  70. boolean stringComplete = false;                                       
  71. boolean wakeUp = false;

  72. void init_device(){                                                                //开机初始化业务代码块
  73.   
  74.   myGLCD.InitLCD(60);                                                        //显示开机画面和点灯
  75.   myGLCD.setFont(SmallFont);
  76.   myGLCD.print("PM2.5 AutoTest", CENTER, 0);
  77.   myGLCD.print("V1.0", CENTER, 16);
  78.   myGLCD.print("|            |", CENTER, 32);
  79.   delay(200);
  80.   for (int i=0; i<12; i++)
  81.   {
  82.     digitalWrite(RLED, HIGH);
  83.     digitalWrite(YLED, HIGH);
  84.     digitalWrite(BLLED, HIGH);
  85.     myGLCD.print("\", 6+(i*6), 32);
  86.     delay(500);
  87.     digitalWrite(RLED, LOW);
  88.     digitalWrite(YLED, HIGH);
  89.     digitalWrite(BLLED, LOW);   
  90.   }
  91.   bt_init();                                //初始化蓝牙
  92.   delay(500);
  93.   myGLCD.clrScr();                        //清屏幕
  94.   
  95. }

  96. void bt_init(){                         //以下为蓝牙业务处理代码
  97.   
  98.     digitalWrite(EN, LOW);
  99.     digitalWrite(BRTS, HIGH);
  100.    
  101. }

  102. void bt_send(){
  103.   
  104.     digitalWrite(EN, LOW);
  105.     digitalWrite(BRTS, LOW);
  106.    
  107. }

  108. void bt_sleep(){
  109.   
  110.       digitalWrite(BRTS, HIGH);
  111.       digitalWrite(EN, HIGH);
  112.       
  113. }

  114. void lcd_dp(float tmp, float hum, float dus){                //正常工作数据监视画面业务代码
  115.   
  116.   myGLCD.setFont(SmallFont);  
  117.   myGLCD.print("      ", RIGHT, 0);
  118.   myGLCD.print("Hum(%):", LEFT, 0);
  119.   myGLCD.printNumF((float)hum, 1, RIGHT, 0);  
  120.   
  121.   myGLCD.print("      ", RIGHT, 8);
  122.   myGLCD.print("Temp(oC):", LEFT, 8);
  123.   myGLCD.printNumF((float)tmp, 1, RIGHT, 8);
  124.   
  125.   myGLCD.print("Dust(ug/m3):", LEFT, 16);
  126.   myGLCD.print("                ", CENTER, 32);
  127.   myGLCD.print("                ", CENTER, 40);
  128.   myGLCD.setFont(MediumNumbers);
  129.   myGLCD.printNumF((float)dus * 1000.0, 1, CENTER, 32);
  130.   
  131. }

  132. void com_prt(float tmp, float hum, float dus){                //串口格式话输出当前数据业务代码
  133.   
  134.   Serial.print(hum);
  135.   Serial.print(",");
  136.   Serial.print(tmp);
  137.   Serial.print(",");
  138.   Serial.println((float)(dus * 1000.0));
  139.   
  140. }

  141. boolean detect_pm(float dus){                                        //PM颗粒度逻辑判断代码,中度污染点亮黄色LED警告
  142.                                                                                                 //重度污染点亮红色LED报警
  143.   if(dus < 75.0){                                                                //判断方式根据国家PM2.5空气质量标准(24小时平均值)
  144.     digitalWrite(YLED, LOW);                                        //优  --->                         0~35ug/m3
  145.     digitalWrite(RLED, LOW);                                        //良  --->                         35~75ug/m3
  146.   }else if((dus >= 75.0)&&(dus < 150.0)){                //轻度污染  --->         75~115ug/m3
  147.       digitalWrite(YLED, HIGH);                                        //中度污染  --->        115~150ug/m3
  148.       digitalWrite(RLED, LOW);                                   //中度污染  --->        150~250ug/m3
  149.       return 1;                                                               //严重污染  --->        >250ug/m3
  150.   }else if(dus >= 150.0){
  151.       digitalWrite(YLED, LOW);
  152.       digitalWrite(RLED, HIGH);
  153.       return 1;   
  154.   }
  155.   return 0;
  156.   
  157. }

  158. void setup(){                                                //MCU初始化入口代码
  159.   
  160.   Serial.begin(115200);
  161.   inputString.reserve(120);
  162.   pinMode(ledPower,OUTPUT);
  163.   pinMode(BLLED,OUTPUT);
  164.   pinMode(RLED,OUTPUT);
  165.   pinMode(YLED,OUTPUT);
  166.   pinMode(EN,OUTPUT);
  167.   pinMode(BRTS,OUTPUT);
  168.   pinMode(WAKEUP,INPUT_PULLUP);
  169.   
  170.   init_device();                                        //调用设备初始化代码块
  171.   attachInterrupt(1, wake_up, LOW);                //开启外部中断1,侦测唤醒按钮
  172.   
  173. }
  174. void loop(){               
  175.   
  176.   ctrl_bl();                 //调用背光点亮延迟并行代码
  177.   main_case();                //调用信号采集和数据处理主业务代码
  178.   
  179.   if (stringComplete) {                //BLE4.0模块接收到连接设备的信息后会转发到MCU串口输入
  180.                                                         //此处会对串口输入的命令做识别和处理
  181.     if(inputString.endsWith("get#")){                        //远程连接设备要求取得当前温湿度和颗粒度侦测数值
  182.        bt_init();                                                                //以下为MCU串口输出固定格式的数据给远程设备
  183.        bt_send();
  184.        delay(10);
  185.        com_prt(temperature, humidity, dustdensity);
  186.        delay(5);
  187.        bt_init();
  188.      }else if(inputString.endsWith("sleep#")){        //远程连接设备要求休眠蓝牙模块,进入脱机工作模式
  189.         bt_sleep();                                                                //MCU关闭BLE
  190.      }else if(inputString.endsWith("lighton#")){        //远程连接设备要求开启背光
  191.         digitalWrite(BLLED, HIGH);
  192.      }else if(inputString.endsWith("lightoff#")){   //远程连接设备要求关闭背光
  193.         digitalWrite(BLLED, LOW);
  194.      }   
  195.     inputString = "";
  196.     stringComplete = false;
  197.    
  198.   }
  199.   delay(800);
  200.   
  201. }

  202. void ctrl_bl(){                        //背光点亮延迟并行处理的业务代码块
  203.                                                 //(在没有硬件延迟的处理电路时可以用此软件方式并行处理)
  204.   if(wakeUp){
  205.       blTime++;
  206.       if(blTime > 50){
  207.         digitalWrite(BLLED, LOW);
  208.         wakeUp = false;
  209.       }
  210.   }
  211.   
  212. }

  213. void main_case(){                //信号采集和数据处理主业务代码
  214.   
  215.   DHT11.read(DHT11PIN);
  216.   humidity = DHT11.humidity;
  217.   temperature = DHT11.temperature;

  218.   digitalWrite(ledPower,LOW);  
  219.   delayMicroseconds(delayTime);
  220.   dustVal=analogRead(dustPin);  
  221.   delayMicroseconds(delayTime2);
  222.   digitalWrite(ledPower,HIGH);  
  223.   delayMicroseconds(offTime);                       
  224.   voltage = dustVal * 0.00488;                //此处颗粒度计算算法公式来源于网络       
  225.   dustdensity = 0.172 * voltage - 0.0999;
  226.   //ppmpercf = (voltage-0.0256) * 120000;
  227.   //if (ppmpercf < 0){
  228.   //    ppmpercf = 0;
  229.   //}
  230.   if (dustdensity < 0 ){                        //滤除传感器失效数据
  231.       dustdensity = 0;
  232.   }
  233.   if (dustdensity > 0.5){                        //滤除传感器爆表后无效数据
  234.       dustdensity = 0.5;
  235.   }
  236.   
  237.   //com_prt(temperature, humidity, dustdensity);
  238.   lcd_dp(temperature, humidity, dustdensity);                //调用数据显示业务代码块
  239.   detect_pm(dustdensity * 1000.0);                                        //调用PM数值判断报警代码块
  240.   
  241. }
  242. void serialEvent() {                //串口事件中断业务代码
  243.   
  244.   while (Serial.available() > 0) {
  245.     char inChar = (char)Serial.read();
  246.     inputString += inChar;
  247.     if ((inChar == '\n')||(inChar == '#')) {
  248.       stringComplete = true;
  249.     }
  250.   }
  251.   
  252. }

  253. void wake_up(){                        //唤醒按键触发业务代码,主要作用1.唤醒背光
  254.                                                 //2.在用户关闭蓝牙模块后唤醒蓝牙模块
  255.   bt_init();
  256.   digitalWrite(BLLED, HIGH);
  257.   blTime = 0;
  258.   wakeUp = true;
  259.   
  260. }
复制代码



    Android端Apk源代码如有需要请到我网盘共享地址下载http://pan.baidu.com/s/1bnGWKMz
    主要参考google开发网站BLE相关实例代码。
    IOS端程序目前无力开发,如有IOS猿感兴趣可以配合做一下。蓝牙模块厂商资料也一并共享在网盘了
    内部有相关service和特征码资料,只要你对iBean了解应该很快。下位机通讯协议很简单:
              MCU接收到UART终端请求且内容为"get#"会返回当前“湿度值,温度值,颗粒度值”
              MCU接收到UART终端请求且内容为"lighton#"会点亮LCD背光
              MCU接收到UART终端请求且内容为"lightoff#"会关闭LCD背光
              MCU接收到UART终端请求且内容为"sleep#"会关闭蓝牙脱机运行



后记:
    此原型机设计有如下两点缺陷,造成后来Android上位机编写时做曲线页面显示功能时
    发现需要手机端按时间不断去去读取资料,这种方式已违背了BLE低功耗,短连接,简单资料的方针
    后来就暂时没有做进去,下次有机会改进,MCU先暂存当天和前天的数据,有请求就按JSON格式一次发送
            1. 没有加入RTC时钟
            2. 没有外部存储方式(SD,TF),内部EEPROM较小

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1 +2 +3 +3 收起 理由
lawrencedon + 2 + 3 + 3 赞一个!

查看全部评分

回复

使用道具 举报

发表于 2015-3-18 18:42:07 | 显示全部楼层
谢谢楼主分享,收藏了
回复 支持 反对

使用道具 举报

发表于 2015-3-18 19:46:15 | 显示全部楼层
谢谢分享学习一下
回复 支持 反对

使用道具 举报

发表于 2015-3-21 12:30:39 | 显示全部楼层
楼主能告诉这个PM2.5的计算公式从哪里查到的吗?给个链接。谢谢!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-21 17:08:19 | 显示全部楼层
smallfivecn 发表于 2015-3-21 12:30
楼主能告诉这个PM2.5的计算公式从哪里查到的吗?给个链接。谢谢!

http://www.howmuchsnow.com/arduino/airquality/
回复 支持 反对

使用道具 举报

发表于 2015-3-28 19:58:54 | 显示全部楼层
很好啊 数据准吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-28 20:02:54 | 显示全部楼层
zxca112 发表于 2015-3-28 19:58
很好啊 数据准吗?

家用足够,和小米空气净化器用的是同一型号的传感器
回复 支持 反对

使用道具 举报

发表于 2015-4-2 10:07:12 | 显示全部楼层
很是不错啊。多谢分享
回复 支持 反对

使用道具 举报

发表于 2015-4-5 08:30:50 | 显示全部楼层
程序手机无法安装
回复 支持 反对

使用道具 举报

发表于 2015-4-5 10:03:11 | 显示全部楼层
楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一下 发现向uno里面编写程序 不连接传感器也能有输出值,这是怎么回事?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-5 18:51:35 | 显示全部楼层
skyfree 发表于 2015-4-5 08:30
程序手机无法安装

1. 手机需要安卓4.4及以上版本系统;
2. 需要在设置-->安全里开启“允许未知来源的程序安装”
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-5 18:54:31 | 显示全部楼层
天天11111 发表于 2015-4-5 10:03
楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一 ...

模拟输入口悬空也会有动态值啊,类似环境噪声;
一般用来做random随机数用
回复 支持 反对

使用道具 举报

发表于 2015-4-5 21:38:25 | 显示全部楼层
HuaShine2015 发表于 2015-4-5 18:51
1. 手机需要安卓4.4及以上版本系统;
2. 需要在设置-->安全里开启“允许未知来源的程序安装”

对系统还有要求啊?我的手机,Note2,安卓还是4.1.2呢。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-7 08:21:16 | 显示全部楼层
skyfree 发表于 2015-4-5 21:38
对系统还有要求啊?我的手机,Note2,安卓还是4.1.2呢。。。

Google的系统在4.3版本以后才正式支持BLE
回复 支持 反对

使用道具 举报

发表于 2015-4-11 17:09:48 | 显示全部楼层
怎么确定是4.0的呀
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 03:04 , Processed in 0.049243 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表