现在所说的"智能家居"，其实更多的是"遥控家具"。正如[以前的文里面提到的](/zi-ji-dong-shou-gai-zao-zhi-neng-jia-ju-sheng-huo.html)，我个人认为智能家居需要三个阶段，遥控化，自动化，和智能化。现在利用ifttt和一些手工规则，我们已经可以实现相当程度的自动化了（6点开暖气，日落开灯等等）。但想要到智能化还有相当的路要走。我自己就是搞机器学习的，所以也希望能学以致用，至少让自己家更智能，过得更舒服。但要搞智能化，面临的第一个问题就是，训练数据从哪来，甚至，训练数据是什么。从提高生活质量的角度出发，我把空气质量作为一个切入点。开始了一些用树莓派测量空气质量的实验。

从自己生活的角度看，其实也很好奇室内污染到底有多严重，甲醛pm2.5到底有多少。由于有后期数据分析可视化的需求，所以更希望从app里面看。然鹅，至少没有看到美国公司做又能测pm2.5/甲醛/游离有机物（VOC），又有app的产品（最接近的是知名pm2.5测量厂商dylos的pro版提供一个土土的串口能连PC）。国内这样的产品有一些接近的，但看到200块的售价和扫一扫朋友圈自动分享的广告语，虽然觉得牛逼，总觉得哪里不对。。所以从实用的角度出发，也决定自己动手丰衣足食一把。

最终的结果就是，做出来一个东西可以搜集/监控家里的温湿度，二氧化碳，噪音水平，以及空气质量。目前空气质量仅仅包括氮氧化物/氨/苯/酒精和甲醛。未来会加入PM2.5。app的截图如下。

![Smart home app interface](https://yage.ai/images/smart-home-air-quality-chart.png)

这些数据是从不同的传感器搜集来的：

* 温湿度是从家里的暖气控制器（thermostat）搜集的。它自带一个（未公开的）OAuth API。Ajax抓包可以拿到。
* 二氧化碳和噪声水平用的是Netatmo。
* 空气质量用的是树莓派加传感器。下面详细说说这个。

![Air quality hardware](https://yage.ai/images/smart-home-air-quality-hardware.jpg)

=============hard core技术内容的分割线===============

树莓派（基于ARM）和Arduino之类单片机的重要差异在于，他虽然有GPIO接口，能够读取数字信息，但他并没有内置模拟数字转换器（ADC），所以不能像Arduino那样直接连模拟传感器。但流行的气体传感器MQ135等等都是模拟的，所以得搭一个小电路，用MCP3008之类的ADC芯片先把模拟信号转成数字信号，然后再读取。这里有一个相当好的教程：[Analog Inputs for Raspberry Pi Using the MCP3008](https://learn.adafruit.com/reading-a-analog-in-and-controlling-audio-volume-with-the-raspberry-pi/overview)

![MCP3008](https://yage.ai/images/smart-home-air-quality-mcp3008.png)

但教程里面对MCP3008信号读取用的是bit banging的方法，也就是自行实现上图的协议。其实树莓派内置硬件支持SPI总线接口。所以我就偷个懒，直接用spidev来读了。改改电路以后几行python就能搞定。后端用tornado架个网站，前端用ajax刷新数据写个web app就接起来了。
同时也和学物理的同学探讨了一下。MQ135之类传感器的原理是，传感器的表面有一层二氧化锡的膜。空气中的目标分子（比如苯分子）接触到这层膜的时候，会可逆地放出电子，从而改变二氧化锡膜的电导率。所以通过测量电阻，就可以实现对有害气体含量的测量了。不同的气体会有不同的膜。至于PM2.5，一般的传感器用的是激光散射。但这个非常不准确，一般只用来做定性测量。原因是气溶胶含量的测量博大精深，不同的条件下适合用不同的方法，很难说有一种传感器能在各种不同的环境下都能得到准确的结果。国家标准里面测量PM2.5用的是BAM之类直接过滤空气的方法，非常昂贵。

今天拿到了更小的树莓派zero。踩了一些坑，也说一下。

![Raspberry Pi Zero](https://yage.ai/images/smart-home-air-quality-rpi0.jpg)

树莓派zero是一种5美元的全功能电脑。它和普通的树莓派在功能上是完全一样的，只是有一些接口上的缩水。比如4个全尺寸USB口变成了1个OTG mini USB口。而且把wifi去掉了，这就很蛋疼。。显然不可能到哪都拖根网线，自然地，就需要折腾看能不能把Wifi给装上去。。一个很简单的想法是，我找个特别小的那种无线网卡，就一个USB口外面伸出来一点点那种，插上不就完了。想法很简单，但真插上去以后发现特别不稳定，一两秒断一次，断一次要找几十秒才能重新连上。折腾了六七个小时，debug了半天内核错误信息。网卡设置，dhcp，路由，驱动，一个个排查过去，最终的结论是。。USB口支持的电流太小，撑不起来这个无线网卡。网上有人找个了有源的USB hub，插上就能跑了。

这特码就有点尴尬了。树莓派zero的好处都有啥？不就是便宜和小么！要是随身带个有源usb hub，又不便宜又不小了。。只能另外想办法。先看能不能魔改OS把usb电流弄大。。搜了一些方法试了以后并没有什么卵用。继续bing，找到另一个魔改方法。大概地说，就是树莓派zero为了调试方便，在PCB电路板上暴露了一些电极。这里面正好包括+5V, GND, 以及USB通信的D+和D-。一个简单粗暴的方法是，老子把网卡拆了，直接把电极焊上不就完了么。

说拆就拆。网卡拆完以后特别特别小。。跟一个一分硬币差不多大。可以看到天线其实就是弯弯曲曲的一排金属。

![Raspberry Pi Zero USB port](https://yage.ai/images/smart-home-air-quality-rpi0-usb.jpg)

有个小坑是USB信号是差分信号（differiential signal），为了避免干扰，每根线的长度最好是一样的。所以焊上去以后摆成了这个奇怪的pose。

![Raspberry Pi Zero USB port welded](https://yage.ai/images/smart-home-air-quality-rpi0-welded.jpg)

插电以后真特码亮了。。DHCP也可以拿到IP地址。DHCP的过程感觉比之前快了不少，可能和电流增大了有关。然鹅，不稳定的问题还是没有完全解决，log里时不时还是能看见网卡重启的错误。还有个大坑是这么焊了以后OTG USB用不了了。。插上网卡就灭了，然后USB也没反应。。所以如何在树莓派zero上加上一个又便宜又小的wifi还是一个未解之谜。。

=====================思想感情的分割线=====================

整个过程中焊了接口，拼了模拟和数字电路，操作了总线，做了驱动和内核debug，写了python，架了网站，写了前端。虽然很多东西从本科毕业就再没碾过，一条龙下来都比较顺畅，感觉本科的系统化教育还是很有用的。总体感受就是，欢迎您报考中国科学技术大学！基础扎实真的不后悔。
