基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录

最近接手了 公司之前同事做的一个项目.
用的是 树莓派,结合 温湿度传感器 和UPS采集 上报机房信息用的.
然后顺带开拓一下,搞个气体检测 玩玩.

环境说明

  • AndroidThing 1.0.15 系统(虽然AndroidThings即将离我们远去,但是49年还能入一下国军不是~)

设备介绍

  • 树莓派3B
  • 某宝买的 7寸屏幕(不太好用,特么居然还得单独供电,不给我整合到HDMI里面去,而且触控还得单独插microUSB,差评!)
  • 某宝买的 空气质量检测器(某宝找了个遍,发现全特么是这个,价格在140~150左右)
    基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录

设备连接

很简单,我买的是UART的, 有4个引脚.

  • VDD: 直接接5V的那个, 3V3的貌似不行,没试过,反正说明是说要5V
  • GND: 接地就行,没啥好说的.
  • NC: 空着,不用插.
  • TX: 接GPIO15,也就是 UART RX.
    基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录

开发

  1. UART连接,通信

这个没啥好说的,说明书上面已经写好了 波特率、数据位、校验位、停止位. 照着搞就行.

  1. 获取数据处理

基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录
这是提供的通信协议,其实写的很清楚了.
需要其中关键的就是 数据解析和数据校验.

我贴一下关键代码吧.

/**
     * 通过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).

踩坑记录

  1. 为什么我一开始获取的数据是正常的,后面获取的都是00000000000 ?

这是我接入这个遇到的最大的坑.
具体表现是:

  • 重新运行程序,前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,休息个几百毫秒即可解决问题.

  1. 这数据文档说是2秒给一次,实际并不是,有时快,有时慢?

实际上并不是标准的2秒,建议还是 自己加一个时间判断, 我是间隔10秒读取一次即可,没必要太频繁.

成品预览

基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录
基于AndroidThings接入空气质量检测器(温度,湿度,二氧化碳,甲醛,TVOC,PM2.5,PM10)记录
代码已上传至GitHub
项目地址
欢迎大家star,fork

上一篇:龙芯LS1C101单片机实验(1)--UART


下一篇:十一、UART&TTY驱动