透過 PyFirmata 函式庫,Raspberry Pi 可以輕鬆控制 Arduino 的數位輸出並讀取數位及類別比輸入。這項技術常用於物聯網裝置開發,讓 Python 程式能直接與 Arduino 硬體互動。以下範例示範如何控制 LED 閃爍、讀取按鈕狀態以及量測電位器數值。這些應用案例涵蓋了常見的硬體控制情境,並提供程式碼範例作為參考。
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyACM0')
led_pin = board.get_pin('d:10:o')
while True:
led_pin.write(1)
time.sleep(0.5)
led_pin.write(0)
time.sleep(0.5)
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyS0')
led_pin = board.get_pin('d:13:o')
while True:
led_pin.write(1)
time.sleep(0.5)
led_pin.write(0)
time.sleep(0.5)
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyUSB0')
button = board.get_pin('d:2:i')
while True:
state = button.read()
if state:
print("按鈕被按下")
time.sleep(0.5)
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyACM0')
switch_pin = board.get_pin('d:4:i')
it = pyfirmata.util.Iterator(board)
it.start()
switch_pin.enable_reporting()
while True:
input_state = switch_pin.read()
if input_state == False:
print('Button Pressed')
time.sleep(0.2)
import pyfirmata
board = pyfirmata.Arduino('/dev/ttyACM0')
analog_input = board.get_pin('a:0:i')
analog_input.enable_reporting()
while True:
reading = analog_input.read()
voltage = reading * 5.0
print(f'原始讀取值:{reading}, 電壓:{voltage}V')
控制Arduino數位輸出從Raspberry Pi的Python
問題
您想要從Raspberry Pi上的Python控制Arduino的數位輸出。
解決方案
在食譜18.3中,您閃動了Arduino板上的內建LED(標有L)。在這裡,您可以建立在此基礎上,將外部LED連線並撰寫一個簡短的Python程式,使其閃動。
要製作這個食譜,您需要以下元件:
- Arduino Uno(見「模組」) *麵包板和跳線(見「原型設計裝置和套件」)
- 270Ω電阻器(見「電阻器和電容器」)
- LED(見「光電子元件」) 作為使用麵包板和LED的替代方案,您可以插入Squid RGB LED的一個色道(食譜9.10)。
將麵包板連線到Arduino,如圖18-5所示。 圖18-5。Arduino和LED的連線圖
如果您尚未這樣做,請按照食譜18.3設定PyFirmata。
以下Python指令碼使LED以大約1 Hz的速率閃動。你可以在書籍下載的Python部分找到這個程式,稱為ch_18_ardu_flash.py(見食譜3.22):
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyACM0')
led_pin = board.get_pin('d:10:o')
while True:
led_pin.write(1)
time.sleep(0.5)
led_pin.write(0)
time.sleep(0.5)
討論
這與將LED連線到Raspberry Pi(食譜10.1)非常相似。然而,由於Arduino的輸出可以提供比Raspberry Pi輸出更多的電流,因此您可以使用較小的電阻值並使LED稍微更亮。Arduino Uno的輸出也是5V,而不是3.3V。
如果您想要使用者介面(UI)控制LED,就像您在食譜10.8中設定的一樣(如圖18-6所示),修改程式碼相當直接。你可以在書籍下載中找到修改過的程式,稱為ch_18_ardu_gui_switch.py。請記住,這不會從Secure Shell(SSH)命令列工作。你需要存取Raspberry Pi的圖形環境,以便檢視使用者介面。
內容解密:
上述Python程式使用pyfirmata函式庫控制Arduino的數位輸出。board = pyfirmata.Arduino('/dev/ttyACM0')
行建立了與Arduino板的連線。led_pin = board.get_pin('d:10:o')
行取得了Arduino板上第10個數位引腳的控制權。while True
迴圈使LED以大約1 Hz的速率閃動。
圖表翻譯:
graph LR A[Python程式] --> B[PyFirmata函式庫] B --> C[Arduino板] C --> D[LED] D --> E[閃動]
此圖表顯示了Python程式、PyFirmata函式庫、Arduino板和LED之間的關係。Python程式使用PyFirmata函式庫控制Arduino板,然後控制LED閃動。
使用PyFirmata與TTL序列埠進行通訊
問題描述
您想要使用PyFirmata透過序列埠(RXD和TXD在GPIO聯結器上)與Arduino進行通訊,而不是使用USB連線。
解決方案
使用電平轉換器將Raspberry Pi的RXD腳位連線到Arduino的Tx腳位,將Raspberry Pi的TXD腳位連線到Arduino的Rx腳位。
所需元件
- Arduino Uno(見「模組」) -麵包板和跳線(見「原型設計裝置和套件」)
- 270Ω和470Ω電阻器(見「電阻器和電容器」)或四向雙向電平轉換器模組(見「模組」)
組裝步驟
如果您使用電平轉換器模組(而不是自己製作電平轉換器),請按照圖18-7中的連線圖進行連線。
圖18-7:使用電平轉換器模組進行序列通訊的連線圖
如果您使用一對電阻器,請按照圖18-8中的連線圖進行連線。
圖18-8:使用一對電阻器進行序列通訊的連線圖
Arduino Rx輸入可以直接接受來自Raspberry Pi TXD腳位的3.3V訊號;然而,來自Arduino Tx腳位的5V訊號必須降低到Raspberry Pi所期望的3V。
Python程式碼
您需要設定PyFirmata(見配方18.3)。Arduino端的程式碼與使用USB連線的配方18.4相同。您需要修改Python程式碼,將裝置名稱從 /dev/ttyACM0
改為 /dev/ttyS0
,因為序列埠的裝置名稱與USB介面不同。
以下Python指令碼使LED以約1Hz的頻率閃爍(您可以在 ch_18_ardu_flash_ser.py
中找到程式碼,見配方3.22):
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyS0')
led_pin = board.get_pin('d:13:o')
while True:
led_pin.write(1)
time.sleep(0.5)
內容解密:
上述Python程式碼使用PyFirmata函式庫與Arduino進行通訊。首先,匯入必要的函式庫,然後建立一個Arduino物件,指定序列埠的裝置名稱為 /dev/ttyS0
。然後,取得LED所在的腳位,並設定為輸出模式。最後,使用 while
迴圈使LED以約1Hz的頻率閃爍。
圖表翻譯:
以下是PyFirmata與Arduino序列通訊的流程圖:
flowchart TD A[初始化PyFirmata] --> B[建立Arduino物件] B --> C[取得LED腳位] C --> D[設定LED為輸出模式] D --> E[使LED閃爍]
圖表顯示了PyFirmata與Arduino序列通訊的流程,從初始化PyFirmata開始,然後建立Arduino物件,取得LED腳位,設定LED為輸出模式,最後使LED閃爍。
使用 PyFirmata 讀取 Arduino 數位輸入
問題描述
您想要從 Raspberry Pi 上的 Python 讀取 Arduino 的數位輸入。
解決方案
使用 PyFirmata 讀取 Arduino 的數位輸入。
所需元件
- Arduino Uno -麵包板和跳線
- 1kΩ 電阻
- 觸控按鈕
步驟
- 將麵包板和元件連線到 Arduino,如圖 18-9 所示。或者,您也可以使用 Squid Button 切換器代替麵包板。
- 如果尚未設定 PyFirmata,請按照 Recipe 18.3 進行設定。
- 執行以下 Python 指令碼,該指令碼會在按鈕被按下時列印預出一條訊息:
import pyfirmata
import time
# 初始化 PyFirmata
board = pyfirmata.Arduino('/dev/ttyUSB0')
# 設定按鈕引腳為輸入模式
button = board.get_pin('d:2:i')
while True:
# 讀取按鈕狀態
state = button.read()
# 如果按鈕被按下
if state:
print("按鈕被按下")
# 延遲 0.5 秒
time.sleep(0.5)
討論
在這個範例中,我們使用 PyFirmata 讀取 Arduino 的數位輸入。首先,我們需要初始化 PyFirmata 並設定按鈕引腳為輸入模式。然後,我們可以使用 read()
方法讀取按鈕的狀態。如果按鈕被按下,state
變數會為 True
,否則為 False
。最後,我們可以根據按鈕的狀態執行相應的動作。
內容解密
在上述程式碼中,board.get_pin('d:2:i')
用於設定按鈕引腳為輸入模式,其中 d:2:i
表示數位引腳 2 為輸入模式。button.read()
用於讀取按鈕的狀態,傳回 True
或 False
。time.sleep(0.5)
用於延遲 0.5 秒,以避免過快地讀取按鈕狀態。
圖表翻譯
flowchart TD A[初始化 PyFirmata] --> B[設定按鈕引腳] B --> C[讀取按鈕狀態] C --> D[檢查按鈕狀態] D --> E[執行動作] E --> F[延遲 0.5 秒] F --> C
在這個流程圖中,首先初始化 PyFirmata,然後設定按鈕引腳為輸入模式。接下來,讀取按鈕狀態,並檢查按鈕是否被按下。如果被按下,執行相應的動作。最後,延遲 0.5 秒,以避免過快地讀取按鈕狀態。
使用 PyFirmata 監控 Arduino 輸入引腳
要使用 PyFirmata 監控 Arduino 輸入引腳,首先需要建立 Arduino 和 Raspberry Pi 之間的連線。以下是範例程式碼,展示如何使用 PyFirmata 讀取 Arduino 輸入引腳的狀態:
import pyfirmata
import time
# 初始化 Arduino 連線
board = pyfirmata.Arduino('/dev/ttyACM0')
# 設定輸入引腳(本例中為數位引腳 4)
switch_pin = board.get_pin('d:4:i')
# 啟動 Iterator 來監控輸入引腳
it = pyfirmata.util.Iterator(board)
it.start()
# 啟用輸入引腳的報告功能
switch_pin.enable_reporting()
while True:
# 讀取輸入引腳的狀態
input_state = switch_pin.read()
# 如果按鈕被按下(狀態為 False)
if input_state == False:
print('Button Pressed')
# 延遲 0.2 秒以避免多餘的輸出
time.sleep(0.2)
這段程式碼使用 PyFirmata 的 Iterator
來監控 Arduino 的輸入引腳。當按鈕被按下時,程式碼會印出 “Button Pressed” 的訊息。
圖 18-9:Arduino 和按鈕的連線圖
當你執行這段程式碼時,可能需要一兩秒鐘的時間讓 Firmata 啟動並與 Raspberry Pi 建立連線。但是一旦啟動,程式碼就會在每次按下按鈕時印出訊息。
程式碼解釋:
- 我們首先匯入必要的模組,包括
pyfirmata
和time
。 - 我們初始化 Arduino 連線,指定連線埠為
/dev/ttyACM0
。 - 我們設定輸入引腳為數位引腳 4(’d:4:i’)。
- 我們啟動
Iterator
來監控輸入引腳。 - 我們啟用輸入引腳的報告功能。
- 我們進入無限迴圈,讀取輸入引腳的狀態,並印出訊息當按鈕被按下。
注意事項:
- PyFirmata 使用
Iterator
來監控 Arduino 輸入引腳,這意味著你不能直接讀取輸入引腳的值;相反,你需要建立一個獨立的執行緒來管理讀取過程。 - 本範例程式碼假設你已經在 Arduino 上安裝了 Firmata 標準程式。
使用 PyFirmata 讀取 Arduino 模擬輸入
問題描述
您想要從 Raspberry Pi 上的 Python 讀取 Arduino 的模擬輸入。
解決方案
使用 PyFirmata 讀取 Arduino 的模擬輸入。
所需材料
- Arduino Uno -麵包板和跳線
- 10kΩ電位器
連線麵包板
將麵包板連線到 Arduino,如圖 18-10 所示。
安裝 PyFirmata
如果您尚未安裝 PyFirmata,請按照食譜 18.3 的步驟進行安裝。
Python 指令碼
以下 Python 指令碼將顯示模擬輸入的原始讀取值和電壓值:
import pyfirmata
# 初始化 Arduino 連線
board = pyfirmata.Arduino('/dev/ttyACM0')
# 啟用模擬輸入報告
analog_input = board.get_pin('a:0:i')
analog_input.enable_reporting()
# 讀取模擬輸入值
while True:
reading = analog_input.read()
voltage = reading * 5.0 # 假設 5V 電源
print(f'原始讀取值:{reading}, 電壓:{voltage}V')
注意事項
- 啟用模擬輸入報告後,當您按 Ctrl-C 離開程式時,程式可能不會正常離開。
- 如果您只有一個開關,使用 Arduino 如此並沒有太大的益處。
參考資料
- 連線開關到 Raspberry Pi (食譜 12.1)
從 Python 操控 Arduino 數位輸出與讀取數位/類別比輸入,PyFirmata 提供了簡潔易用的橋樑。本文深入剖析 PyFirmata 的核心機制,並從實務佈署的視角探討其應用價值與挑戰。
PyFirmata 將複雜的序列通訊抽象化,讓開發者能以 Python 程式碼直接控制 Arduino 的腳位。透過 board.get_pin()
與 pin.write()
等指令,得以輕鬆控制數位輸出,例如閃爍 LED。此外,讀取數位與類別比輸入也相當直觀,只需設定引腳模式並使用 pin.read()
即可取得感測器資料。然而,PyFirmata 的效能瓶頸在於序列通訊的延遲,尤其在高頻率資料採集時更為明顯。此外,程式結束時可能無法立即釋放序列埠資源,需特別留意。
整合 PyFirmata 至現有系統時,需考慮硬體連線與軟體相容性。使用電平轉換器確保 Raspberry Pi 與 Arduino 的電壓匹配至關重要,避免損壞硬體。軟體方面,則需根據實際應用場景選擇合適的序列埠(/dev/ttyACM0
或 /dev/ttyS0
)。此外,程式碼中使用 Iterator
監控輸入引腳的機制,雖能提升效率,但也增加了程式設計的複雜度。
展望未來,PyFirmata 的發展方向將聚焦於提升通訊效率與擴充套件功能。例如,整合更多 Arduino 函式庫,或支援無線通訊協定,將能進一步拓展其應用範圍。同時,隨著物聯網應用日趨普及,PyFirmata 在連線實體世界與數位世界方面將扮演更重要的角色。對於追求快速原型開發和跨平臺整合的專案,PyFirmata 是一個值得評估的方案。技術團隊應著重於解決通訊延遲和資源釋放等核心挑戰,才能充分釋放 PyFirmata 的潛力。