MicroPython 的 GPIO 控制能力是其核心功能之一,允許開發者透過程式碼直接與外部硬體互動。理解 GPIO 的工作原理及相關的通訊協定,對於開發嵌入式系統和物聯網應用至關重要。本文將詳細介紹如何使用 MicroPython 操作 GPIO,並透過實際範例展示如何控制 LED、讀取按鈕狀態,以及使用 UART、SPI 和 I2C 等通訊協定與外部裝置進行資料交換。此外,文章也涵蓋了紅外線通訊的原理和應用,以及進階的 GPIO 技巧如位元碰撞,提供讀者更全面的 MicroPython GPIO 應用。
GPIO 與外部裝置的互動
GPIO(General Purpose Input and Output)是微控制器與外部世界溝通的橋樑。透過GPIO,MicroPython 能夠控制和讀取連線的外圍裝置,從而實作對外部世界的感知和控制。每個GPIO引腳都有特定的名稱,以便在程式中參照,根據組態的不同,這些引腳能夠處理和傳送不同型別的訊號。
引腳的工作原理
「引腳」是一個泛稱,歷史上它指的是看起來像針腳的連線點,但現代的設計往往並非如此。在本文的上下文中,引腳是指連線到微控制器的導電區域,透過這些區域可以與外部裝置進行通訊。圖9-1顯示了micro:bit上的「引腳」特寫:
這些「引腳」並不像傳統的針腳,有些甚至大到可以直接用鱷魚夾夾住。它們位於開發板的底部邊緣,但你可能會疑惑如何連線裝置到那些較小的引腳。解決方案是使用邊緣聯結器,將跳線連線到外部裝置,或使用麵包板來放置外部元件(圖9-2)。
使用外設進行感測
雖然micro:bit、Circuit Playground Express和PyBoard都具備內建的輸入和感測器,但你也可以將外設連線到任何執行MicroPython的裝置的GPIO引腳。關鍵在於透過引腳存取裝置,就像本章前面示範的那樣。對於外部外設,它們會使用可用的外部引腳,而不是直接連線到板上元件的「引腳」。
以下是一個使用ESP8266開發板的簡單範例(圖8-2):
from machine import Pin
led = Pin(2, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)
while True:
led.value(button.value())
內容解密:
from machine import Pin:從machine模組匯入Pin類別,用於控制GPIO引腳。led = Pin(2, Pin.OUT):將引腳2組態為輸出模式,用於控制LED燈。button = Pin(14, Pin.IN, Pin.PULL_UP):將引腳14組態為輸入模式,並啟用上拉電阻,用於讀取按鈕狀態。while True::進入無限迴圈,不斷讀取按鈕狀態並更新LED狀態。led.value(button.value()):將LED的狀態設定為按鈕的當前值,實作按鈕控制LED的效果。
這個範例展示瞭如何透過GPIO引腳讀取外部按鈕的狀態,並控制LED燈的開關。
常見的通訊協定
本章將介紹三種常見的通訊協定:UART、SPI和I2C,這些協定使得與外部裝置的互動變得簡單和標準化。透過這些協定,你可以輕鬆地與各種外設進行資料交換,實作更豐富的功能。
UART 協定
UART(Universal Asynchronous Receiver/Transmitter)是一種常用的串列通訊協定,用於裝置之間的非同步資料傳輸。它只需要兩根線(TX和RX)即可實作雙向通訊,廣泛應用於微控制器與電腦或其他裝置之間的資料交換。
SPI 協定
SPI(Serial Peripheral Interface)是一種高速、全雙工的串列通訊協定,主要用於微控制器與外設之間的高速資料傳輸。SPI通常需要四根線(MOSI、MISO、SCK和CS),能夠實作高效的資料交換。
I2C 協定
I2C(Inter-Integrated Circuit)是一種多主機、多從機的串列通訊協定,只需要兩根線(SCL和SDA)即可實作多裝置之間的資料傳輸。I2C協定廣泛應用於各種感測器、顯示模組和其他外設的連線。
透過瞭解和掌握這些通訊協定,你可以更加靈活地使用MicroPython開發各種應用,與外部世界進行互動。
GPIO 與微控制器的互動基礎
在微控制器(如 micro:bit、Circuit Playground Express、PyBoard 和 ESP8266/32)的世界中,GPIO(通用輸入/輸出)針腳扮演著至關重要的角色。這些針腳讓開發者能夠與外部周邊裝置進行互動,實作各種創意專案。
針腳的命名與功能
不同的微控制器板有不同的針腳組態和命名規則。例如,micro:bit 和 Circuit Playground Express 的針腳較大,便於使用鱷魚夾進行連線;而 PyBoard 則有兩種組態,一種是沒有預先焊接針腳,另一種是預先焊接了 female 針腳。ESP8266/32 板通常預先焊接了 male 針腳。
針腳的名稱通常印在電路板上,以便開發者參考。在程式碼中參照針腳時,需要根據所使用的 MicroPython 版本和裝置型別進行不同的操作。例如,在 micro:bit 上,需要使用 microbit 模組;而在 CircuitPython 中,則使用 board 模組。
針腳的多樣功能
GPIO 針腳有多種功能,包括:
- 數位輸入/輸出:控制針腳的狀態為高(3.3V)或低(0V)。
- 類別比輸入/輸出:讀取或輸出介於高低之間的電壓值。
- 電容式觸控:檢測人體觸控。
- 中斷請求(IRQ):當針腳狀態改變時,觸發中斷請求。
中斷請求(IRQ)的使用
在某些微控制器板上,可以定義中斷請求(IRQ),當針腳的輸入狀態改變時觸發回呼函式。以下是一個 ESP8266 板的範例:
from machine import Pin
def callback(p):
print('Pin', p)
p0 = Pin(0, Pin.IN)
p0.irq(trigger=Pin.IRQ_FALLING, handler=callback)
內容解密:
- 匯入
machine模組中的Pin類別,用於控制 GPIO 針腳。 - 定義一個回呼函式
callback,當中斷請求觸發時列印針腳物件。 - 將針腳 0 設定為輸入模式,並定義中斷請求的觸發條件為下降沿(
Pin.IRQ_FALLING),並指定回呼函式。 - 當針腳 0 的狀態從高變低時,回呼函式被觸發,列印相關資訊。
序列通訊與 UART
UART(通用非同步收發傳輸器)是微控制器中用於序列通訊的硬體元件。它將序列訊號轉換為平行位元組,或將平行位元組轉換為序列訊號。UART 在 REPL(互動式命令列介面)中扮演著重要角色,使得開發者能夠透過 USB 連線與微控制器進行通訊。
串列通訊協定:UART 與 SPI 詳解
在微控制器與外設之間的通訊中,串列通訊協定扮演著重要的角色。其中,UART(通用非同步收發傳輸器)與 SPI(串列周邊介面)是兩種常見的串列通訊協定。
UART 通訊協定
UART 是一種非同步串列通訊協定,廣泛應用於微控制器與電腦之間的通訊。要實作 UART 通訊,需要進行以下組態:
- 連線 TX 與 RX 引腳:裝置 A 的 TX 引腳須連線到裝置 B 的 RX 引腳,反之亦然。
- 設定鮑率:雙方須約定相同的鮑率(bits per second),常見的鮑率有 9600、14400、19200、28800、38400、57600 和 115200。
- 設定資料位元、奇偶校驗位元和停止位元:通常資料位元為 8 位元,但有時需要指定奇偶校驗位元和停止位元的數量。
UART 具有「先進先出」(FIFO)佇列,能夠緩衝接收到的資料。MicroPython 開發板上的 UART 通常連線到內部 USB-UART TX/RX 引腳,透過 USB 連線到電腦。在電腦端,可以使用 pySerial 或 picocom 等函式庫或工具開啟串列連線,實作與 MicroPython REPL 的通訊。
MicroPython 中的 UART 範例
from microbit import *
while True:
msg = uart.read()
if msg:
uart.write(msg)
此範例演示瞭如何使用 UART 讀取和寫入資料到連線的電腦。micro:bit 開發板具有一個 uart 物件來處理通訊。其他開發板可能需要例項化 UART 類別並進行相應的組態。
SPI 通訊協定
SPI 是另一種串列通訊協定,與 UART 不同的是,它是一種同步資料匯流排,具有裝置階層結構。
SPI 的特點
- 同步時脈訊號:SPI 使用時脈訊號(SCLK)來同步資料傳輸,避免了 UART 中因時脈不同步而導致的錯誤。
- 主從式架構:SPI 具有主從式架構,主裝置(通常是微控制器)提供時脈訊號,從裝置則根據時脈訊號進行資料傳輸。
- 資料傳輸連線:SPI 使用 MOSI(主出從入)和 MISO(主入從出)連線進行資料傳輸。
- 晶片選擇(CS)連線:SPI 使用 CS 連線來選擇特定的從裝置進行資料傳輸。
SPI 組態範例
SPI 可以組態為獨立從裝置模式或菊花鏈模式。在獨立從裝置模式中,每個從裝置都有一個獨立的 CS 連線。在菊花鏈模式中,所有從裝置共用一個 CS 連線。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333
title SPI 組態範例
rectangle "SCLK" as node1
rectangle "MOSI" as node2
rectangle "MISO" as node3
rectangle "CS" as node4
node1 --> node2
node2 --> node3
node3 --> node4
@enduml
此圖示說明瞭 SPI 的主從式架構和兩種組態模式。
#### 內容解密:
此圖表呈現了 SPI 的基本架構,包括主裝置和從裝置之間的連線。在獨立從裝置模式中,每個從裝置都有獨立的 CS 連線,而在菊花鏈模式中,所有從裝置共用一個 CS 連線,並透過 MISO 連線串聯起來。這種架構使得 SPI 能夠支援多個從裝置的通訊。
SPI與I2C通訊協定在MicroPython中的應用
在MicroPython中,SPI(Serial Peripheral Interface)與I2C(Inter-Integrated Circuit)是兩種重要的硬體通訊協定,分別具有不同的特點和應用場景。
SPI通訊協定
SPI是一種高速的、全雙工的同步序列通訊協定,廣泛應用於微控制器與周邊裝置之間的資料傳輸。其主要特點包括:
- 高速資料傳輸
- 全雙工通訊
- 主從式架構
- 需要至少四條連線線(MISO、MOSI、SCLK、CS)
在SPI通訊中,主裝置透過CS(Chip Select)訊號選擇特定的從裝置進行資料交換。資料傳輸透過MISO(Master In Slave Out)和MOSI(Master Out Slave In)線路進行,分別負責主裝置接收從裝置資料和主裝置向從裝置傳送資料。
Daisy Chain組態
SPI支援Daisy Chain組態,即多個從裝置串聯連線,主裝置只需一個CS訊號即可控制所有從裝置。資料透過每個從裝置傳遞,最終到達目標裝置。
from machine import SPI, Pin
# 初始化SPI物件
spi = SPI('X')
# 初始化CS物件
cs = Pin('X1', Pin.OUT)
# 啟動CS訊號
cs.value(0)
# 建立資料緩衝區
buffer = bytearray(5)
# 進行資料交換
spi.write_readinto(b'hello', buffer)
# 結束CS訊號
cs.value(1)
程式碼解析
- 初始化SPI物件:使用
SPI('X')初始化SPI物件,指定SPI介面。 - 初始化CS物件:使用
Pin('X1', Pin.OUT)初始化CS物件,並設定為輸出模式。 - 啟動CS訊號:將CS訊號設為低電平,啟動與從裝置的通訊。
- 建立資料緩衝區:使用
bytearray(5)建立一個大小為5位元組的資料緩衝區。 - 進行資料交換:使用
spi.write_readinto(b'hello', buffer)進行資料交換,將b'hello'傳送到從裝置,並將從裝置的回應儲存在buffer中。 - 結束CS訊號:將CS訊號設為高電平,結束與從裝置的通訊。
I2C通訊協定
I2C是一種半雙工的同步序列通訊協定,使用兩條線路(SCL、SDA)進行資料傳輸。其主要特點包括:
- 半雙工通訊
- 主從式架構
- 支援多主裝置和多從裝置
- 需要兩條連線線(SCL、SDA)
在I2C通訊中,主裝置透過SCL(Serial Clock)訊號控制時鐘,SDA(Serial Data)訊號傳輸資料。從裝置透過地址識別自身是否為目標裝置。
I2C通訊流程
- 起始條件:主裝置將SDA訊號拉低,同時保持SCL訊號高電平,表示開始新的通訊。
- 地址幀:主裝置傳送7位元地址和1位元讀寫控制位,從裝置根據地址識別自身是否為目標裝置。
- 確認位元:目標從裝置將SDA訊號拉低,表示確認收到地址幀。
- 資料幀:主裝置或從裝置根據讀寫控制位傳輸資料。
- 停止條件:主裝置將SCL訊號拉高,同時將SDA訊號拉高,表示結束通訊。
from machine import I2C
# 初始化I2C物件
i2c = I2C('X')
# 掃描I2C匯流排上的裝置
devices = i2c.scan()
print(devices)
# 向指定裝置寫入資料
i2c.writeto(46, b'A')
# 從指定裝置讀取資料
data = i2c.readfrom(46, 8)
print(data)
程式碼解析
- 初始化I2C物件:使用
I2C('X')初始化I2C物件,指定I2C介面。 - 掃描I2C匯流排上的裝置:使用
i2c.scan()掃描I2C匯流排上的裝置,並傳回裝置地址列表。 - 向指定裝置寫入資料:使用
i2c.writeto(46, b'A')向地址為46的裝置寫入位元組b'A'。 - 從指定裝置讀取資料:使用
i2c.readfrom(46, 8)從地址為46的裝置讀取8位元組的資料。
綜上所述,SPI和I2C是兩種常見的硬體通訊協定,分別具有不同的特點和應用場景。在MicroPython中,可以使用相關的函式庫和API實作這兩種通訊協定,從而實作微控制器與周邊裝置之間的資料交換。
網路連線
由於執行MicroPython的裝置體積小巧,無法容納乙太網路介面。因此,這些裝置若具備相互通訊的能力,通常採用無線方式進行。
無線通訊的魅力
遠距離互動總帶有某種奇妙的滿足感,彷彿是在施展魔法。然而,這背後的原理遠比魔法更為精彩:物理學!本章將探討兩種通訊方式:紅外線(適用於Circuit Playground Express)與無線電(適用於micro:bit及ESP8266/32為基礎的裝置)。
紅外線通訊
紅外線通訊最常見的應用是電視遙控器:使用者按下按鈕,遙控器發出訊號給電視。紅外線在短距離內效果良好,但需要發射器與接收器之間有直接視線(因此需要將遙控器對準電視)。
紅外線的工作原理
紅外線的波長略低於可見光,因此人類無法直接觀察到紅外線。環境中有許多紅外線源,例如陽光、燈泡、蠟燭,甚至人體(人體輻射的大部分熱能都屬於紅外線光譜)。為了減少環境中紅外線源的幹擾,傳送訊號時通常會對訊號進行調變。所謂調變,是指訊號以預先約定的頻率傳送,最常見的是38 kHz(儘管也有其他頻率被使用)。簡單來說,紅外線發射器以每秒38,000次的頻率閃爍。這種訊號與環境中的其他紅外線源有所不同,從而減少幹擾。
MicroPython中的I2C介面使用範例
>>> i2c.writeto_mem(46, 0, b'A')
>>> i2c.readfrom_mem(46, 0, 2)
b'\x00A'
程式碼解析:
i2c.writeto_mem(46, 0, b'A'):向位址為46的I2C裝置的記憶體位址0寫入字元’A’。i2c.readfrom_mem(46, 0, 2):從位址為46的I2C裝置的記憶體位址0讀取2個位元組。
這個範例展示瞭如何在MicroPython中使用I2C介面與外部裝置進行通訊。
GPIO進階技巧與協定
除了常見的UART、SPI和I2C協定之外,一些周邊裝置可能使用專有的協定,例如NeoPixels(也稱為ws2812)和數位濕度與溫度(DHT)感測器系列,它們都使用1-wire介面。MicroPython已經為這兩種裝置提供了模組,因此實際實作細節並不重要。然而,當遇到沒有標準協定的周邊裝置時,若沒有現成的模組可用,可能需要自行實作相關程式碼。
位元碰撞(Bit Banging)
位元碰撞是一種忽略硬體協定,直接使用軟體控制針腳、時序、電平和同步,以創造低成本、高度客製化的解決方案來處理周邊裝置問題的方法。這是一種「駭客」行為,但也正是其趣味所在。當遇到需要與硬體進行非標準互動的情況時,位元碰撞提供了一種靈活的解決方案。
網路連線的重要性
MicroPython執行於微控制器上,提供了一種高階、表達力強且易於使用的語言,使開發者能夠在極短的時間內建立可運作的解決方案。這種接近硬體卻又具備高階語言特性的開發方式,使得MicroPython成為一種優秀的教育工具。開發者既能夠深入瞭解電腦硬體的工作原理,又能夠使用功能強大、靈活且易於學習的程式語言。將MicroPython所學的技能轉移到「一般」Python程式設計中,也證明瞭Python生態系統所提供的經驗連續性。