MicroPython 簡潔易學的特性,使其成為嵌入式系統開發的理想選擇,尤其在硬體互動和視覺化應用方面更具優勢。本文將以 NeoPixels、micro:bit 和 PyBoard 的 LCD160CR 為例,展示 MicroPython 如何控制 LED、顯示文字、影像和動畫,以及如何處理按鈕輸入。透過程式碼範例和詳細的解說,讀者可以快速掌握 MicroPython 的核心概念,並將其應用於實際專案中。此外,文章也探討了事件迴圈和暫停機制的重要性,以及如何避免在處理快速輸入事件時出現錯誤。對於想要深入學習 MicroPython 的開發者來說,本文提供了豐富的實用技巧和參考資訊。
NeoPixels:閃爍燈光的進階應用
NeoPixels 是 MicroPython 和 CircuitPython 中用於控制 LED 燈串的強大工具。它們可以顯示多種顏色,並透過簡單的程式碼控制。在本章中,我們將探討如何使用 NeoPixels 來實作各種視覺效果。
NeoPixels 的基本操作
要使用 NeoPixels,首先需要匯入 neopixel 模組,並例項化 NeoPixel 類別。這個類別需要兩個主要引數:連線 NeoPixels 的針腳和 NeoPixels 的數量。以 Circuit Playground Express 為例,程式碼如下:
import neopixel
from board import NEOPIXEL
np = neopixel.NeoPixel(NEOPIXEL, 10, auto_write=False)
內容解密:
import neopixel:匯入neopixel模組,用於控制 NeoPixels。from board import NEOPIXEL:從board模組匯入NEOPIXEL,它代表連線 NeoPixels 的針腳。np = neopixel.NeoPixel(NEOPIXEL, 10, auto_write=False):例項化NeoPixel類別,設定 NeoPixels 的數量為 10,並將auto_write設為False,表示需要手動更新 NeoPixels 的狀態。
控制單個 NeoPixel
NeoPixels 可以像列表一樣被存取和修改。使用下標符號([])可以取得或設定特定位置的 NeoPixel 的顏色。
>>> np[0]
(0, 0, 0)
>>> np[0] = (32, 0, 32)
>>> np.write()
內容解密:
np[0]:取得第一個 NeoPixel 的當前顏色,傳回一個包含三個整數的元組,代表紅、綠、藍三種顏色的強度。np[0] = (32, 0, 32):將第一個 NeoPixel 的顏色設定為紫色(紅色和藍色強度為 32,綠色強度為 0)。np.write():手動更新 NeoPixels 的狀態,使更改生效。
同時控制所有 NeoPixels
可以使用 fill 方法一次性設定所有 NeoPixels 的顏色。
>>> np.fill((0, 32, 32)) # 將所有 NeoPixels 設定為青色
>>> np.write()
內容解密:
np.fill((0, 32, 32)):將所有 NeoPixels 的顏色設定為青色(綠色和藍色強度為 32,紅色強度為 0)。np.write():更新 NeoPixels 的狀態,使更改生效。
視覺回饋:點亮NeoPixels與micro:bit顯示
NeoPixels的色彩魔法
NeoPixels是一種能夠呈現絢麗色彩的LED燈條,透過簡單的程式控制即可創造出令人驚豔的視覺效果。以下是一個結合NeoPixels與迴圈控制,使裝置看起來像活著的範例:
import neopixel
import random
import time
from board import NEOPIXEL
np = neopixel.NeoPixel(NEOPIXEL, 10, auto_write=False)
step = 32
while True:
for i in range(10):
for j in range(10):
np[j] = tuple((max(0, val - step) for val in np[j]))
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
np[i] = (r, g, b)
np.write()
time.sleep(0.05)
內容解密:
- 初始化NeoPixels:使用
neopixel.NeoPixel類別初始化10個NeoPixels,並設定auto_write=False以避免每次更改都立即寫入。 - 迴圈控制:進入無限迴圈,遍歷每個NeoPixel。
- 調暗其他LED:對每個NeoPixel,將其目前的RGB值降低
step(32),確保不會低於0,以實作漸暗效果。 - 隨機色彩:為目前選中的NeoPixel生成隨機的RGB色彩值。
- 寫入並延遲:將新的色彩值寫入NeoPixels,並暫停0.05秒以控制效果速度。
這個範例創造了一個隨機變色的迴圈燈效,可以透過調整time.sleep的值來改變效果的速度,或是修改step的值來控制燈光漸暗的速度和「尾巴」的長度。
micro:bit的文字、影像與動畫
micro:bit擁有一個5x5的紅色LED矩陣顯示屏,可以用來呈現文字、影像和簡單的動畫。
滾動文字
from microbit import display, Image
display.scroll("Hello, World!")
內容解密:
display.scroll方法:用於在micro:bit的顯示屏上滾動顯示文字。- 引數控制:可以透過
delay引數控制滾動速度,wait引數決定是否等待滾動完成,loop引數設定是否迴圈滾動,monospace引數控制字元寬度。
例如,以下程式碼實作了一個快速、迴圈滾動的單空格訊息:
display.scroll("Hello!", delay=80, wait=False, loop=True, monospace=True)
顯示靜態文字
如果希望文字一個接一個地顯示而不是滾動,可以使用display.show方法:
display.show("Danger!")
內容解密:
display.show方法:用於在micro:bit的顯示屏上顯示文字或影像。- 引數控制:支援與
scroll方法類別似的引數,如wait和clear,但不包含monospace。
影像顯示
micro:bit內建了一個Image類別,可以用來顯示預設或自定義的影像。
顯示預設影像
display.show(Image.HAPPY)
內容解密:
Image類別:提供了多種預設影像,如HAPPY、SAD等。display.show方法:用於顯示選定的影像。
自定義影像
你可以透過建立Image例項來建立自定義影像:
my_picture = Image(
'33333:'
'36663:'
'36963:'
'36663:'
'33333:')
display.show(my_picture)
內容解密:
- 字串表示法:使用數字(0-9)代表LED的亮度,冒號(:)表示行結束。
- 自定義影像:根據字串描述生成對應的影像,並顯示在micro:bit上。
這些範例展示瞭如何利用micro:bit和NeoPixels創造出豐富的視覺效果,從簡單的文字滾動到複雜的影像和動畫,都能為你的專案增添更多的互動性和趣味性。
使用 micro:bit 的 Image 類別建立與操作影像
micro:bit 的 Image 類別提供了一個強大的方式來建立和操作影像,使其能夠在 micro:bit 的 LED 顯示屏上顯示。一個 Image 例項不一定要受限於顯示屏的尺寸,這使得它可以用於建立更大尺寸的遊戲或應用程式。
建立 Image 物件
建立 Image 物件有兩種主要方法:使用字串和使用 bytearray。
使用字串建立 Image
from microbit import display, Image
# 建立一個 5x5 的影像
image = Image("00000:"
"90009:"
"09090:"
"90009:"
"00000")
display.show(image)
使用 bytearray 建立 Image
from microbit import display, Image
# 使用 bytearray 建立一個 10x10 的影像
buf = bytearray(x % 10 for x in range(100))
image = Image(10, 10, buf)
display.show(image.crop(3, 4, 5, 5))
內容解密:
bytearray(x % 10 for x in range(100)):這行程式碼生成了一個包含 100 個元素的bytearray,每個元素的值在 0 到 9 之間,代表了影像中每個畫素的亮度。Image(10, 10, buf):利用生成的bytearray,建立了一個 10x10 的影像。image.crop(3, 4, 5, 5):從原始影像中裁剪出一個 5x5 的子影像,並將其顯示在 micro:bit 的 LED 顯示屏上。
操作 Image 物件
Image 物件提供了多種方法來操作影像,包括:
copy():傳回影像的副本。invert():傳回一個新影像,其畫素亮度與原始影像相反。fill(value):將所有畫素設定為指定的亮度值。get_pixel(x, y):取得指定位置畫素的亮度。set_pixel(x, y, value):設定指定位置畫素的亮度。shift_left(n)、shift_right(n)、shift_up(n)、shift_down(n):將影像向指定方向移動 n 個畫素。blit(src, x, y, w, h):將源影像的一部分複製到當前影像中。
使用 shift 方法實作滾動效果
from microbit import display, Image
# 建立一個影像
image = Image("00000:"
"90009:"
"09090:"
"90009:"
"00000")
# 向右滾動影像
for _ in range(5):
display.show(image)
image = image.shift_right(1)
內容解密:
image.shift_right(1):將影像向右移動 1 個畫素。- 在迴圈中不斷顯示和更新影像,實作滾動效果。
製作動畫
透過使用迭代器物件傳回一系列 Image 物件,可以在 micro:bit 上建立動畫。
使用內建的動畫幀列表
from microbit import display, Image
display.show(Image.ALL_CLOCKS, delay=50, wait=False, loop=True)
自定義動畫
from microbit import display, Image
import random
import array
def animation():
while True:
blinkenlights = array.array('b', [random.randint(0, 9) for _ in range(25)])
yield Image(5, 5, blinkenlights)
display.show(animation())
內容解密:
animation()函式是一個生成器,不斷生成新的隨機影像。display.show(animation())將生成器傳回的影像序列顯示為動畫。
PyBoard 彩色 LCD 顯示技術詳解
LCD160CR 顯示控制基礎
在 MicroPython 的世界中,控制 LCD160CR 這類別彩色 LCD 顯示幕是一項有趣且實用的技術。首先,我們需要使用 LCD160CR 類別來例項化一個代表實體 LCD 裝置的物件,並指定裝置的連線方式(“X” 或 “Y”)。一旦例項化,裝置就會啟動並顯示 MicroPython 的標誌,表示它正在運作。
import lcd160cr
lcd = lcd160cr.LCD160CR('X')
lcd.erase()
內容解密:
lcd160cr.LCD160CR('X'):例項化 LCD160CR 物件,指定連線埠為 ‘X’。lcd.erase():清除螢幕上的內容。
REPL 輸出重定向至 LCD 顯示
將 REPL(Read-Eval-Print Loop)輸出重定向至 LCD 顯示,可以讓開發者直接在 LCD 上與 MicroPython 互動。
import pyb
uart = pyb.UART('XA', 115200)
pyb.repl_uart(uart)
內容解密:
pyb.UART('XA', 115200):設定 UART 通訊埠 ‘XA’,波特率為 115200。pyb.repl_uart(uart):將 REPL 輸出重定向至指定的 UART。
字型設定與文字輸出
LCD160CR 提供了多種字型和文字輸出的控制方法。可以使用 set_font 方法來改變字型大小和樣式。
lcd.set_font(3, scale=0, bold=1, trans=0, scroll=1)
lcd.write("Hello, World!")
內容解密:
lcd.set_font(3, scale=0, bold=1, trans=0, scroll=1):設定字型為 3 號,縮放比例為 0,加粗效果為 1,背景透明度為 0,並啟用平滑滾動效果。lcd.write("Hello, World!"):在 LCD 上輸出 “Hello, World!"。
文字顏色與背景顏色設定
可以透過 set_text_color 方法來改變文字和背景的顏色。
text_colour = lcd.rgb(255, 128, 0)
background = lcd.rgb(0, 128, 255)
lcd.set_text_color(text_colour, background)
lcd.write("Hello, World!")
內容解密:
lcd.rgb(255, 128, 0)和lcd.rgb(0, 128, 255):分別生成文字顏色和背景顏色的 RGB 值。lcd.set_text_color(text_colour, background):設定文字和背景的顏色。
圖形輸出與基本繪圖
LCD160CR 不僅支援文字輸出,也提供了基本的圖形繪製功能,如設定畫素、繪製矩形和線條。
lcd.set_pixel(x, y, colour)
lcd.rect(20, 20, 40, 40)
內容解密:
lcd.set_pixel(x, y, colour):在座標 (x, y) 處設定畫素的顏色。lcd.rect(20, 20, 40, 40):繪製一個矩形,其左上角座標為 (20, 20),寬度和高度均為 40。
簡易 Mondrian 風格繪圖範例
下面是一個簡單的範例,展示如何使用 LCD160CR 繪製 Mondrian 風格的圖案。
import lcd160cr
from random import randint, choice, uniform
# 省略部分程式碼...
class Node:
# 省略部分程式碼...
def draw(self, x, y, w, h):
# 省略部分程式碼...
內容解密:
- 使用遞迴的方式繪製 Mondrian 風格的圖案。
Node類別代表圖案中的一個節點,具有顏色、深度和子節點等屬性。
輸入與感測:裝置互動的核心
在裝置與使用者互動的過程中,輸入與感測扮演著至關重要的角色。不同於傳統的計算裝置,如鍵盤、滑鼠或觸控螢幕,嵌入式裝置通常需要透過其他方式與使用者進行互動。MicroPython 為這些裝置提供了豐富的輸入與感測功能,使得裝置能夠對外部環境變化做出反應。
按鈕與電容式觸控
按鈕是最常見的輸入裝置之一。不同裝置具有不同數量的按鈕,有些裝置甚至支援電容式觸控功能。以 micro:bit 為例,其具有兩個按鈕(A 和 B),分別對應 button_a 和 button_b 物件。這些按鈕物件具有相同的方法,使得開發者能夠輕鬆地處理按鈕事件。
事件迴圈與暫停
在處理輸入事件時,事件迴圈(event loop)是至關重要的。事件迴圈是一種不斷迴圈的程式碼,用於等待和處理輸入事件。然而,由於事件迴圈的執行速度遠快於人類的反應速度,因此需要加入暫停機制,以避免多次觸發同一事件。
from microbit import *
position = 2
while True: # 事件迴圈
sleep(60) # 暫停
if button_a.is_pressed():
display.clear()
position = max(0, position - 1)
elif button_b.is_pressed():
display.clear()
position = min(4, position + 1)
display.set_pixel(position, 2, 9)
程式碼解析
while True:建立一個無限迴圈,作為事件迴圈的主體。sleep(60):在每次迴圈中暫停 60 毫秒,降低迴圈的執行頻率,以適應人類的反應速度。if button_a.is_pressed():和elif button_b.is_pressed()::檢查按鈕 A 和 B 是否被按下,並根據按下的按鈕調整position的值。display.set_pixel(position, 2, 9):在指定的位置顯示一個畫素點。
為何需要暫停?
如果沒有 sleep(60) 這行程式碼,事件迴圈將會以極快的速度執行。這意味著在你按下按鈕的短暫時間內,事件迴圈已經執行了多次,從而導致 position 的值被多次修改,最終可能只能將畫素點移動到最左邊或最右邊的位置。加入暫停後,事件迴圈的執行速度變慢,能夠正確地捕捉到每次按鈕按下事件。