最近接到了一個需求,是想要用樹莓派連接 Arduino UNO 來控制與偵測電路的開關狀態。在開發這項功能時最麻煩且最容易出 Bug 的地方就是作業系統和 Arduino 的通訊,也就是序列埠 (Serial Port)。思考到這幾年 Python 非常夯,又剛好樹莓派標配的作業系統也是 Linux,對 Python 的支援性也很好,就在思考有沒有辦法只用 Python 來控制與偵測 Arduino 腳位的電路狀態,就找到了 Firmata 這個有趣東西。
先說重點,Firmata 讓我們不用寫任何 Arduino C++ 程式碼,只要把內建的一支程式燒進去就能動,邏輯的設計都在 Python 寫,再加上 Python 本身能結合各種網路連線、資料儲存之類的功能,整個開發就變的很有彈性。但缺點很明顯,因為全部都靠 Firmata,要整合如 RFID 之類的複雜感測模組可能就沒那麼容易,所以目前打算先將它應用在簡單電路。
燒錄 Firmata 至 Arduino
前面有說,我們不用寫任何 Arduino C++。請開啟 Arduino IDE,開啟頂部選單 > File > Examples > Firmata > StandardFirmata。
它會開啟一個名為 StandardFirmata 的專案,請連接上 Arduino 後直接燒錄進去,下一步我們將要來寫 Python。
安裝 pyFirmata2
請為樹莓派接上電源,並配置好開發環境。我們需要一個可以安裝 pip 套件的 Python 3 虛擬環境,可以參考前一篇 使用 VS Code 遠端開發 Python 程式 的教學。
首先,請在終端機輸入以下指令,安裝 pyFirmata2 套件。
1pip install pyfirmata2
找到 Arduino 序列埠
在開始寫程式之前,我們要先找到 Arduino 在樹莓派上的序列埠名稱。我們平常看到的 COM3、COM4 是在 Windows 上才能用的名稱,Linux 使用的是 /dev/ttyOOXX。
我們沒辦法在樹莓派上開裝置管理員或 Arduino IDE 的話要怎麼看呢?
首先,請先在還沒有連接 Arduino 的狀態下,在終端機輸入以下指令,你可以先看到一大堆的序列埠:
1ls /dev/tty*
現在再將 Arduino 用 USB 線連接到樹莓派,然後再輸入一次剛才的指令 (可以按鍵盤方向鍵上來執行上一個指令)。我們可以發現多出了一個 /dev/ttyACM0,有時候可能名稱會不一樣,但重點是現在新出現的這個就是 Arduino 的序列埠名稱,請把它記下來。
撰寫 Python 程式
進入重頭戲,我們現在要來用 Python 控制 Arduino 對電路的輸出,用 LED、1kΩ 電阻和杜邦線接兩個 LED,正極分別接在 12 與 13 腳位,待會要讓它交替閃爍。
接下來要來寫程式,請把以下程式碼複製貼上到 main.py 或自己建一個副檔名為 .py 的 Python 檔案內,並修改第 4 行內的序列埠字串為你剛才紀錄的名稱,這邊假設序列埠名稱就是 /dev/ttyACM0。
1import pyfirmata2
2import time
3
4board = pyfirmata2.Arduino('/dev/ttyACM0')
5
6while True:
7 board.digital[12].write(0)
8 board.digital[13].write(1)
9 time.sleep(1)
10 board.digital[12].write(1)
11 board.digital[13].write(0)
12 time.sleep(1)
依序解釋一下程式碼的作用:
- 前兩行是匯入程式有用到的 pyFirmata2 和 time 程式庫。
- 第四行是建立 Python 與 Arduino 的連線。
- 接下來開一個無限回圈,如同 Arduino 的 loop。
- 首先指定腳位 12 為 LOW、13 為 HIGH,如同 Arduino 的 digitalWrite。
- 再用 time.sleep 延遲 1 秒鐘,如同 Arduino 的 delay。
- 同樣邏輯,只不過 12、13 腳位的狀態相反。
最後點擊右上角的播放按鈕即可執行程式。
執行結果如影片,兩顆 LED 將會交替閃爍!我覺得這方法真的很適合用在簡單電路開關情境,這次我們只有先控制腳位的高低電位,下一次這系列的文章預計要來實際拿按鈕 or 磁簧開關等零件來實作腳位狀態的讀取!