概述
基于nb-iot和arduino的气象站(二)PM2.5和GPS传感器
上一篇介绍了温湿度传感器和紫外线传感器的使用。
这一篇介绍pm2.5和GPS传感器的使用。
一、PM2.5传感器
我使用的传感器为DSL-03。
DSL-03是一款激光式PM2.5传感器,内置激光器和光电接收组件,采用光散射原理,激光在颗粒物上产生散射光,由光电接收器件转变为电信号,再通过特定算法计算出PM2.5质量浓度、PM10质量浓度、PM0.3~PM2.5粒子个数、PM2.5~PM10粒子个数。
1.1接线说明
- GND接GND
- VCC接5V
- TX接arduino RX
- RX接arduino TX
1.2数据格式
该传感器采用异步串行通信方式,以帧为单位进行通讯。帧格式固定,每一帧由9个字节组成,分命令帧和应答帧。
- 传感器上电后,需要给传感器发送开机指令
帧头 | 帧命令 | 帧内容 | 校验和 | 帧尾 |
---|---|---|---|---|
0xAA | 0x01 | 0x00000000 | 0x0166 | 0xBB |
传感器向外部设备回应帧具体内容为
帧头 | 帧命令 | 帧内容 | 校验和 | 帧尾 |
---|---|---|---|---|
0xAA | 0x01 | 0x00004F4B | 0x0200 | 0xBB |
1. 读PM2.5和PM10的值
外部设备向传感器发送命令
帧头 | 帧命令 | 帧内容 | 校验和 | 帧尾 |
---|---|---|---|---|
0xAA | 0x02 | 0x00000000 | 0x0167 | 0xBB |
传感器向外部设备回应帧具体内容为
帧头 | 帧命令 | 帧内容 | 校验和 | 帧尾 |
---|---|---|---|---|
0xAA | 0x02 | 0x01310123 | 0x01BD | 0xBB |
计算PM2.5质量浓度:(字节5)*256+(字节6)=0x01*256+0x23=291(ug/m3)
计算PM2.5质量浓度:(字节3)*256+(字节4)=0x01*256+0x31=305(ug/m3)
计算字节和校验:
(字节1)+(字节2)+(字节3)+(字节4)+(字节5)+(字节6)+(字节9)=(字节7)*256+(字节8)
1.3参考代码
#include <Adafruit_Sensor.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(5, 6);
uint16_t pm25;
uint16_t pm10;
void setup() {
mySerial.begin(9600);
Serial.begin(9600);
pmOn();
delay(1000);
}
void pmRead(){
uint8_t data[] = {0xAA,0x02,0x00,0x00,0x00,0x00,0x01,0x67,0xBB};
mySerial.write(data,9);
delay(100);
for(int i=0;i<9;i++){
if (mySerial.available()) {
data[i] = mySerial.read();
}
}
if(data[0]==0xAA && data[8]== 0xBB){
pm25 = data[4]*256 + data[5];
pm10 = data[2]*256 + data[3];
}
}
void pmOn(){
uint8_t data[] = {0xAA,0x01,0x00,0x00,0x00,0x00,0x01,0x66,0xBB};
mySerial.write(data,9);
}
void pmOff(){
uint8_t data[] = {0xAA,0x03,0x00,0x00,0x00,0x00,0x01,0x68,0xBB};
mySerial.write(data,9);
}
在代码中,用到了软串口,因为arduino的硬串口只有1个,不够这么多传感器同时使用。
二、GPS传感器
我使用的传感器采用U-BLOX NEO-6M模组,体积小巧。模块增加放大电路,有利于无源陶瓷天线快速搜星。
2.1接线说明
VCC接3.3V~5V
GND接GND
TX接arduino RX
RX接arduino TX
2.2数据格式
帧格式形如:$aaccc,ddd,ddd,…,ddd*hh(CR)(LF)
- “$”:帧命令起始位
- aaccc:地址域,前两位为识别符(aa),后三位为语句名(ccc)
- ddd…ddd:数据
- “*”:校验和前缀(也可以作为语句数据结束的标志)
- hh:校验和(check sum),$与*之间所有字符ASCII码的校验和(各字节做异或运算,得到校验和后,再转换16进制格式的ASCII字符)
- (CR)(LF):帧结束,回车和换行符
序号 | 命令 | 说明 | 最大帧长 |
---|---|---|---|
1 | $GPGGA | GPS定位信息 | 72 |
2 | $GPGSA | 当前卫星信息 | 65 |
3 | $GPGSV | 可见卫星信息 | 210 |
4 | $GPRMC | 推荐定位信息 | 70 |
5 | $GPVTG | 地面速度信息 | 34 |
6 | $GPGLL | 大地坐标信息 | |
7 | $GPZDA | 当前时间(UTC)信息 |
以GPRMC为例:
GPRMC(推荐定位信息,RecommendedMinimumSpecificGPS/TransitData)
G
P
R
M
C
(
推
荐
定
位
信
息
,
R
e
c
o
m
m
e
n
d
e
d
M
i
n
i
m
u
m
S
p
e
c
i
f
i
c
G
P
S
/
T
r
a
n
s
i
t
D
a
t
a
)
GPRMC语句的基本格式如下:
$GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)
(1) UTC时间,hhmmss(时分秒)
(2) 定位状态,A=有效定位,V=无效定位
(3) 纬度ddmm.mmmmm(度分)
(4) 纬度半球N(北半球)或S(南半球)
(5) 经度dddmm.mmmmm(度分)
(6) 经度半球E(东经)或W(西经)
(7) 地面速率(000.0~999.9节)
(8) 地面航向(000.0~359.9度,以真北方为参考基准)
(9) UTC日期,ddmmyy(日月年)
(10)磁偏角(000.0~180.0度,前导位数不足则补0)
(11) 磁偏角方向,E(东)或W(西)
(12) 模式指示(A=自主定位,D=差分,E=估算,N=数据无效)
举例如下:
$GPRMC,023543.00,A,2308.28715,N,11322.09875,E,0.195,,240213,,,A*78
2.3参考代码
int L = 13; //LED指示灯引脚
struct
{
char GPS_Buffer[80];
bool isGetData; //是否获取到GPS数据
bool isParseData; //是否解析完成
char UTCTime[11]; //UTC时间
char latitude[11]; //纬度
char N_S[2]; //N/S
char longitude[12]; //经度
char E_W[2]; //E/W
bool isUsefull; //定位信息是否有效
} Save_Data;
const unsigned int gpsRxBufferLength = 600;
char gpsRxBuffer[gpsRxBufferLength];
unsigned int ii = 0;
void setup() //初始化内容
{
Serial.begin(9600);
Serial.println("ILoveMCU.taobao.com");
Serial.println("Wating...");
Save_Data.isGetData = false;
Save_Data.isParseData = false;
Save_Data.isUsefull = false;
}
void loop() //主循环
{
gpsRead(); //获取GPS数据
parseGpsBuffer();//解析GPS数据
printGpsBuffer();//输出解析后的数据
}
void errorLog(int num)
{
Serial.print("ERROR");
Serial.println(num);
while (1)
{
digitalWrite(L, HIGH);
delay(300);
digitalWrite(L, LOW);
delay(300);
}
}
void printGpsBuffer()
{
if (Save_Data.isParseData)
{
Save_Data.isParseData = false;
Serial.print("Save_Data.UTCTime = ");
Serial.println(Save_Data.UTCTime);
if(Save_Data.isUsefull)
{
Save_Data.isUsefull = false;
Serial.print("Save_Data.latitude = ");
Serial.println(Save_Data.latitude);
Serial.print("Save_Data.N_S = ");
Serial.println(Save_Data.N_S);
Serial.print("Save_Data.longitude = ");
Serial.println(Save_Data.longitude);
Serial.print("Save_Data.E_W = ");
Serial.println(Save_Data.E_W);
}
else
{
Serial.println("GPS DATA is not usefull!");
}
}
}
void parseGpsBuffer()
{
char *subString;
char *subStringNext;
if (Save_Data.isGetData)
{
Save_Data.isGetData = false;
Serial.println("**************");
Serial.println(Save_Data.GPS_Buffer);
for (int i = 0 ; i <= 6 ; i++)
{
if (i == 0)
{
if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL)
errorLog(1); //解析错误
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
char usefullBuffer[2];
switch(i)
{
case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break; //获取UTC时间
case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; //获取UTC时间
case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break; //获取纬度信息
case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break; //获取N/S
case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break; //获取纬度信息
case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break; //获取E/W
default:break;
}
subString = subStringNext;
Save_Data.isParseData = true;
if(usefullBuffer[0] == 'A')
Save_Data.isUsefull = true;
else if(usefullBuffer[0] == 'V')
Save_Data.isUsefull = false;
}
else
{
errorLog(2); //解析错误
}
}
}
}
}
void gpsRead() {
while (Serial.available())
{
gpsRxBuffer[ii++] = Serial.read();
if (ii == gpsRxBufferLength)clrGpsRxBuffer();
}
char* GPS_BufferHead;
char* GPS_BufferTail;
if ((GPS_BufferHead = strstr(gpsRxBuffer, "$GPRMC,")) != NULL || (GPS_BufferHead = strstr(gpsRxBuffer, "$GNRMC,")) != NULL )
{
if (((GPS_BufferTail = strstr(GPS_BufferHead, "rn")) != NULL) && (GPS_BufferTail > GPS_BufferHead))
{
memcpy(Save_Data.GPS_Buffer, GPS_BufferHead, GPS_BufferTail - GPS_BufferHead);
Save_Data.isGetData = true;
clrGpsRxBuffer();
}
}
}
void clrGpsRxBuffer(void)
{
memset(gpsRxBuffer, 0, gpsRxBufferLength); //清空
ii = 0;
}
下一篇将介绍NB-IoT模块的使用。
最后
以上就是直率大白为你收集整理的基于nb-iot和arduino的气象站(二)基于nb-iot和arduino的气象站(二)PM2.5和GPS传感器的全部内容,希望文章能够帮你解决基于nb-iot和arduino的气象站(二)基于nb-iot和arduino的气象站(二)PM2.5和GPS传感器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复