前陣子入手 3D 印表機,從網路下載現成模型幫老古董 Raspberry Pi B+ 印了外個殼,一時懷舊之心大發,翻出舊零件拼裝了一台可轉動鏡頭角度的網路照相機,還騷包寫了網頁版控制介面,摸到一大票新東西,筆記留念一下。
Raspberry Pi 的硬體 IO 介面不如 Arduino 豐富,能控制伺服馬達的 PWM 輸出只有一組,想控制多個伺服馬達通常會外接 I2C 介面控制板,前陣子玩 Arduino時入手一塊 PCA9685 16 路舵機控制板還沒拆封,這回正好派上用場。(下圖前方的長方形藍色電路板就是)
PCA9685 控制板用 4 條線連上 Raspberry Pi,二者使用 I2C 協定溝通,讓 RPi 可控制多達 16 個伺服馬達。而攝影鏡頭旋轉座只需兩個,一個水平旋轉,一個控制仰角。下圖的黑色 2 軸塑膠雲台也是之前買的,現在雖然又多了自己 3D 列印選項,但規格已標準化的東西,大量生產的成品還是遠比自幹省時省力也省錢。
Raspberry Pi 的程式開發資源以 Python/C 為大宗,Pi B+ 沒法玩 .NET Core,就用 Python 吧! 反正這年頭什麼語言都可以用 Visual Studio Code 寫。 XD
照著範例改寫出一支 servo.py(註:Python 有個奇妙特色,縮排是有意義的不能隨興亂調,寫慣 C#/JavaScript 有點不適應 ),藉由 python survo.py x y控制水平/垂直伺服馬達角度,拍照則用 raspistill -o photo.jpg –w 640 –h 480,不過 Raspberry Pi 拍照超慢,拍一張照片耗時 5 秒,調參數可縮短曝光時間,但照片亮度會嚴重偏暗。無論如何,到這裡一台由命令列控制的可轉鏡頭照相機算是完成了。但,身為前端攻城師,沒提供網頁操作介面像話嗎? 於是,我又踏上另一段奇幻旅程...
前面說過我的樹莓派是古老的 B+ 版,最新版 ASP.NET Core 不是選項,回頭花時間鑽研 Mono 投資效益不佳。要在 Pi 寫網頁,Apapche 與 PHP 有現成的套件可裝,一個 sudo apt-get install … 指令就順利搞定,那就用 PHP 來寫網站好了。
爬文惡補 PHP,透過 URL 控制伺服馬達及拍照是靠底下這一小段程式搞定,程式接收參數並呼叫外部程式,透過 Python 程式旋轉鐘頭,使用 raspistill 拍照。
<html><?php
$h = intval($_GET['h']); //200-600, mid 400
$v = intval($_GET['v']); //100-500, mid 350
if ($_GET['m'] == "R") {
$h = 400;
$v = 350;
}
if ($h > 0 || $v > 0) {
if ($h == 0)
$h = -1;
else {
$h = max($h, 200);
$h = min($h, 600);
}
if ($v == 0) {
$v = -1;
}
else {
$v = max($v, 150);
$v = min($v, 500);
}
$cmd = sprintf("sudo python /home/pi/python/servo/Adafruit_Python_PCA9685/examples/runservo.py %d %d", $h, $v);
$result = exec($cmd, $output);
}
if ($_GET['m'] == 'S')
exec('sudo raspistill -w 640 -h 480 -o /home/pi/php/webcam/photo/current.jpg -n -ex auto -awb auto');
?></html>
在陌生程式領域裡探險,資深老鳥重溫菜鳥心境,意外有個感想:
避免寫出不安全的程式絕對是必要,但對菜鳥還真是一項考驗。
依據多年的開發經驗,我一眼看出裡面隱藏了資安風險:一個是將使用者輸入內容轉為呼叫外部程式參數有指令碼注入風險,二則是開放網頁程式以管理者身分執行,一旦程式有漏洞,損害程度加劇。
前者倒不難處理,只需強制將參數轉成數字,即能社絕偷渡 Shell 指令。至於後者,較好的做法是另寫一個本機服務,透過 IPC / Socket 接收指令做事,如此網站使用低權限執行身分即可。這種中間服務如在 Windows / C# 我是信手拈來,如今身處 Raspberry Pi 環境就難如登天了,只能先接受這種可行但不安全的解決方案。實務上,應該有不少的安全漏洞也在類似情境下誕生,更何況,有更多情況是開發者壓根沒意識某些做法或寫法是不安全的... (尤其是無任何開發經驗的正港菜鳥)
PHP 搞定後,前端我用 SPA 來做,總算又回到我熟悉的領域,不過我決定用 Vue.js 當成練習,強迫自己跟它培養感情。
我在 Raspiberry Pi 設定 Samba 分享程式相關資料夾,Python、PHP、Vue.js 都是在 Windows 10 用 Visaul Studio Code 連上網路磁碟機修改,開發體驗還不錯。
影片部分,我又順手練習簡單後製還假掰配上 YouTuber 經典 BGM,RPi 相機的速度太慢,不過拿來拍縮時影片應該OK,至於監控用途,另外要走 Streaming 模式,下回再研究。總結是一次綜合格鬥練習,用上了 Ubuntu、GPIO、I2C、Python、PHP、Vue.js、影片後製... 呵。
謝謝收看。
【參考資料】
- 四軸飛行器- Raspberry - 使用PCA9685控制板,控制伺服馬達
- Adafruit-raspi-python-Adafruit_MotorShield at master · CaptainStouf-Adafruit-raspi-python
- 葉難- Raspberry Pi:Samba伺服器
- Using the Adafruit Library - Adafruit 16 Channel Servo Driver with Raspberry Pi - Adafruit Learn
- Executing GPIO python scripts through PHP - Raspberry Pi Forums