GreenPiThumb:一款 Raspberry Pi 园艺机器人
简介
这就是 GreenPiThumb 的故事:一款会自动给室内植物浇水、但有时也会把它们浇死的园艺机器人。
故事始于大约一年前。那时,我突然产生了想养一盆室内植物的念头。植物看起来很漂亮,能给我提供急需的氧气,还能向客人暗示:我是一个有责任心的成年人,有能力照料一个生命。
但我是程序员,不是园丁。如果养了植物,我每周就得给它浇几次水,还要检查它的健康状况。我觉得,花上几百个小时造一个机器人来替我做这些事,肯定会容易得多。如果这株植物能活到 80 岁,我在时间上就能稍微占点便宜。
为什么要做 GreenPiThumb?
和我接手的大多数软件项目一样,做 GreenPiThumb 的主要动机是学习新技术。我之前编写了 ProsperBot,用来学习 Go、Ansible 和 Redis。我把 GreenPiThumb 看成学习前端开发的机会,具体来说就是学习 JavaScript 和 AngularJS。
我的朋友 Jeet(吉特)刚开始学习编程,所以我问他是否有兴趣和我一起合作开发 GreenPiThumb。这似乎是个让他了解健康软件工程实践的好机会,比如代码审查、单元测试和持续集成。Jeet 同意了,于是我们开始了这项我们以为只需两三个月就能完成的工作。
由 Raspberry Pi 驱动
Raspberry Pi 是一种面向业余爱好者的小型廉价计算机。人们用 Raspberry Pi 制作未来感十足的智能镜子、运行老式电子游戏,还用它来驱动电动滑板。
过去几年里,我一直在摆弄 Raspberry Pi,但我是个软件人员,所以以前从没用它做过廉价玩具服务器以外的东西。对大多数爱好者来说,Raspberry Pi 最大的吸引力在于它能很好地与消费电子设备集成。
Raspberry Pi 有数量众多的传感器和集成指南可用,因此非常适合 GreenPiThumb。我想,使用 Raspberry Pi 也会迫使我了解它的硬件能力,并最终弄清楚那些“GPIO 引脚”到底是做什么的。

Raspberry Pi 及其神秘的 GPIO 引脚
为什么还要再做一款 Raspberry Pi 园艺机器人?
我们当然不是第一批想到制作 Raspberry Pi 园艺机器人的人。此前已经有两个很酷的项目:PiPlanter 和 Plant Friends,此外还有一些类似项目。
我们决定自己做一个,原因有两个:自己动手制作东西很有趣,而且我们希望机器人的软件能成为一等公民。
大多数 Raspberry Pi 项目都是由电子技术很棒、但没有专业软件经验的爱好者制作的。我们想反其道而行之——软件很优秀,但硬件勉强能用,有时还会热到把面包板熔化。

早期原型,很可能存在“着火”问题
GreenPiThumb 的代码是开源的,具备以下特性:
硬件架构

GreenPiThumb 接线图(可下载文件)
Raspberry Pi 读取的是数字信号,因此无法直接读取模拟传感器。我们使用 MCP3008 模数转换器(analog-to-digital converter,模数转换器),将土壤湿度传感器和光线传感器的模拟读数转换为数字读数。
DHT11 传感器用于检测空气温度和湿度。它输出数字信号,因此可以直接接入 Raspberry Pi。
最后,我们有一个 12V 水泵,但 Raspberry Pi 只能输出 5V,所以我们将12V 电源适配器与水泵串联,并接入一个MOSFET(金属氧化物半导体场效应晶体管)。Raspberry Pi 把 MOSFET 当作数字开关使用,需要关闭或开启水泵时,就断开或接通电路。
软件架构
GreenPiThumb 软件架构
GreenPiThumb 后端
后端负责 GreenPiThumb 的主要工作。它是一个 Python 应用,负责:
- 管理物理传感器(土壤湿度、温度等)
- 开启和关闭水泵
- 在数据库中记录事件和传感器读数
GreenPiThumb Web API
Web API 是一个 HTTP 接口,用于提供 GreenPiThumb 的状态和历史信息。它只是 GreenPiThumb 数据库之上的一层薄封装,会将所有内容转换为 JSON,让 Web 应用更容易理解。
GreenPiThumb Web 仪表盘
Web 仪表盘显示 GreenPiThumb 的当前状态,并绘制传感器读数随时间变化的图表。
我们的 Raspberry Pi 还不足以胜任面向互联网的 Web 服务器,不过这里有一个 GreenPiThumb 仪表盘的静态镜像,与我们的本地版本完全相同:
部署
要将 GreenPiThumb 部署到 Raspberry Pi 设备上,我们使用Ansible,一种开源 IT 自动化工具。
我们创建了自定义的 GreenPiThumb Ansible 配置(用 Ansible 的术语来说就是“role”),用于部署 GreenPiThumb 所需的全部软件。这个 Ansible role 会下载并安装 GreenPiThumb 的后端和前端代码,以及 GreenPiThumb 所依赖的第三方软件组件。
只需执行几条命令,就能在一台全新的 Raspberry Pi 设备上使用这个工具,并在几分钟内让 GreenPiThumb 的所有软件运行起来。
一路上的坎坷
GreenPiThumb 花了一年多才完成,比预期长得多,因为我们遇到的障碍有时会让进度停滞数周。下面介绍一些比较有趣的难题。
如何分配水
其他 Raspberry Pi 园艺项目都没有说明它们如何把水分散到土壤上,这很遗憾,因为我们至今也没弄明白。
第一次把水泵进花盆时,水管将一股细流导向一个点,把那一小片区域完全浇透,却让其余土壤保持干燥。我们考虑过把橡胶管沿花盆内壁盘起来,再在管子上戳孔,但不确定这样能否让土壤中央也得到足够的水。我们试过使用莲蓬头,但既不知道如何将它防水地固定在水管上,也不知道如何同时控制水流方向。
最终我们采用了“喷出去,然后祈祷”的办法。这是我们环顾公寓、随手抓来一些可能解决问题的东西后想出的方案。我们从一只小厨房手套上剪下一根手指,用一根紧紧对折的橡皮筋把它固定在水管上,再用缝衣针和指甲剪在手套上扎出许多孔。
我们打开水泵,手套被剪下的手指立刻从水管上飞脱,把水喷得满公寓墙都是。我们重新装好所有东西,但这次在橡皮筋前面插了一根安全别针,防止橡皮筋向前滑动。


由厨房手套改成的分水器
这算不上最优雅的解决方案,但基本能用。
园艺部分本来不该这么难
电子设备本应是 GreenPiThumb 最大的挑战。园艺看起来没那么难。尤其是四季豆,人们经常把它描述为一种耐活、只需基本园艺技能就能种好的植物。
事实证明,我们连基本的园艺技能都没有。GreenPiThumb 的目标是自动化照料室内花园中原本由人完成的部分,但要自动化任何事情,人必须知道“正确”是什么样的。我们很难判断 GreenPiThumb 浇水过多还是过少,因为我们自己都不知道该浇多少水。于是,我们意外拍出了这部园艺版的植物虐杀电影:
测量湿度能有多难?
最让我们头疼的问题是泥土。
开始制作 GreenPiThumb 时,我们以为浇水当天土壤湿度会升高、没浇水当天会降低。GreenPiThumb 的工作似乎很简单:每当读数低于某个阈值,就加水,以维持正确的湿度水平。
下面,我们使用昂贵而复杂的建模软件,将预期中的 GreenPiThumb 土壤湿度模式可视化:

想象中的土壤湿度模式
糟糕的读数
土壤拒绝配合我们。最初的版本中,土壤湿度读数在 95% 到 100% 之间振荡,然后缓慢收敛到约 99.5%。我们取出土壤传感器,用它测试不同介质:空气、水、湿纸巾、我们的手,以及完全干燥的土壤。所有这些东西似乎都能得到合理读数,但只要土壤带有任何湿气,传感器读数就会飙升到接近 100%。

土壤湿度读数,原始湿度传感器
我们最初使用 Dickson Chow(迪克森·周)的 Plant Friends 土壤探针,但后来换成了 SparkFun 土壤传感器。新传感器在潮湿土壤中的读数为 82%,浇水后会立即跳到 85%。然而几小时内,它又会降回 82%,并在那里保持数天。这个传感器似乎无法区分三小时前浇过水的土壤和五天没浇水的土壤。

土壤湿度读数,SparkFun 湿度传感器
我觉得我的泥土坏了
也许问题出在泥土上。我们的盆栽土是 Miracle-Gro 的这款预包装混合土,号称采用“易于浇水配方”。有点可疑,对吧?显然,这是某种永远不会变干的邪恶基因工程土壤。这就是可怜的土壤传感器如此困惑的原因。
我们需要一种不会和我们耍花招的泥土,于是买了这款有机盆栽混合土。为了测试,我们在塑料杯里装满有机土,加水,在杯底戳孔让水排出,然后放置三天,使其符合 GreenPiThumb 花盆中的土壤状况。三天后,我们在两种土壤中分别测试传感器。
结果读数完全相同:两种都是 82%。所以,我们不能怪土壤……
放弃
想不到办法后,我们重新研究了启发 GreenPiThumb 的那些项目。他们是怎么解决这个问题的?
Plant Friends 根本不抽水。PiPlanter会测量土壤湿度,但无论湿度如何,都会按固定时间表浇水。我们用 Google 搜到了一些声称完全依据土壤湿度浇水的 Raspberry Pi 园艺项目,但它们没有一个公开源代码或分享结果数据。因此,我们觉得可以合理地假设,依据湿度水平浇水是不可能的,而在物理世界某些不可抗拒的限制下,GreenPiThumb 已经尽其所能。
最终我们决定改用混合系统。现在,如果土壤过于干燥,或者距离上次浇水已经过去七天,GreenPiThumb 就会给植物浇水。
最终成品
下面是我们完成的 GreenPiThumb 成品图片:





延时摄影是这个过程中最有趣的部分。这段视频拍摄的是我们第一批四季豆(安息吧)。我们没意识到植物会如此迅速地长出近距离俯拍角度的范围。后来我们换用了更大的可弯曲支架,能以更好的角度记录植物的完整生命周期,但原来的装置拍到了最初几天生长过程的精彩延时摄影:
第二批植物生长期间,我们始终把相机放在完全相同的位置。这是第二批目前的生长进度:
经验教训
没有什么事情像看起来那么简单
我原以为这是一个简单的两三个月项目,但我们花了一年多才完成,因为没有什么事情像看起来那么简单。
这是我很久以前从软件评论家 Joel Spolsky(乔尔·斯波尔斯基)那里学到的教训,也是我预计今后在许多软件项目中会一次又一次学到的教训。
电子技术:从基础开始
开始做 GreenPiThumb 时,我对电子技术的唯一了解来自高中物理课中模糊的记忆。我买了Arduino 入门套件,通过教程打下电子技术基础。
这些教程非常有趣,也很实用。它们从简单内容开始,逐步过渡到更高级的主题,做得很好。我向所有对电子技术感兴趣的初学者推荐这套套件。
单独测试硬件
一些曾和我一起参与软件项目的人说到写代码时,会形容我“过于吹毛求疵”或“过度迂腐”。我更愿意把自己的编码风格称为“严谨”。我们先实现了 GreenPiThumb 的软件部分,对每个软件组件逐一进行严格的同行评审和测试。
但说到硬件,我们就完全不严谨了。可以说,我们有点鲁莽,而且天真得可笑。我们最初测试硬件组件的流程是:编写 GreenPiThumb 软件的基础版本,把所有传感器接到测试板上,运行程序,然后看看它产生了什么。
什么也没有。它什么也没产生。因为那是测试硬件的糟糕策略。系统中的每个电子元件都有可能出故障,要么是元件本身有缺陷,要么是安装不正确。一次把所有东西接起来,我们就无法判断究竟是哪一个或哪几个部件坏了。
后来,我们学会了单独测试传感器。我们为每个硬件组件创建了独立的诊断脚本。现在每次调整硬件,我们首先都会运行这些诊断脚本,确认读数正常。新的硬件部件无法工作时,我们会使用万用表系统地找出根本原因。我们本该早得多买万用表的。它只花了 13 美元,却本可以为我们省下无数个沮丧抓狂、苦思不得其解的小时。
源代码
零件清单
下表列出了我们制作 GreenPiThumb 时使用的设备。我们分享确切的零件型号,方便你照着我们的方案制作,但其中许多都是通用元件,可以替换成在功能上完全相同的产品。
GreenPiThumb 必需品
- Raspberry Pi 3 Model B
- 12V 水泵
- Raspberry Pi Camera V2 - 8 MP
- 100-240v AC 转 12 & 5v DC 4pin Molex 2A 电源适配器
- MicroSD 卡(32 GB)
- 硅胶管
- FQP30N06L N 沟道 MOSFET
- Raspberry Pi 电源
- DHT11 温湿度传感器
- MCP3008 模数转换器
- 可焊面包板(400 个连接点)
- 土壤湿度传感器
- 橡胶手套
- Molex 转 SATA 电源线适配器
- 光敏电阻
- 1 加仑塑料水壶(用作储水箱)
- 安全别针
- 橡皮筋
常用电子元件
下面这些是可用于许多项目的通用电子工具和元件。因为我们之前完全没有电子设备,所以为完整起见将它们也列出:
园艺用品
可选组件
- 第三只手焊接工具
- 我们一开始使用这种基础夹具支架,但它很难摆放和调节。可弯曲款贵了好几倍,但让焊接工作变得更简单、更愉快。
- 可弯曲相机支架
- 非常适合固定相机。它足够长且足够灵活,能让你有很多选择来寻找合适的角度和距离。
- PEX 管切割器
- 可以干净利落地切割水管。
- 数字万用表
- 我们强烈建议你买一只基础万用表。这款本身没有什么特别之处,但用起来很可靠。
- Pi 相机支架
- 可以将 Raspberry Pi 相机连接到标准的 1/4 英寸相机支架上,例如上面的可弯曲支架。
- Pi 相机延长线(1m)
- 当 Raspberry Pi 相机需要远离 Raspberry Pi 设备本身时,这是必需品。
- 扎带
- 用于固定水管或线缆。
致谢
非常感谢帮助我们完成这个项目的人:
- Devon Bray(德文·布雷),他的项目 PiPlanter 2 极大地启发了 GreenPiThumb 的硬件设计。
- Dickson Chow(迪克森·周),他的项目 Plant Friends 为我们提供了有用的硬件参考,并在整个项目期间给予我们许多鼓励。
- Nicole Michaelis(妮可·迈克尔斯),她自愿抽出时间帮助编辑这篇文章。
- /r/raspberry_pi Reddit 社区,在我们遇到接线问题而陷入困境时,感谢他们提供的帮助。
随机一篇博客