基于树莓派的空气监测系统(3)PM2.5模块程序
PM2.5模块(SHARP 灰尘传感器GP2Y1051AU0F)
灰尘传感器的主要参数
- 光学原理,能够探测1微米以上的粉尘粒子;
- 5VDC供电;
- 串口通信(5V);
原理:微粒和分子在光的照射下会产生光的散射现象,和此同时,还吸收部分照射光的能量。当一束平行单色光入射到被测颗粒场时,会受到颗粒周围散射和吸收的影响,光强将被衰减。如此一来便可求得入射光通过待测浓度场的相对衰减率。而相对衰减率的大小基本上能线性反应待测场灰尘的相对浓度。光强的大小和经光电转换的电信号强弱成正比,通过测得电信号就可以求得相对衰减率。
树莓派3B串口设置
树莓派串口说明
树莓派从大的方向来说一共出了3代,每一代的CPU外设基本相同,但内核不同,外设里面一共包含两个串口,一个称之为硬件串口(/dev/ttyAMA0),一个称之为mini串口(/dev/ttyS0)。
硬件串口由硬件实现,有单独的波特率时钟源,性能高、可靠,mini串口性能低,功能也简单,并且没有波特率专用的时钟源而是由CPU内核时钟提供,因此mini串口有个致命的弱点是:波特率受到内核时钟的影响。
对于树莓派3 B+ 来说,它的uart 功能有三种: 1、内部蓝牙使用 2、控制终端使用 3、与其他设备进行串口通信;
树莓派 3 只提供一个硬件 uart,对应硬件接口 GPIO14-Tx/GPIO15-Rx。硬件串口被默认分配给与蓝牙模块通信了,而把那个mini串口默认分配给了排针引出的GPIO Tx Rx。
树莓派3串口默认映射对换
1.查看/boot/overlays/目录下是否有pi3-miniuart-bt-overlay.dtb(或者pi3-miniuart-bt.dtbo)文件。
(这个文件的功能是将树莓派3的蓝牙切换到mini串口(ttyS0),并且恢复硬件串口(ttyAMA0)到GPIO 14&15脚中。并且给出了载入的方法。)
2.编辑/boot目录下的config.txt文件
sudo vim /boot/config.txt
dtoverlay=pi3-miniuart-bt-overlay
保存文件,重启树莓派使之生效。
- 默认映射
- 修改后的映射
禁用串口的控制台功能
编辑/boot目录下的cmdline.txt文件,把console=serial0,115200删掉console=serial0,115200。
串口程序
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
//串口初始化
void init_tty(int fd)
{
struct termios newtio;
struct termios oldtio;
bzero(&newtio,sizeof(struct termios));
tcgetattr(fd,&oldtio);
newtio.c_cflag |= CLOCAL | CREAD;
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
printf("c_cflag=%x\n",newtio.c_cflag);
newtio.c_cflag &= ~CSIZE;
printf("c_cflag=%x\n",newtio.c_cflag);
newtio.c_cflag |= CS8;
printf("c_cflag=%x\n",newtio.c_cflag);
newtio.c_cflag &= ~PARENB;
newtio.c_iflag &= ~INPCK;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
//设置原始模式
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
newtio.c_oflag &= ~OPOST; /*Output*/
//设置终端模式
//newtio.c_lflag |= (ICANON | ECHO | ECHOE | ISIG); /*Input*/
//newtio.c_oflag |= OPOST; /*Output*/
tcflush(fd,TCIOFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
}
//PM2.5模块数据处理
int da_pro(char* da_buf)
{
unsigned char crr;
double vout;
int ud,i;
if(da_buf==NULL)
return -1;
for(i=0;i<10;i++){
if(da_buf[i]==0xAA)
break;
}
if(da_buf[i+0] != 0xAA || da_buf[i+6]!= 0xFF)
return -1;
crr = da_buf[i+1] + da_buf[i+2] + da_buf[i+3] + da_buf[i+4];
if(da_buf[i+5] != crr)
return -1;
vout = (da_buf[i+1]*256+da_buf[i+2])/1024.0*8.0;
ud = 800 * vout;
return ud;
}
int main()
{
int i;
int fd = -1;
int ret = -1;
int pm;
char buf[16];
fd = open("/dev/ttyAMA0",O_RDWR);
if(fd < 0){
printf("没有串口设备/dev/ttyAMA0\n");
exit(1);
}
printf("fd=%d\n",fd);
init_tty(fd);
while(1){
bzero(buf,16);
if(read(fd,buf,15)>0){
for(i=0;i<15;i++){
// printf(" %X ",buf[i]);
}
pm = 0;
pm=da_pro(buf);
if(pm==-1)
printf("recv data err...\n");
else
printf("PM2.5 = %d\n",pm);
}
usleep(300*1000);
}
close(fd);
}