GreenPiThumb: A Raspberry Pi Gardening Bot

Michael Lynch

GreenPiThumb:Raspberry Pi 園藝機器人

簡介

這是 GreenPiThumb 的故事:一台會自動為室內植物澆水的園藝機器人,但有時也會把植物弄死。

GreenPiThumb 完整系統

故事要從大約一年前說起,當時我突然很想養一盆室內植物。養盆植物感覺不錯,能提供我迫切需要的氧氣,還能向客人暗示我是個負責任的大人,有能力照顧一個生命。

但我是個程式設計師,不是園藝家。如果我養了植物,就得每週澆水好幾次,還得檢查植物的健康狀況。我心想,乾脆花上數百小時打造一台機器人來幫我做這些事還比較輕鬆。如果這盆植物能活到 80 歲,我還算小賺。

為什麼要做 GreenPiThumb?

跟我接手的大多數軟體專案一樣,我做 GreenPiThumb 的主要動機是為了學習新技術。我寫上一個應用程式 ProsperBot,是為了自學 Go、Ansible 和 Redis。我把 GreenPiThumb 視為學習前端開發的機會,特別是 JavaScript 和 AngularJS。

我的朋友 Jeet(傑特) 才剛開始學程式設計,所以我問他有沒有興趣跟我一起合作 GreenPiThumb。這對他來說似乎是個學習良好軟體工程實務的好機會,像是程式碼審查、單元測試和持續整合。傑特答應了,於是我們便展開了這段原本以為只要兩、三個月就能完成的旅程。

由 Raspberry Pi 驅動

Raspberry Pi 是一台為創客設計的小型平價電腦。人們曾用 Raspberry Pi 來打造未來感十足的智慧鏡子執行懷舊電玩遊戲,以及驅動電動滑板

Raspberry Pi

過去幾年我一直在玩 Raspberry Pi,但身為一個軟體人,我從來沒有把它當成便宜的玩具伺服器以外的用途來使用。對於大多數愛好者社群而言,Raspberry Pi 最大的吸引力在於它與消費性電子產品的良好整合能力。

有這麼多感測器和整合教學可供使用,Raspberry Pi 自然成為 GreenPiThumb 的理想選擇。我心想,使用 Raspberry Pi 也能逼自己去學習它的硬體功能,終於搞懂那些「GPIO 接腳」到底是做什麼的。

MOSFET 熔毀麵包板

Raspberry Pi 及其神祕的 GPIO 接腳

為什麼還要再做一台 Raspberry Pi 園藝機器人?

我們當然不是第一個想到要打造 Raspberry Pi 園藝機器人的人。在我們之前,就有兩個很酷的專案,分別是 PiPlanterPlant Friends,不過此外也還有其他幾個類似的專案。

我們決定自己動手做有兩個原因:自己動手做東西很有趣,而且我們希望機器人的軟體品質能成為首要考量。

大多數 Raspberry Pi 專案都是由擅長電子硬體、但缺乏專業軟體經驗的愛好者所打造。我們想反其道而行——軟體很強,但硬體勉強能動,有時甚至熱到把麵包板都熔掉了。

GPIO 接腳

一個早期原型,很可能有「著火」的問題

GreenPiThumb 的程式碼是開源的,具備以下特色:

  • 完整的單元測試
  • 程式碼覆蓋率追蹤
  • 持續整合
  • 除錯日誌
  • 詳盡的文件——包含 README 和程式碼註解
  • 嚴格遵循風格指南
  • 安裝工具

硬體架構

GreenPiThumb 線路圖

GreenPiThumb 線路圖(可下載檔案

Raspberry Pi 讀取的是數位訊號,因此無法直接讀取類比感測器。我們使用 MCP3008 analog-to-digital converter(類比數位轉換器) 來將類比的 土壤濕度感測器和光感測器的讀數轉為數位訊號。

DHT11 感測器負責偵測空氣中的溫度和濕度。它輸出的是數位訊號,因此可以直接連接到 Raspberry Pi。

最後,我們有一個 12V 抽水馬達,但 Raspberry Pi 只能輸出 5V,因此我們將一個 12V 電源變壓器與馬達串聯,並透過一個 MOSFET(金屬氧化物半導體場效電晶體) 連接。Raspberry Pi 利用 MOSFET 作為數位開關,需要開啟或關閉馬達時,就透過它來導通或切斷電路。

軟體架構

GreenPiThumb 軟體架構

GreenPiThumb 軟體架構

GreenPiThumb 後端

後端負責 GreenPiThumb 的核心工作。它是一個 Python 應用程式,負責:

  • 管理實體感測器(土壤濕度、溫度等)
  • 控制抽水馬達的開關
  • 在資料庫中記錄事件與感測器讀數

GreenPiThumb 網頁 API

網頁 API 是一個 HTTP 介面,提供 GreenPiThumb 狀態與歷史紀錄的資訊。它是 GreenPiThumb 資料庫的輕量封裝,將所有資料轉為 JSON,讓網頁應用程式更容易理解。

GreenPiThumb 網頁儀表板

網頁儀表板會顯示 GreenPiThumb 的目前狀態,並繪製感測器讀數隨時間變化的圖表。

GPIO 接腳

我們的 Raspberry Pi 還沒辦法勝任對外開放的網頁伺服器,不過這裡有一個與我們本地端完全相同的 GreenPiThumb 儀表板靜態鏡像:

部署

要將 GreenPiThumb 部署到我們的 Raspberry Pi 裝置上,我們使用 Ansible,這是一套開源的 IT 自動化工具。

我們為 GreenPiThumb 建立了一個客製化的 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 雖然會測量土壤濕度,但澆水是按照固定時程進行的,與濕度無關。我們在網路上搜尋,找到幾個號稱完全依據土壤濕度來澆水的 Raspberry Pi 園藝專案,但它們既沒有公開原始碼,也沒有分享成果數據。因此,我們認為可以公平地假定,單純依據濕度來澆水是不可能的,而 GreenPiThumb 已經在物理世界某些不可違逆的限制下,做到最好了

最終,我們決定改用混合式系統。現在 GreenPiThumb 會在土壤過乾距離上次澆水已超過七天時,才為植物澆水。

最終成品

以下是我們完成的 GreenPiThumb 的一些照片:

GreenPiThumb 完整系統GreenPiThumb 完整系統
GreenPiThumb 電子零件GreenPiThumb 抽水馬達GreenPiThumb 儲水槽

縮時攝影是這個過程中最有趣的部分。這段影片來自我們的第一批四季豆(安息吧)。我們沒料到植物會這麼快就長到超出近距離俯拍的角度。我們後來換成一個更大的可彎折支架,能以更好的角度捕捉植物完整的生命週期,但我們最初的設置還是捕捉到了最初幾天生長過程的精彩縮時:

第二批我們讓相機全程保持在完全相同的位置。這是第二批到目前為止的生長進度:

經驗教訓

沒有什麼事看起來那麼簡單

我原以為這會是一個單純、只要兩到三個月的專案,但我們花了一年多才完成,因為沒有什麼事看起來那麼簡單。

這是我很久以前從傑出的軟體隨筆作家 Joel Spolsky(喬爾·斯波爾斯基)那裡學到的一課,我預期在未來許多軟體專案中,還會一再學到同樣的教訓。

電子學:從基礎開始

Arduino 入門套件

在 GreenPiThumb 剛開始時,我對電子學的唯一認識只剩下高中物理的模糊記憶。我買了 Arduino 入門套件,並跟著教學一步步建立電子學的基礎。

這些教學結果證明既有趣又實用。它們從簡單的內容開始,循序漸進地帶到更進階的主題。我會向任何對電子學有興趣的初學者推薦這個套件。

單獨測試硬體

有些曾與我共事過軟體專案的人形容我在寫程式時「吹毛求疵」或「過度拘謹」。我倒覺得自己的寫作風格算是「嚴謹」。我們先實作了 GreenPiThumb 的軟體部分,嚴謹地逐一進行同儕審查並測試每個軟體元件。

輪到硬體時,我們就非常不嚴謹了。可以說我們有點草率、天真得可笑。我們最初測試硬體元件的流程是:先寫一個 GreenPiThumb 軟體的陽春版,把所有感測器都接在測試板上,執行後看看會產生什麼結果。

什麼都沒有。它什麼都沒產生。因為那是一個糟糕透頂的硬體測試策略。系統中的每個電子元件都有可能失效,可能是元件本身瑕疵,也可能是安裝不正確。一次把所有東西都接起來,我們根本無法判斷到底是哪個環節出了問題。

久而久之,我們學會了單獨測試感測器。我們為每個硬體元件建立了獨立的診斷腳本。現在每次調整硬體時,我們首先做的就是執行這些診斷腳本,確認讀數是否合理。當新的硬體零件無法運作時,我們會用三用電表有系統地找出根本原因。我們應該更早一點就買三用電表的。它只要 13 美元,卻能為我們省下無數小時的挫折與困惑。

原始碼

零件清單

下表列出我們打造 GreenPiThumb 所使用的設備。我們分享確切的零件型號,是為了讓你更容易照著我們的範例製作,但其中許多都是功能相同的通用元件,你可以用同等品來替換。

GreenPiThumb 必備零件

通用電子元件

以下項目是可用於許多專案的通用電子工具與元件。因為我們一開始完全沒有電子設備,所以為了完整起見也一併列出:

園藝用品

選配元件

  • 第三手焊接輔助工具
    • 我們一開始用的是這款基本夾式支架,但定位和調整很不方便。可彎折的款式雖然貴了好幾倍,但讓焊接工作變得更簡單、更愉快。
  • 可彎折相機支架
    • 很適合用來固定相機。夠長且可彎折,能讓你有更多選擇來找到良好的拍攝角度與距離。
  • PEX 水管切管器
    • 能對水管做出漂亮俐落的切口。
  • 數位三用電表
    • 我們強烈建議你買一個基本的三用電表。這一款沒有什麼特別之處,但對我們來說很好用。
  • Pi 相機支架
    • 可讓你將 Raspberry Pi 相機固定到標準的 1/4 吋相機支架上,例如上面提到的可彎折支架。
  • Pi 相機延長線(1 公尺)
    • 用於將 Raspberry Pi 相機佈署在遠離 Raspberry Pi 主機本身的位置時不可或缺。
  • 束線帶
    • 用於固定水管或線材。

致謝

衷心感謝以下幫助我們完成此專案的人:

原文由 Michael Lynch 發布

本文章由 muse-spark-1.2-contributor 進行翻譯