故事要從家裡服役十七年的老冰箱掛點講起,老冰箱這兩年百病纏身,冷度不足,門框磁膠條密合不佳,冰箱兩側散熱區溫度偏高… 加上老機型耗電,早有換新念頭,逛賣場也常在冰箱區留連,但換冰箱茲事體大令人不想面對,總缺少臨門一腳。上週起冰箱兩側忽然熱到燙手,然後,它就死掉了... 不得不啟動應變計劃,尋找食材暫放空間,評估冰箱廠牌款式,比價找供應商,忙得不亦樂乎。冰箱暴斃事件,讓我再次對「重要但不緊急的事,拖久就會變重要又緊急」有深刻體認!共勉之。
感念老冰箱苦撐十七年護國有功,挑了同廠牌新一代六門有製冰機外加能源效率一級的新機型。新冰箱就位後有個小問題-新機容量大,機身較寬( 72cm –> 77cm),離牆面距離變短,現代冰箱靠左右兩側跟上方散熱,依說明書要求兩側離牆要2cm以上,實測右側是有2 - 3.5cm的空隙。作業系統說記憶體至少2G,真的只裝2G RAM,效能通常只有「堪用」的水準,這個最小離牆距離夠不夠?會不會導致兩側溫度偏高增加耗電量?吾人以為,只有實測才能解答。
於是我啟動了「外掛式物聯網強化計劃」,構想是用Arduino、Espruino或Raspberry Pi連接溫濕度感應器(Sensor),定期測量溫度上傳到網站,再整理成圖表。要上傳資料,支援USB無線網卡的Raspberry Pi是最簡便的選擇,從書架上積滿灰塵的盒子拿出買來只玩幾天就打入冷宮的Raspberry Pi [我的Arduino、Espruino好像都是同樣下場 (笑) ],重見天日的 Pi 說:皇上,臣妾想你想得好苦哇~
手邊有的溫濕度感應器是DHT11,原本想循往例依照DHT11的通信規格用Mono C#自幹GPIO驅動物件,但DHT11資料傳輸時序精準度要到Microsecond(百萬分之一秒)等級,C#的Thread.Sleep只有Millisecond(千分之一秒)玩不起。重新評估後決定改走Python(另一個選擇是C/C++,跟魔戒或薩魯曼同隊心理壓力超大,我還是跟樹精做朋友就好),程式語言門檻較低,現成程式庫或範例也多。
先完成硬體接線,DHT11只有三條線,3.3V或5V電源、接地與訊號,訊號線我選擇接在GPIO4(圖中白線)。
軟體部分我先試了網路上很多人提到的Adafruit_Python_DHT,但卡死在用sudo執行還是噴出Error accessing GPIO錯誤,網路上相關討論眾多無明確結論,只知似與Raspberry Pi OS版本有關。另外找到透過pigpio Daemon的做法,單一.py程式搞定感覺較單純易偵錯。前題要先執行pigpio Daemon,pigpiod會以root身分執行,另開Socket介面讓程式以一般身分操作GPIO。我試出來的安裝步驟是:
wget abyz.co.uk/rpi/pigpio/pigpio.zip
unzip pigpio.zip
cd PIGPIO
make
make install
接著sudo pigpiod,dht11.py裡sensor = DHT11(pi, 4)也是走GPIO4針腳跟我的實體接法相同,不用改就能跑,得到溫度與濕度數字代表執行成功:
下一步是建置資料蒐集機制,雖然寫個幾行ASP.NET網頁就能搞定,但不想為了喝牛奶養一頭牛,我找到有圖表功能又容易上手的雲端資料蒐集服務-http://ubidots.com,免註冊用Facebook、Google、Twitter或Github帳號就能登入取得API Key,API教學非常詳細易懂,5個以下Sensor變數不收費,又有線上圖表可看,超級方便。
搞懂API呼叫方法後,在dht11.py中加入程式碼將溫度上傳到ubidots API,SSH登入Pi用nano改程式有點蹩腳,平日習慣Visual Studio豪華的開發環境,這回像是用慣衝鋒槍的突擊隊員被要求拿小彈弓上戰場,充滿無力感。想起Visual Studio 2015支援Python編輯,原本只想借重它的語法高亮顯示跟大視窗,卻驚喜地發現Python Tools for Visual Studio (PTVS ) 支援Goto Definition、Find All References、變數更名、Intellisense 顯示註解,還能設中斷點。順手查了文章,更發現它甚至能遠端連線 Raspberry Pi 進行偵錯,即時顯示區域變數值… 嚇得我滿地撿下巴。(PTVS遠端偵錯示範影片)
Visual Studio 住海邊無誤!
(深夜在粉絲專頁貼完感想拾獲一篇MSDN中文介紹文,有興趣的朋友可以一讀:VS 上開發 Python 你不可不知道的六大功能。
在Python要發送HttpRequest,Requests程式庫是首選,用起來跟C#的WebClient一樣方便,幾行就能搞定跟WebServer往來的大小事。修改dht11.py,一開始import requests,再加入幾行:
if __name__ == '__main__':
pi = pigpio.pi()
sensor = DHT11(pi, 4)
tempVarId = "5776...略...a49b"
humdVarId = "5776...略...bbd4"
url = "http://things.ubidots.com/api/v1.6/variables/"
pathAndToken = "/values?token=bQqr...略...nxnP"
headers = { 'content-type': 'application/json' }
for d in sensor:
print("temperature: {}".format(d['temperature']))
print("humidity: {}".format(d['humidity']))
try:
requests.post(url + tempVarId + pathAndToken, \
data='{ "value": ' + str(d["temperature"]) + ' }', headers=headers)
requests.post(url + humdVarId + pathAndToken, \
data='{ "value": ' + str(d["humidity"]) + ' }', headers=headers)
except:
print("upload error")
time.sleep(60)
sensor.close()
最後還有一關,要能將程式丟到背景跑,才能在退出SSH終端後繼續執行,我選擇用nohup來做:
Raspberry Pi 用USB充電器供電放在冰箱上方,將DHT11垂吊在冰箱與牆壁之間,透過無線網卡登入終端以nohup啟動dht11.py,我的第一個IoT專案-「冰箱散熱器溫度監測系統」就正式上線囉~
附上今天初跑五小時的統計,溫度在30-38度間游離,沒有想像來得熱,我想2公分的間距足夠。至於會不會在某些條件下持續飆高,反正監測系統已成,就進行長期觀察囉~