BeagleBone Black 安装 OpenWrt 后还可以把空闲的 DHT22 也利用上,即当软路由又当温湿度计。
器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由数据线完成。
步骤一:
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 系统,可以先尝试使用两个现有库:
- Adafruit_Python_DHT,这个库已经不再维护了,但库本身还是好用的。
- Adafruit_CircuitPython_DHT,这个库是目前一个比较活跃的社区在做的,它需要安装一些依赖库,具体安装和使用:Installing CircuitPython Libraries on Raspberry Pi or BeagleBone Black
2. 交叉编译
因为 Adafruit_Python_DHT 库读 DHT22 数据的核心操作是在底层 c 语言的代码里,所以在现有 python 库安装不上的情况下,可以通过交叉编译在本地机器上生成可执行的二进制文件,再丢到 BBB 上执行。具体步骤:
添加 DEVMEM 到 kernel
Adafruit_Python_DHT 的底层 c 语言需要用到 /dev/mem,因此编译 OpenWrt 时需要增加 DEVMEM。
1
CONFIG_KERNEL_DEVMEM=y
生成交叉编译工具
在编译 OpenWrt
make menuconfig
时,做如下勾选:或者在 .config 文件中添加:
1
CONFIG_MAKE_TOOLCHAIN=y
这样编译出来的 OpenWrt 包里就有 toolchain 了。
安装交叉编译工具
把 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
测试工具
确保以下命令能正确输出 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)口,见下图。
进入目录,输入命令编译: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平台交叉编译