ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Johnny-Five Multi 温湿度一体读取:DHT22 I2C Nano Backpack 控制器完全指南

2026/9/23 16:02:29 拓冰建站 浏览量
Johnny-Five Multi 温湿度一体读取:DHT22 I2C Nano Backpack 控制器完全指南 Johnny-Five Multi 温湿度一体读取DHT22 I2C Nano Backpack 控制器完全指南【免费下载链接】johnny-fiveJavaScript Robotics and IoT programming framework, developed at Bocoup.项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five导读本文以 Johnny-Five 官方文档 docs/multi-DHT22_I2C_NANO_BACKPACK.md 为核心围绕Multi组件配合DHT22_I2C_NANO_BACKPACK控制器讲解如何通过一个 I2C 转接板Backpack同时读取 DHT22 温湿度传感器的温度与相对湿度数据。读完本文你将掌握该控制器的完整接线方案、Multi/Thermometer/Hygrometer三种使用姿势、底层 I2C 数据流与固件烧录原理并能够直接在命令行运行仓库内的示例程序。一、场景为什么 DHT22 需要 I2C 转接板DHT22AM2302本身是一款单总线1-Wire数字温湿度传感器其 DATA 引脚以自定义单总线时序输出数据不直接兼容标准的 I2CSDA/SCL总线。直接读取 DHT 系列传感器需要精确的时序控制这在某些平台上并不方便。为此Johnny-Five 仓库在 firmwares/dht_i2c_nano_backpack.ino 中提供了一套 Arduino Nano 固件把 DHT 传感器包装成一个 I2C 从设备Backpack主机只需通过 I2C 写入目标引脚与 DHT 型号再读取 4 字节数据即可拿到温湿度结果。这样DHT22 的读取就从单总线时序变成了标准的 I2C 读写对上层 JavaScript 代码完全透明。DHT22_I2C_NANO_BACKPACK正是 Johnny-Five 中对接该固件的控制器名称。从源码看Multi、Thermometer、Hygrometer三个组件都注册了这一控制器lib/thermometer.jsControllers.DHT22_I2C_NANO_BACKPACK Controllers.DHT_I2C_NANO_BACKPACKlib/hygrometer.jsControllers.DHT22_I2C_NANO_BACKPACK Controllers.DHT_I2C_NANO_BACKPACKlib/sip.jsDrivers.DHT22_I2C_NANO_BACKPACK Drivers.DHT_I2C_NANO_BACKPACK同一套控制器还以别名方式服务于 DHT11 与 DHT21见 lib/sip.js本文以 DHT22 为例展开。二、硬件接线I2C Backpack 的四个关键点原文档提供了面包板接线图上文插图与 Fritzing 源文件docs/breadboard/multi-DHT22_I2C_NANO_BACKPACK.fzz以及对应的 multi-DHT22_I2C_NANO_BACKPACK.png。接线核心要点如下连接说明5V → VCC为 I2C 转接板与 DHT22 供电GND → GND共地参考SDA → A4数据线接入主控 I2C 数据引脚Arduino UNO 默认SCL → A5时钟线接入主控 I2C 时钟引脚Arduino UNO 默认关于 I2C 地址需要特别注意两点默认地址 0x0A驱动在 lib/sip.js 中声明ADDRESSES: { value: [0x0A] }。固件同样以I2C_DEFAULT_ADDRESS 0x0A作为默认从机地址见 firmwares/dht_i2c_nano_backpack.ino。地址可扩展固件通过 AD0引脚 11与 AD1引脚 12两个地址引脚读取偏移量在 0x0A 基础上累加见 firmwares/dht_i2c_nano_backpack.ino从而支持挂载多个 Backpack。当多个转接板共存时可在options中显式指定address由Drivers.addressResolver解析lib/sip.js。三、烧录固件把 Arduino Nano 变成 I2C 从设备在运行任何 Node.js 示例之前需要先把固件烧录到 Arduino Nano。固件源码位于 firmwares/dht_i2c_nano_backpack.ino其核心逻辑通过Wire.begin(address)以从机模式启动 I2C第 51 行主机i2cWrite发送[pin, type]两个字节后触发onReceive设置dhtPin与dhtType第 98-110 行主循环每 250ms 读取一次 DHT将湿度与温度各放大 100 倍后拆成两个字节写入发送缓冲区第 56-84 行主机i2cRead时触发onRequest一次性写出 4 字节[H_MSB, H_LSB, T_MSB, T_LSB]第 94-96 行。缓冲区布局在固件头部注释中给出第 14-17 行0H LSB、1H MSB、2T LSB、3T MSB也就是说 4 字节的顺序是湿度高位、湿度低位、温度高位、温度低位。该固件依赖 Arduino 的DHT库#include DHT.h烧录前需安装该库。四、运行示例命令行一条命令启动原文档给出了官方的命令行运行方式直接执行node eg/multi-DHT22_I2C_NANO_BACKPACK.js前提是已在仓库根目录执行过依赖安装npm install且 Arduino 开发板已通过串口连接。该示例源码位于 eg/multi-DHT22_I2C_NANO_BACKPACK.jsvar five require(../); var board new five.Board(); board.on(ready, function() { var multi new five.Multi({ controller: DHT22_I2C_NANO_BACKPACK, pin: 2, }); multi.on(change, function() { console.log(Thermometer); console.log( celsius : , this.thermometer.celsius); console.log( fahrenheit : , this.thermometer.fahrenheit); console.log( kelvin : , this.thermometer.kelvin); console.log(--------------------------------------); console.log(Hygrometer); console.log( relative humidity : , this.hygrometer.relativeHumidity); console.log(--------------------------------------); }); });代码要点pin: 2指定 DHT22 连接到 Backpack 上的引脚号。该值通过 I2C 写入固件固件用它对 DHT 库进行初始化firmwares/dht_i2c_nano_backpack.ino。若省略pin驱动默认取 2见 lib/sip.js。multi.on(change, ...)在温度或湿度发生变化时触发通过this.thermometer与this.hygrometer两个子组件访问数据。fahrenheit与kelvin是派生属性由celsius换算而来lib/thermometer.js。五、另一种姿势拆分成 Thermometer 与 Hygrometer 单独使用Multi是把Thermometer与Hygrometer组合在一起的复合组件。原文档仓库中还提供了两个单组件示例适合只关注单一物理量的场景温度专用eg/temperature-DHT22_I2C_NANO_BACKPACK.js对应文档 docs/temperature-DHT22_I2C_NANO_BACKPACK.mdconst { Board, Thermometer } require(../lib/johnny-five.js); const board new Board(); board.on(ready, () { const thermometer new Thermometer({ controller: DHT22_I2C_NANO_BACKPACK }); thermometer.on(change, () { const {celsius, fahrenheit, kelvin} thermometer; console.log(Thermometer); console.log( celsius : , celsius); console.log( fahrenheit : , fahrenheit); console.log( kelvin : , kelvin); console.log(--------------------------------------); }); });湿度专用eg/hygrometer-DHT22_I2C_NANO_BACKPACK.js对应文档 docs/hygrometer-DHT22_I2C_NANO_BACKPACK.mdvar five require(../); var board new five.Board(); board.on(ready, function() { var hygrometer new five.Hygrometer({ controller: DHT22_I2C_NANO_BACKPACK }); hygrometer.on(change, function() { console.log(Hygrometer); console.log( relative humidity : , this.relativeHumidity); console.log(--------------------------------------); }); });对应命令行运行方式node eg/temperature-DHT22_I2C_NANO_BACKPACK.js node eg/hygrometer-DHT22_I2C_NANO_BACKPACK.js值得注意的是即使只实例化Thermometer或Hygrometer底层 I2C 驱动依然完整读取 4 字节数据只是各组件只消费自己关心的字段温度组件取{temperature}湿度组件取{humidity}见 lib/thermometer.js 与 lib/hygrometer.js。六、底层原理从 I2C 字节流到物理量6.1 数据帧格式主机每次从地址 0x0A 读取 4 字节驱动将其解析为两个有符号 16 位整数lib/sip.jsio.i2cWrite(address, [dhtPin, dhtType]); io.i2cRead(address, 4, data { computed.humidity int16(data[0], data[1]); // H 高字节, H 低字节 computed.temperature int16(data[2], data[3]); // T 高字节, T 低字节 this.emit(data, computed); });其中int16(msb, lsb)将两个字节组合成带符号 16 位整数lib/fn.js。6.2 型号识别从控制器名提取 DHT 类型驱动从options.controller中通过正则/(\d{2})/提取两位数型号据此决定dhtTypelib/sip.jsconst dhtVariantExec /(\d{2})/.exec(options.controller); const dhtVariant dhtVariantExec dhtVariantExec.length dhtVariantExec[0]; if (dhtVariant) { dhtType dhtVariant; }因此DHT22_I2C_NANO_BACKPACK会把dhtType设为 22 并写入固件固件据此实例化DHT dht(dhtPin, dhtType)。DHT11_I2C_NANO_BACKPACK与DHT21_I2C_NANO_BACKPACK同理这也是三个控制器共享同一驱动的原因。6.3 数值换算为什么读数要先除以 100固件在把物理量写入缓冲区前先放大 100 倍firmwares/dht_i2c_nano_backpack.inoint h (int)((float)dht.readHumidity() * 100); int c (int)((float)dht.readTemperature() * 100);对应的上层换算逻辑乘以 100 的逆运算温度round(raw / 100)见 lib/thermometer.js换算结果精度为 0.01℃湿度toFixed(raw / 100, 1)见 lib/hygrometer.js换算结果保留一位小数对应 DHT22 0.1%RH 的分辨率。6.4 事件节流data 与 change 的区别驱动在固件每 250ms 的新数据到达时立刻emit(data)。而组件层面还做了一层节流Thermometer默认以freq: 25毫秒周期轮询原始值data事件每个周期都发仅当celsius数值变化时才发changelib/thermometer.jsHygrometer同样以freq默认 25ms轮询仅当relativeHumidity变化时发changelib/hygrometer.js。所以示例程序里监听change是推荐做法可避免对未变化的读数做无意义输出如需完整采样流可改用data事件。6.5 驱动复用多组件共享同一 I2C 会话Drivers.get会按dht_i2c_nano_backpack-address作为键缓存驱动实例lib/sip.js、lib/sip.js。当Multi同时实例化Thermometer与Hygrometer时两者都请求同一个驱动实际只建立一次 I2C 通信两个子组件共享同一份数据流这正是 lib/sip.js 中DHT_I2C_NANO_BACKPACK控制器声明components: [HYGROMETER, THERMOMETER]的设计意图。七、进阶多个 Backpack 与自定义地址固件支持通过 AD0/AD1 引脚调整从机地址详见本文第二节。当总线上挂载多个 Backpack 时可结合board-sampling-interval之类的 I2C 配置为每个组件显式指定addressvar multiA new five.Multi({ controller: DHT22_I2C_NANO_BACKPACK, address: 0x0A, pin: 2, }); var multiB new five.Multi({ controller: DHT22_I2C_NANO_BACKPACK, address: 0x0B, pin: 3, });地址解析逻辑见Drivers.addressResolverlib/sip.js优先使用options.address否则回退到驱动默认的ADDRESSES首项 0x0A。驱动缓存键中包含地址因此不同地址的 Backpack 会被视为不同驱动实例互不干扰。八、常见问题排查示例无输出先确认 Backpack 固件已正确烧录Wire.begin的从机地址与驱动默认 0x0A 一致并确认 DHT22 接线正确供电、GND、DATA 到 Backpack 指定引脚。读数为 0 或 NaN检查pin是否与 DHT22 实际连接的 Backpack 引脚一致检查固件侧dhtPin是否在onReceive中被正确设置。需要修改采样间隔固件固定每 250ms 刷新一次数据firmwares/dht_i2c_nano_backpack.ino上层freq只控制事件轮询频率不改变传感器采样率。九、相关文档与源码索引示例文档docs/multi-DHT22_I2C_NANO_BACKPACK.md、docs/temperature-DHT22_I2C_NANO_BACKPACK.md、docs/hygrometer-DHT22_I2C_NANO_BACKPACK.md示例程序eg/multi-DHT22_I2C_NANO_BACKPACK.js、eg/temperature-DHT22_I2C_NANO_BACKPACK.js、eg/hygrometer-DHT22_I2C_NANO_BACKPACK.js固件源码firmwares/dht_i2c_nano_backpack.ino核心实现lib/sip.jsI2C 驱动、lib/thermometer.js温度换算、lib/hygrometer.js湿度换算面包板图与 Fritzing 源文件docs/breadboard/multi-DHT22_I2C_NANO_BACKPACK.png、docs/breadboard/multi-DHT22_I2C_NANO_BACKPACK.fzz【免费下载链接】johnny-fiveJavaScript Robotics and IoT programming framework, developed at Bocoup.项目地址: https://gitcode.com/gh_mirrors/jo/johnny-five创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考