Home BeagleBone Black 用 DHT22 测量温湿度
Post
Cancel

BeagleBone Black 用 DHT22 测量温湿度

BeagleBone Black 安装 OpenWrt 后还可以把空闲的 DHT22 也利用上,即当软路由又当温湿度计。

DHT22 Datasheet

器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由数据线完成。

步骤一:

AM2302 上电后( AM2302 上电后要等待 2S 以越过不稳定状态,在此期间读取设备不能发送 任何指令),测试环境温湿度数据,并记录数据,此后传感器自动转入休眠状态。AM2302 的 SDA 数据线由上拉电阻拉高一直保持高电平,此时 AM2302 的 SDA 引脚处于输入状态,时刻检测外部信号。

步骤二:

微处理器的 I/O 设置为输出, 同时输出低电平,且低电平保持时间不能小于 800us,典型值是拉低 1MS,然后微处理器的 I/O 设置为输入状态,释放总线,由于上拉电阻,微处理器的 I/O 即 AM2302 的 SDA 数据线也随之变高,等主机释放总线后,AM2302 发送响应信号,即输出 80 微秒的低电平作为应答信号,紧接着输出 80 微秒的高电平通知外设准备接收数据。

步骤三:

AM2302 发送完响应后,随后由数据总线 SDA 连续串行输出 40 位数据,微处理器根据 I/O 电 平的变化接收 40 位数据。

位数据“0”的格式为: 50 微秒的低电平加 26-28 微秒的高电平;

位数据“1”的格式为: 50 微秒的低电平加 70 微秒的高电平;

树莓派上使用 DHT22 比较简单,网上帖子一搜就有,我也做了个:dht22

但在安装 Openwrt 系统的 BBB 上使用 DHT22 就费了劲了,主要原因是:BBB 的 OpenWrt 装不上现成的 python 库,具体原因也没找到,可能是 gcc(7.4.0) 跟 python 版本没对上。最后,无奈只能尝试用现有 python 库底层用的 c 代码交叉编译后在放到 BBB 上运行。

1. 已有 python 库

如果不是 Openwrt 系统,可以先尝试使用两个现有库:

2. 交叉编译

因为 Adafruit_Python_DHT 库读 DHT22 数据的核心操作是在底层 c 语言的代码里,所以在现有 python 库安装不上的情况下,可以通过交叉编译在本地机器上生成可执行的二进制文件,再丢到 BBB 上执行。具体步骤:

  1. 添加 DEVMEM 到 kernel

    Adafruit_Python_DHT 的底层 c 语言需要用到 /dev/mem,因此编译 OpenWrt 时需要增加 DEVMEM。

    1
    
    CONFIG_KERNEL_DEVMEM=y
    
  2. 生成交叉编译工具

    在编译 OpenWrt make menuconfig 时,做如下勾选:

    toolchain

    或者在 .config 文件中添加:

    1
    
    CONFIG_MAKE_TOOLCHAIN=y
    

    这样编译出来的 OpenWrt 包里就有 toolchain 了。

  3. 安装交叉编译工具

    把 toolchain 包解压到某个路径并添加环境变量就可以了。

    1
    2
    3
    
    tar -xjvf openwrt-toolchain-omap_gcc-8.4.0_musl_eabi.Linux-x86_64.tar.bz2 -C ~/bin/
    export PATH=~/bin/openwrt-toolchain-omap_gcc-8.4.0_musl_eabi.Linux-x86_64/toolchain-arm_cortex-a8+vfpv3_gcc-8.4.0_musl_eabi/bin:$PATH
    export STAGING_DIR=~/bin/openwrt-toolchain-omap_gcc-8.4.0_musl_eabi.Linux-x86_64/toolchain-arm_cortex-a8+vfpv3_gcc-8.4.0_musl_eabi/bin:$STAGING_DIR
    
  4. 测试工具

    确保以下命令能正确输出 gcc 版本 8.4.0

    1
    
    arm-openwrt-linux-gcc -v
    

    再本地交叉编译个 hellworld 丢到 BBB 上执行,用 arm-openwrt-linux-gcc helloworld.c -o helloworld 编译以下 c 代码,生成 helloworld。

    1
    2
    3
    4
    5
    6
    
    #include <stdio.h>
       
    int main(void) {
        printf("Hello World!\n");
        return 0;
    }
    

    scp 到 BBB 上,再 ssh 登陆 BBB 执行:xxx/xxx/helloworld 看结果。

3. 调整代码

交叉编译工具搞定之后就是简单调整下 Adafruit_Python_DHT 库里的 c 代码。目录结构:

1
2
3
4
5
6
7
8
|-- lib
|   |-- bbb_dht_read.c
|   |-- bbb_dht_read.h
|   |-- bbb_mmio.c
|   |-- bbb_mmio.h
|   |-- common_dht_read.c
|   `-- common_dht_read.h
`-- main.c

lib 目录下的都是从 Adafruit_Python_DHT 里 copy 出来的,只需要改个头文件路径。

main.c 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>

#include "lib/bbb_dht_read.h"

int main(void) {
    int sensor = 22;
    int base = 1, number = 28;
    float humidity = 0, temperature = 0;
    char hum[10], temp[10];

    int result = bbb_dht_read(sensor, base, number, &humidity, &temperature);

    memset(hum, 0, sizeof(hum));
    memset(temp, 0, sizeof(temp));
    sprintf(hum, "%.2f", humidity);
    sprintf(temp, "%.2f", temperature);
    printf("[%s, %s]\n", hum, temp);
    
    return result;
}

编译命令:arm-openwrt-linux-gcc main.c lib/* -o dht22

执行结果:[99.90, 14.20]

4. Web

有了温湿度计的可执行程序,再用 go 仿照 dht22 做个 web server,让 bbb 启动后就可以提供显示温湿度的 web 服务。

代码:dht22-bbb,目前 dht22 数据脚接的是固定的 P9_12(GPIO_60)口,见下图。

beaglebone-black-pinout

进入目录,输入命令编译:CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-openwrt-linux-gcc go build -o dht22 main.go,其中 CC 就是交叉编译的 gcc 工具。

把编译好的 dht22 可执行文件以及 static 文件夹拷备到 bbb 上,输入命令启动:./dht22 -root=/static 文件路径/ -port=xxxx,-root 参数用来指定 static 文件夹的路径,-port 参数用来指定 web server 端口(默认值是 8081)。

开机启动:编辑 /etc/rc.local 文件,在 exit 0 之前加入 dht22 的启动命令即可。

go 调用 c

两篇官方文档:C? Go? Cgo!cgo

一篇中文博客:Go调用C程序及arm平台交叉编译

This post is licensed under CC BY 4.0 by the author.