最近接手了 公司之前同事做的一个项目.
用的是 树莓派,结合 温湿度传感器 和UPS采集 上报机房信息用的.
然后顺带开拓一下,搞个气体检测 玩玩.
环境说明
- AndroidThing 1.0.15 系统(虽然AndroidThings即将离我们远去,但是49年还能入一下国军不是~)
设备介绍
- 树莓派3B
- 某宝买的 7寸屏幕(不太好用,特么居然还得单独供电,不给我整合到HDMI里面去,而且触控还得单独插microUSB,差评!)
- 某宝买的 空气质量检测器(某宝找了个遍,发现全特么是这个,价格在140~150左右)
设备连接
很简单,我买的是UART的, 有4个引脚.
- VDD: 直接接5V的那个, 3V3的貌似不行,没试过,反正说明是说要5V
- GND: 接地就行,没啥好说的.
- NC: 空着,不用插.
- TX: 接GPIO15,也就是 UART RX.
开发
这个没啥好说的,说明书上面已经写好了 波特率、数据位、校验位、停止位. 照着搞就行.
这是提供的通信协议,其实写的很清楚了.
需要其中关键的就是 数据解析和数据校验.
我贴一下关键代码吧.
/**
* 通过UART获取传输过来的数据
*/
public void readUartBuffer(UartDevice uart){
byte[] buffer = new byte[33];
int index = -1;
try {
uart.read(buffer, buffer.length);
//遍历一下数据,找一下 帧头.
for (int i = 0; i < buffer.length; i++) {
if (buffer[i] == 60 && i + 1 < 33 && buffer[i + 1] == 2) {
//数据不对,越界了,丢弃~
if (i + 16 > 33) {
return;
}
index = i;
}
}
if (index == -1) {
return;
}
//sleep一下,因为从uart读取数据到byte[]里面需要时间,避免太快导致 拿到的都是0000000
Thread.sleep(400);
float[] compress = compress(buffer, index);
if (checkData(compress)) {
callBack.callBack(compress);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 对应数据的起点 index
*/
private float[] compress(byte[] data, int index) {
float[] result = new float[7];
try {
//温度
result[0] = data[index + 12] + data[index + 13] / 100f;
//湿度
result[1] = data[index + 14] + data[index + 15] / 100f;
//二氧化碳
result[2] = (0xFF & data[index + 2]) * 256 + (0xFF & data[index + 3]);
//甲醛
result[3] = (0xFF & data[index + 4]) * 256 + (0xFF & data[index + 5]);
//TVOC
result[4] = (0xFF & data[index + 6]) * 256 + (0xFF & data[index + 7]);
//PM2.5
result[5] = (0xFF & data[index + 8]) * 256 + (0xFF & data[index + 9]);
//PM10
result[6] = (0xFF & data[index + 10]) * 256 + (0xFF & data[index + 11]);
} catch (Exception e) {
e.printStackTrace();
} finally {
return result;
}
}
贴的代码,分别是
- uart读取数据
按照文档说明,一次完整的数据是 17位,所以我一次读取33个byte, - 寻找帧头
按照之前返回的数据来看,并不是每一次帧头都在前面,需要遍历找一下位置. - 解析数据.
高字节使用 (0xFF & data) * 256 的方式处理,低字节使用 (0xFF & data).
踩坑记录
这是我接入这个遇到的最大的坑.
具体表现是:
- 重新运行程序,前2次数据是正常的,后面数据全部是60 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-
断点调试,60%的概率数据是OK的,但是取消断点,数据就又是00000了
既然断点数据是OK的,不打断的就出问题,那么问题一定是出在 代码执行时间上面了.
其实整个采集显示流程是:
uart返回数据 --> 读取uart数据 --> 数据解析 --> 解析数据校验合法性 --> 显示UI
只需要再 读取uart数据 --> 数据解析之间,加上一个sleep,休息个几百毫秒即可解决问题.
实际上并不是标准的2秒,建议还是 自己加一个时间判断, 我是间隔10秒读取一次即可,没必要太频繁.
成品预览
代码已上传至GitHub
项目地址
欢迎大家star,fork