本博客已停止维护,仅供浏览存档内容。了解详情 »

自己动手打造智能物联网设备

自从前段时间研究了智能家居设备之后,我便迷上了物联网和开源硬件。玩遍了市面上各种常见的物联网产品,总觉得各有不足,于是我突发奇想:干脆自己做一个!

对于我而言,现在市面上的物联网产品最大的问题在于太过封闭,不同厂商的产品都得用自家的 App 才能使用,而且大多数用户体验实在不敢恭维。虽然通过我前一篇博文介绍的方法将它们接入到 HomeAssistant 和 HomeKit 之后使用自由度会高得多,但依然无法满足我自己编写家居智能控制程序的要求。

当我问 Siri 客厅的室温是多少的时候,数据是这样传输的:米家温湿度传感器读取温度数据、通过 ZigBee 信号发送给米家智能网关、通过 Wi-Fi 发送到路由器,路由器再传给树莓派、HA 存储数据、Homebridge 读取和广播数据、手机上的 HomeKit 再通过 Wi-Fi 读取数据……可想而知,数据传输的环节越多,稳定性和数据时效性就越低。比如我想做一个根据电视画面的亮度来调整房间灯光亮度的设备,当电视在播放夜间画面(亮度较低)的时候调暗房间灯光来减轻屏幕反光的影响,反之则调亮灯光方便我吃东西。这时候就需要以百毫秒级的速率来读取光线传感器的数据,一般的商业产品很难满足这种需求。

此外,价格也是很重要的因素:一个硬件成本不超过十元的智能插座零售价高达两百多元;即使选用相对便宜的米家系列传感器和 Sonoff 开关,要实现我心目中真正的智能家居——家中所有电器全部智能化、每个角落都有人体感应器也将是一笔非常可观的开支。

初识 Arduino

于是我开始深入了解开源硬件方面的知识来打造完全合乎自己要求的物联网设备,这时候我发现了 Arduino 这个开源电子原型平台。它本质上是一个单片机,有丰富的针脚接口用于连接各类传感器、伺服器和继电器等等。在电脑上用 Arduino IDE 编写代码后,可以很方便地写入到微控制器上执行。更重要的是由于 Arduino 的软硬件都是完全开源的,让我能以很低的成本获取所需的软件和硬件。

Arduino 有很多种版本,加之以开源的 PCB 图为基础自行生产的第三方产品可谓数不胜数,我选择的是一个可以和我的第三代 Raspberry Pi(树莓派)结合使用的版本——因为 Arduino 本身只是个单片机,并不能像树莓派之类基于 ARM 架构的微型电脑一样连接网络和存储大量数据。虽然市面上 Arduino 也有能实现相关功能的硬件模块,但我依然认为搭配熟悉的树莓派更简单好用。

这个 Arduino 通过串口与树莓派通讯,同时封装了树莓派上的所有 GPIO 针脚,所以需要将它用 USB 线连接到树莓派,然后再将整个 Arduino 都插在它上面。

接入传感器

市面上有非常多的传感器可供选择,且售价大多不过二三十元。Arduino 支持接入模拟和数字两种信号的传感器,我第一个接入的温湿度传感器 DHT11 属于后者,所以要用杜邦线将它插到数字针脚上。

插好之后就可以开始写代码了。Arduino 主要用 C++ 来编程,这是一种我从未接触过的编程语言,还好我学过 Objective-C,所以还算是能读懂;配合万能的 Google、完善的官方文档和传感器厂商提供的实例代码,在开发过程中基本没有遇到什么困难。

虽然厂商提供了已经封装好的代码库,只需调用即可直接读取到传感器数据,不过我对从硬件电路到软件数据的传输和转换过程很感兴趣,于是一探究竟,才知道 Arduino 通过数字接口读取到的是 DHT11 传感器在一段时间内通过电压变化来传输的二进制数值:

按照官方数据表的说明,高电平输出 26 微秒左右表示 0,输出 70 微秒则表示 1,用逻辑分析器即可看到比较直观的效果,这里我偷个懒在网上找了一张已经标注好的图:

这里可以看到传感器总共输出了 40 位的数据,其中前 16 位是湿度,紧接着的 16 位是温度,最后 8 位则用于校验数据有效性,若为温湿度数值之和即为有效;温湿度的 16 位数据中只有前 8 位是有效数据,后 8 位是奇偶校验位,这里全部为 0,可直接忽略。

按照上述规则来解析,图片中的二进制湿度数据为 00011110,温度为 00011001,将它们转换成十进制即可得到最终结果:30% 相对湿度和 25 摄氏度。再计算一下 00011110 + 00011001 = 00110111,即最后 8 个奇偶校验位的数值,证明数据是有效的。

当然实际使用时并不需要自己计算这些,只要引入官方提供的代码库,简单调用一下即可获取传感器数值并通过串口输出,非常方便。

这里要吐槽一下 Arduino IDE 的代码编辑器,功能简陋到基本就是个带语法高亮的记事本,然而它的流畅性和视觉效果甚至还不如记事本……让我不得不在 Sublime Text 里写代码再复制过来编译。

接下来试试光线传感器,它传输的是模拟信号,所以要插在模拟接口的针脚上。软件方面就简单多了,调用 Arduino 内置的 analogRead() 方法即可获取亮度数据。

将数据传送到树莓派

现在已经可以用 Arduino 读取传感器的数据,接下来就要将数据传送到树莓派来做进一步处理。实际上之前所写的代码已经可以让 Arduino 把数据通过串口输出到树莓派上了,所以真正需要做的只是在树莓派上写个程序来读取串口输入的数据,我是用 Python 写的,只需六行代码。

测试成功后我又在 Arduino 上接入了六七种传感器,读取数据的方法都大同小异,这里就不再展开;不过随着数据量的增加,需要对数据进行封装才好解析。这里我选用了 ArduinoJson 库将数据转换为 JSON 格式输出,这样在树莓派上用 Python 读取就方便多了。

在树莓派上用 Python 读取到传感器数据之后,就可以自己写个程序通过我前一篇文章提到过的 HomeAssistant API 来自动控制家里的其他电器了。至此我的智能物联网终端已经初步完成,当然我还会继续研究如何实现更多新奇有趣的用法,包括如何进一步脱离网络传输,完全在本地直接控制电器等等,相信没有做不到,只有想不到。在学习 Arduino 传感器的过程中我还顺便了解到了很多关于电机、伺服器、继电器、ZigBee 通讯协议和无线充电的相关知识,让我很感兴趣,说不定哪天我会一时兴起,给它装上轮子和机械手臂,做成 AI 机器人管家之类的东西,哈哈。

扫描二维码可分享到微信
或点击此处分享到新浪微博