可以蓝牙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较小 谢谢楼主分享,收藏了 谢谢分享学习一下 楼主能告诉这个PM2.5的计算公式从哪里查到的吗?给个链接。谢谢! 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 static/image/common/back.gif
很好啊 数据准吗?
家用足够,和小米空气净化器用的是同一型号的传感器 很是不错啊。多谢分享 程序手机无法安装 楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一下 发现向uno里面编写程序 不连接传感器也能有输出值,这是怎么回事? skyfree 发表于 2015-4-5 08:30 static/image/common/back.gif
程序手机无法安装
1. 手机需要安卓4.4及以上版本系统;
2. 需要在设置-->安全里开启“允许未知来源的程序安装” 天天11111 发表于 2015-4-5 10:03 static/image/common/back.gif
楼主,我现在只是一个初学者 能给个只通过电容电阻,依靠arduino uno控制传感器的连接图吗?昨晚我尝试了一 ...
模拟输入口悬空也会有动态值啊,类似环境噪声;
一般用来做random随机数用 HuaShine2015 发表于 2015-4-5 18:51 static/image/common/back.gif
1. 手机需要安卓4.4及以上版本系统;
2. 需要在设置-->安全里开启“允许未知来源的程序安装”
对系统还有要求啊?我的手机,Note2,安卓还是4.1.2呢。。。
skyfree 发表于 2015-4-5 21:38 static/image/common/back.gif
对系统还有要求啊?我的手机,Note2,安卓还是4.1.2呢。。。
Google的系统在4.3版本以后才正式支持BLE 怎么确定是4.0的呀
页:
[1]
2