树莓派使用 NodeJS 读取并监控 DHT11/22 温度湿度传感器
本文详细介绍了如何在树莓派上使用 nodejs 读取 dht11/22/AM2302 温度湿度传感器,并提供完整的驱动包,真正的开箱即用。并且介绍了如何使用 RxJS 以观察者模式监控温度和湿度的变化,并发出通知。
dht11 温度湿度传感器使用很广泛,价格也相对便宜,并且使用单总线传输数据,这使得编写驱动变得容易不少。下面我们会重点介绍如何去监控温度和湿度的变化,并且在达到触发条件时发出通知,从而达到自动化控制的目的。除此之外,作者也会提供封装好的 RxJS 包,让开发变得更容易。
先介绍一下 DHT11 传感器,这个模块使用单总线进行数据传输,并且输出的是数字信号,意外着我们只需要一个 GPIO 口就能读取温度和湿度了。
上面的图片是本店中出售的 DHT11 温度湿度传感器,电源支持 3.3v - 5v,可用在树莓派、51单片机、stm32、arduino、ESP系列上。
下面是该传感器的详细介绍:
下面我们使用 NodeJS 的 rx-dht-sensor 库来驱动传感器。感谢开源社区和作者给我们提供这么好用的库。
安装驱动库
我们在树莓派上默认使用 nodejs (v8.10.0) 进行安装和使用。当然其它版本也是可以的。如果你的树莓派还没有 nodejs 环境,请先 下载 nodejs,然后参照这个 安装 nodejs。
假设到这里 nodejs 环境已经准备好了。
$ cd your-project-dir
$ npm install rx-dht-sensor
上面的命令会在当前目录下安装 rx-dht-sensor 包。
硬件接线
该传感器仅需要 3 根线就可以,其中 2 根是电源,另外 1 根是 data
。下面是树莓派的默认接线图。
注意:请一定注意电源正负极。电源反接必烧毁。 本模块兼容 3.3v 和 5v,树莓派的 3.3v 可能由于电源质量问题,实际不足数。如发现传感器读数偏差较大或不稳定工作,可接到 5v 引脚上。 其它店铺购买的模块,请一定确认清楚电源,理论上 3.3v 的模块接 5v 必定会烧毁的。本人不负责。
至此,传感器的线接好了,下面开始写程序读取传感器的值。
hello dht! 代码
新建 hello-dht.js 文件,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var DHTSeries = require('rx-dht-sensor');
// 创建驱动实例
var dht11 = new DHTSeries({
model: 'dht11',
address: 4
});
// 简单的使用 fetch 方法读取传感器的值,如读取失败,err 参数不为 null
dht11.fetch(function (err, temperature, humidity) {
if (err) {
return console.error('a error occur when read dht-sensor:', err);
}
console.log('temperature: ' + temperature.toFixed(1) + ', humidity: ' + humidity.toFixed(1));
});
然后使用下面命令运行它:
$ node hello-dht.js
如果没有显示传感器的值,检查传感器的接线是否正确。如果程序有报错,能看懂的错误自己解决,看不懂的请在文章下面留言,或使用页面右下角的站内信邮件。在本店购买的用户,有问题请直接联系旺旺客服或售后技术群,将会第一时间给你解答。
如果显示:a error occur when read dht-sensor:
,使用 ctrl + c
中断程序,然后多重试几次。这可能是由于数据传输不稳定造成的。
驱动支持型号:dht11, dht22, am2302
address:GPIO BCM 编号
使用观察者模式监控数值
上面我们使用了 fetch 方法一次性读取传感器的数值,主要是测试一下驱动是否正常。通常,我们使用温度湿度传感器都需要一直读取它,以达到实时更新的目的。比如屏幕上实时更新、自动化控制等。
下面我们使用驱动提供的观察者模式,来自动完成这些功能。
实时刷新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var DHTSeries = require('rx-dht-sensor');
// 创建实例
var dht11 = new DHTSeries({
model: 'dht11',
address: 4
});
// 每隔 2000毫秒(2秒) 刷新一次
var observable = dht11.observe(2000);
// 开始实时刷新,把结果打印出来
var subscription = observable.then(function subscribe(value) {
console.log('temperature: ' + value.t.toFixed(1) + ', humidity: ' + value.h.toFixed(1));
}, function onError(err) {
console.error('dht-sensor monitoring error.');
});
// 如果想停止刷新,可以使用 dispose() 停止.
// subscription.dispose()
提示:上面出现了一些陌生的词语,如果你只是想学会怎么使用,那你完全可以忽略它们。如果你想更深入了解,你可以学习 RxJS,然后在 GitHub 查看 then 操作符的源代码。
上面我们使用 RxJS 提供的观察者模式进行监控数据。使用 observe(interval, type=’all’) 同时进行温度和湿度的监控。
observe 会返回 observable(观察者) 对象,然后我们订阅温度和湿度的值。
注意: observe 只返回 观察者,此时它并不会真正的去读取传感器的数值,因为 观察者 是惰性的,现在还没有人订阅它。 必须使用驱动提供的 then 操作符去订阅它,或者使用 RxJS 自带的 subscribe 函数订阅。
订阅后,每隔 2s 就会打印 温度和湿度 的数值。如果想根据温度和湿度的变化进行一系列的操作,就可以在 then 回调函数里面进行。
observe 可以同时监控温度和湿度,也可以只监控 温度 (t
) 或者 湿度 (h
),通过 type 来筛选。
只监控 温度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var DHTSeries = require('rx-dht-sensor');
// 创建实例
var dht11 = new DHTSeries({
model: 'dht11',
address: 4
});
// 每隔 2000毫秒(2秒) 刷新一次,只监听 温度
var observable = dht11.observe(2000, 't');
// 开始实时刷新,把结果打印出来
var subscription = observable.then(function subscribe(value) {
console.log('temperature: ' + value.toFixed(1));
}, function onError(err) {
console.error('dht-sensor monitoring error.');
});
// 如果想停止刷新,可以使用 dispose() 停止.
// subscription.dispose()
当你指定了 type 后,返回的 value 值是不同的,请注意取值,否则会发生 undefined 报错。
当然,驱动提供了常用的操作符用于简化业务代码。下面我们介绍驱动提供的几种操作符。
操作符
max: 当数值大于设定条件的时候触发
1
2
3
4
// 只有当温度大于 28 度时才会触发 then 回调函数
var subscription = dht11.observe(2000, 't').max(28).then(function(value){
console.log('好热啊!当前温度是: ', value);
});
min: 当数值小于设定条件的时候触发
1
2
3
4
// 只有当湿度小于 20% 时才会触发 then 回调函数
var subscription = dht11.observe(2000, 'h').min(20).then(function(value){
console.log('好干燥啊!当前湿度是: ', value);
});
when: 当数值等于给定条件的时候触发
1
2
3
4
// 只有当温度等于 20度 时才会触发 then 回调函数
var subscription = dht11.observe(2000, 't').when(20).then(function(value){
console.log('设定的温度到了!当前温度是: ', value);
});
between: 当数值大于左区间并且小于右区间的时候触发
1
2
3
4
// 只有当温度 大于20度 并且 小于26度 时才会触发 then 回调函数
var subscription = dht11.observe(2000, 't').between(20, 26).then(function(value){
console.log('当前温度是: ', value);
});