MicroPython操作每一顆LED

在前面的單元中說明的是在LED矩陣上顯示文字以及圖案,在這一單元中我們就來以單一顆LED為單位來操作個別LED的顯示與不顯示,讓LED的應用變得更加地多元和有趣。

輪流點亮每一顆LED

micro:bit除了可以利用show和scroll來操作LED矩陣之外,每一個LED也都有自己的x, y座標,透過這些x, y座標即可獨立地操作每一顆LED的亮度,而操作這些個別的LED的指令是set_pixel函數。請練習以下的程式:

from microbit import *
for x in range(5):
for y in range(5):
display.set_pixel(x, y, 9)
sleep(200)

在上面的程式中會從左上角的LED開始,由上而下,由左而右依序點亮每一顆LED,直到點亮全部的LED為止。請再練習以下的程式,比較看看和上一個程式執行結果有何不同:

from microbit import *
for y in range(5):
for x in range(5):
display.set_pixel(x, y, 9)
sleep(200)

仔細觀察上面兩個程式的差異,相信同學們對於LED矩陣的x, y座標就能夠有更加清楚的理解了。那麼,接下來,如果我們不想要填滿整個LED矩陣,而只是想讓那個LED在畫面上移動呢?答案是只要適時地加入display.clear()指令清除畫面即可,程式如下:

from microbit import *
while True:
for x in range(5):
for y in range(5):
display.clear()
display.set_pixel(x, y, 9)
sleep(200)

為每一顆LED編個別的號碼

如果不使用display.clear()的話,為了清除上一個LED,需要使用另外一個變數來記錄上一個LED的位置,為了避免記錄2個數字,我們只使用1個數字來代替每一個LED,實際要顯示時再進行數字的轉換:

from microbit import *
counter, old = 0, 0
while True:
x = old % 5
y = old // 5
display.set_pixel(x, y, 0)
x = counter % 5
y = counter // 5
display.set_pixel(x, y, 9)
sleep(200)
old = counter
counter = counter + 1
if counter > 24:
counter = 0

程式的邏輯是這樣的,把LED矩陣的最左上角那顆LED編號為0,它的右邊的編號是1,再來是2,也就是第一列(其實是第0列)的LED分別是0到4,第二列(其實在內部是第1列)為5到9,依此類推。原有以x, y座標編號的LED如下圖所示:

我們以單一數字來編號的情形是以下這樣的:

對照兩者之間的差異,意思是在程式內部編號4的那顆LED實際要顯示的時候其座標是(4, 0),編號5的那顆座標是(1,1),編號24的那顆是(4, 4),依此類推。假設要顯示編號是n的LED,則(x, y)座標轉換的公式如下:

x=n%5y=n//5x = n \% 5 \\ y = n // 5

其中%是取餘數,而//則是取整數的意思。瞭解了上述的原理,相信同學們應該就可以理解上述程式的邏輯了。我們設定了2個變數分別是counter和old,一開始兩個變數都設為0(第2行),每一次要顯示新的LED之前要先把舊的LED關閉(第6行),在顯示了新的LED之後,就把新的LED編號記在old變數之中(第12行),之後再新增counter的內容(第13行)。

不過每一次在顯示LED的時候都要進行一次轉換(第4行到第5行以及第8行和第9行),比較方便的方法是設計一個副程式來專心做這件事,方法如下:

from microbit import *
def setLED(number, value):
x = number % 5
y = number // 5
display.set_pixel(x, y, value)
counter, old = 0, 0
while True:
setLED(old, 0)
setLED(counter, 9)
sleep(200)
old = counter
counter = counter + 1
if counter > 24:
counter = 0

雖然程式的行數看起來差不多,但是有了這個副程式setLED(number, value),在主程式的邏輯就會更容易理解。有了這個編號的方式,就可以使用程式讓LED依自訂的順序點亮,例如要倒過來點亮(移動)也只要做些小改變就好了:

from microbit import *
def setLED(number, value):
x = number % 5
y = number // 5
display.set_pixel(x, y, value)
counter, old = 24, 24
while True:
setLED(old, 0)
setLED(counter, 9)
sleep(200)
old = counter
counter = counter - 1
if counter < 0:
counter = 24

電 子輪盤

以下是電子輪盤的程式碼:

from microbit import *
def setLED(number, value):
x = number % 5
y = number // 5
display.set_pixel(x, y, value)
seq = [0, 1, 2, 3, 4, 9, 14, 19, 24, 23, 22, 21, 20, 15, 10, 5]
counter, old = 0, 0
while True:
setLED(seq[old], 0)
setLED(seq[counter], 9)
sleep(100)
old = counter
counter = counter + 1
if counter >= len(seq):
counter = 0

以下是正轉加上反轉的程式範例,不同於上面程式,這次我們利用for迴圈的方式來解決這個問題:

from microbit import *
def setLED(number, value):
x = number % 5
y = number // 5
display.set_pixel(x, y, value)
seq = [0, 1, 2, 3, 4, 9, 14, 19, 24, 23, 22, 21, 20, 15, 10, 5]
old = seq[0]
while True:
for counter in seq:
setLED(old, 0)
setLED(counter, 9)
sleep(100)
old = counter
for counter in reversed(seq):
setLED(old, 0)
setLED(counter, 9)
sleep(100)
old = counter

其實上面這個程式的兩個內迴圈的內容幾乎是一樣的,但是old和counter這兩個變數所代表的意義是不一樣的,同學們可以看得出來嗎?

透過以上的顯示能力,接下來就可以搭配按鈕玩電子輪盤的遊戲了。