HuaShine2015 发表于 2015-3-18 15:38:18

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

本帖最后由 HuaShine2015 于 2015-3-18 15:58 编辑

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



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

      原理框图:

      作品外观:



   Android远程通讯APP界面:


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

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

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

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

LCD5110:
      CLK- Arduino Pin D8
      DIN- Arduino Pin D9
      DC   - Arduino Pin D10
      RST- Arduino Pin D11
      CE   - Arduino Pin D12
      BLK- Arduino Pin D7
      VCC- 5V/3.3V
      GND- Arduino GND pin
      
PM Value Alert_LED (Red):
      VCC- Arduino Pin D6 (connected to 220ohm resister)
      GND- Arduino GND pin
PM Value Warning_LED (Yellow):
      VCC- Arduino Pin D14 (connected to 220ohm resister)//D14 = A0;
      GND- Arduino GND pin
      
Wakeup_Key:
      pin 1 - Arduino Pin D3
      pin 2 - Arduino GND pin
*/

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

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

dht11 DHT11;                                                                        //创建DHT11对象                                                                               

int YLED = 14;                                                                         //定义LED,蓝牙,GP2Y1010AU,相关使能PIN
int BLLED = 7;
int RLED = 6;
int EN = 13;
int WAKEUP = 3;
int BRTS = 2;
int dustPin = A1;
int ledPower = 5;

int blTime = 0;                                                                        //定义相关温湿度颗粒度数据处理变量
int delayTime = 280;
int delayTime2 = 40;
int dustVal = 0;
float offTime = 9680.0;
float voltage = 0.0;
float humidity = 0.0;
float temperature = 0.0;
float dustdensity = 0.0;
float ppmpercf = 0.0;

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

void init_device(){                                                                //开机初始化业务代码块

myGLCD.InitLCD(60);                                                        //显示开机画面和点灯
myGLCD.setFont(SmallFont);
myGLCD.print("PM2.5 AutoTest", CENTER, 0);
myGLCD.print("V1.0", CENTER, 16);
myGLCD.print("|            |", CENTER, 32);
delay(200);
for (int i=0; i<12; i++)
{
    digitalWrite(RLED, HIGH);
    digitalWrite(YLED, HIGH);
    digitalWrite(BLLED, HIGH);
    myGLCD.print("\\", 6+(i*6), 32);
    delay(500);
    digitalWrite(RLED, LOW);
    digitalWrite(YLED, HIGH);
    digitalWrite(BLLED, LOW);   
}
bt_init();                                //初始化蓝牙
delay(500);
myGLCD.clrScr();                        //清屏幕

}

void bt_init(){                         //以下为蓝牙业务处理代码

    digitalWrite(EN, LOW);
    digitalWrite(BRTS, HIGH);
   
}

void bt_send(){

    digitalWrite(EN, LOW);
    digitalWrite(BRTS, LOW);
   
}

void bt_sleep(){

      digitalWrite(BRTS, HIGH);
      digitalWrite(EN, HIGH);
      
}

void lcd_dp(float tmp, float hum, float dus){                //正常工作数据监视画面业务代码

myGLCD.setFont(SmallFont);
myGLCD.print("      ", RIGHT, 0);
myGLCD.print("Hum(%):", LEFT, 0);
myGLCD.printNumF((float)hum, 1, RIGHT, 0);

myGLCD.print("      ", RIGHT, 8);
myGLCD.print("Temp(oC):", LEFT, 8);
myGLCD.printNumF((float)tmp, 1, RIGHT, 8);

myGLCD.print("Dust(ug/m3):", LEFT, 16);
myGLCD.print("                ", CENTER, 32);
myGLCD.print("                ", CENTER, 40);
myGLCD.setFont(MediumNumbers);
myGLCD.printNumF((float)dus * 1000.0, 1, CENTER, 32);

}

void com_prt(float tmp, float hum, float dus){                //串口格式话输出当前数据业务代码

Serial.print(hum);
Serial.print(",");
Serial.print(tmp);
Serial.print(",");
Serial.println((float)(dus * 1000.0));

}

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

}

void setup(){                                                //MCU初始化入口代码

Serial.begin(115200);
inputString.reserve(120);
pinMode(ledPower,OUTPUT);
pinMode(BLLED,OUTPUT);
pinMode(RLED,OUTPUT);
pinMode(YLED,OUTPUT);
pinMode(EN,OUTPUT);
pinMode(BRTS,OUTPUT);
pinMode(WAKEUP,INPUT_PULLUP);

init_device();                                        //调用设备初始化代码块
attachInterrupt(1, wake_up, LOW);                //开启外部中断1,侦测唤醒按钮

}
void loop(){               

ctrl_bl();                 //调用背光点亮延迟并行代码
main_case();                //调用信号采集和数据处理主业务代码

if (stringComplete) {                //BLE4.0模块接收到连接设备的信息后会转发到MCU串口输入
                                                        //此处会对串口输入的命令做识别和处理
    if(inputString.endsWith("get#")){                        //远程连接设备要求取得当前温湿度和颗粒度侦测数值
       bt_init();                                                                //以下为MCU串口输出固定格式的数据给远程设备
       bt_send();
       delay(10);
       com_prt(temperature, humidity, dustdensity);
       delay(5);
       bt_init();
   }else if(inputString.endsWith("sleep#")){        //远程连接设备要求休眠蓝牙模块,进入脱机工作模式
      bt_sleep();                                                                //MCU关闭BLE
   }else if(inputString.endsWith("lighton#")){        //远程连接设备要求开启背光
      digitalWrite(BLLED, HIGH);
   }else if(inputString.endsWith("lightoff#")){   //远程连接设备要求关闭背光
      digitalWrite(BLLED, LOW);
   }   
    inputString = "";
    stringComplete = false;
   
}
delay(800);

}

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

}

void main_case(){                //信号采集和数据处理主业务代码

DHT11.read(DHT11PIN);
humidity = DHT11.humidity;
temperature = DHT11.temperature;

digitalWrite(ledPower,LOW);
delayMicroseconds(delayTime);
dustVal=analogRead(dustPin);
delayMicroseconds(delayTime2);
digitalWrite(ledPower,HIGH);
delayMicroseconds(offTime);                       
voltage = dustVal * 0.00488;                //此处颗粒度计算算法公式来源于网络       
dustdensity = 0.172 * voltage - 0.0999;
//ppmpercf = (voltage-0.0256) * 120000;
//if (ppmpercf < 0){
//    ppmpercf = 0;
//}
if (dustdensity < 0 ){                        //滤除传感器失效数据
      dustdensity = 0;
}
if (dustdensity > 0.5){                        //滤除传感器爆表后无效数据
      dustdensity = 0.5;
}

//com_prt(temperature, humidity, dustdensity);
lcd_dp(temperature, humidity, dustdensity);                //调用数据显示业务代码块
detect_pm(dustdensity * 1000.0);                                        //调用PM数值判断报警代码块

}
void serialEvent() {                //串口事件中断业务代码

while (Serial.available() > 0) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if ((inChar == '\n')||(inChar == '#')) {
      stringComplete = true;
    }
}

}

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

}



    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较小

sinkr 发表于 2015-3-18 18:42:07

谢谢楼主分享,收藏了

suoma 发表于 2015-3-18 19:46:15

谢谢分享学习一下

smallfivecn 发表于 2015-3-21 12:30:39

楼主能告诉这个PM2.5的计算公式从哪里查到的吗?给个链接。谢谢!

HuaShine2015 发表于 2015-3-21 17:08:19

smallfivecn 发表于 2015-3-21 12:30 static/image/common/back.gif
楼主能告诉这个PM2.5的计算公式从哪里查到的吗?给个链接。谢谢!

http://www.howmuchsnow.com/arduino/airquality/

zxca112 发表于 2015-3-28 19:58:54

很好啊 数据准吗?

HuaShine2015 发表于 2015-3-28 20:02:54

zxca112 发表于 2015-3-28 19:58 static/image/common/back.gif
很好啊 数据准吗?

家用足够,和小米空气净化器用的是同一型号的传感器

FutureMaker 发表于 2015-4-2 10:07:12

很是不错啊。多谢分享

skyfree 发表于 2015-4-5 08:30:50

程序手机无法安装

天天11111 发表于 2015-4-5 10:03:11

楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一下 发现向uno里面编写程序 不连接传感器也能有输出值,这是怎么回事?

HuaShine2015 发表于 2015-4-5 18:51:35

skyfree 发表于 2015-4-5 08:30 static/image/common/back.gif
程序手机无法安装

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

HuaShine2015 发表于 2015-4-5 18:54:31

天天11111 发表于 2015-4-5 10:03 static/image/common/back.gif
楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一 ...

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

skyfree 发表于 2015-4-5 21:38:25

HuaShine2015 发表于 2015-4-5 18:51 static/image/common/back.gif
1. 手机需要安卓4.4及以上版本系统;
2. 需要在设置-->安全里开启“允许未知来源的程序安装”

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

HuaShine2015 发表于 2015-4-7 08:21:16

skyfree 发表于 2015-4-5 21:38 static/image/common/back.gif
对系统还有要求啊?我的手机,Note2,安卓还是4.1.2呢。。。

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

yyy_zc 发表于 2015-4-11 17:09:48

怎么确定是4.0的呀
页: [1] 2
查看完整版本: 可以蓝牙4.0通讯的手持式PM2.5检测仪