透過 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Ω 電阻
  • 觸控按鈕

步驟

  1. 將麵包板和元件連線到 Arduino,如圖 18-9 所示。或者,您也可以使用 Squid Button 切換器代替麵包板。
  2. 如果尚未設定 PyFirmata,請按照 Recipe 18.3 進行設定。
  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() 用於讀取按鈕的狀態,傳回 TrueFalsetime.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 建立連線。但是一旦啟動,程式碼就會在每次按下按鈕時印出訊息。

程式碼解釋:

  1. 我們首先匯入必要的模組,包括 pyfirmatatime
  2. 我們初始化 Arduino 連線,指定連線埠為 /dev/ttyACM0
  3. 我們設定輸入引腳為數位引腳 4(’d:4:i’)。
  4. 我們啟動 Iterator 來監控輸入引腳。
  5. 我們啟用輸入引腳的報告功能。
  6. 我們進入無限迴圈,讀取輸入引腳的狀態,並印出訊息當按鈕被按下。

注意事項:

  • 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 的潛力。