在前面的章節中我們介紹了許多的micro:bit的練習,如何運用在練習中建立的實例運用到實際的場域中呢?這次博雅教育中心的成果展裡面所展示的燈籠牆是其中的一個例子。先來看看照片:
從照片中同學們應該可以看得出來,在這面牆上共有7串燈籠,每一燈籠串共有10個燈籠,在這個例子中每一串我們只使用了中間的8個燈籠,也就是每一串都有8個燈籠是可以由我們來分別控制它們的明滅動作的。
在組裝之前是這個樣子的:
以及這個樣子:
由於每一串均需使用一個控制器,因此7串燈籠共使用了7個控制器,而由於每一個燈籠中使用的是12V的高亮度LED,這顆LED所供應的電流並不是micro:bit所能提供的,因此要控制這些燈的開關,就是繼電器控制模組派上用場的時候了。
每一個單獨的控制器如下所示:
在上面的控制器裡面使用了一個八路繼電器模組,每一個繼電器可以控制1個燈的明滅運用。這支影片示範的是讓八路繼電器模組可以使用2進位的方式從00000000計算到11111111,同學們有看出來嗎?
在燈籠牆的例子中使用的就是這樣控制模組,但是,如何才能控制這7個模組的運作呢?答案是透過micro:bit的無線電功能。
在每一個模組中,它都會一直不斷地偵測無線電訊號,如果一收到從無線電來的訊息之後,立刻剖析收到的字串,依照字串的內容來呈現出對應的燈號,其程式碼如下所示:
from microbit import *import radioUNIT_NO = 3relay = [pin0, pin1, pin2, pin3, pin4, pin6, pin7, pin8]display.show(UNIT_NO)sleep(2000)display.off()for r in relay:if UNIT_NO == 3:r.write_digital(0)else:r.write_digital(1)radio.on()while True:incoming = radio.receive()while incoming is None:incoming = radio.receive()if len(incoming) > 4:command, unit_no, digit = incoming.split(",")if int(unit_no) == UNIT_NO:if command == "go":for r in relay:r.write_digital(0)bits = [0, 0, 0, 0, 0, 0, 0, 0]count = 0digit = int(digit)while digit > 1:bits[count] = digit % 2count += 1digit = digit // 2bits[count] = digitfor i, r in enumerate(reversed(bits)):if UNIT_NO == 3:relay[i].write_digital(1-r)else:relay[i].write_digital(r)
上述的程式中,UNIT_NO代表的就是第幾串燈籠串,當收到屬於自己這串命令的時候,會把收到的命令剖析出來,每一個數字(放在digit變數中)先把它轉換成整數,之後把它從10進位轉換成2進位,再依序依照該位元是0或是1把訊號送給繼電器模組,以決定開關是打開還是關閉,也就是可以直接以數字的方式控制燈的明滅。以下是原始設計文字元的紙張:
在7串燈籠的控制器都燒錄了之後,接下來就可以透過控制器去傳送要呈現的資訊給每一個燈籠串,其中一個範例如下:
from microbit import *import radiobitmaps = {'?': [0, 64, 128, 138, 144, 96, 0],'!': [0, 0, 0, 251, 0, 0, 0],'l': [56, 124, 252, 63, 252, 124, 56],'A': [7, 56, 72, 136, 72, 56, 7],'B': [255, 255, 145, 145, 145, 105, 14],'C': [60,66,129,129,129,129,70],'D': [255,129,129,129,129,66,60],'E': [255,137,137,137,137,137,137],'F': [255,136,136,136,136,128,128],'G': [60,66,129,137,137,138,79],'H': [255,255,24,24,24,255,255],'I': [129,129,129,255,129,129,129],'J': [132,130,129,255,128,128,128],'K': [0,255,8,24,36,66,129],'L': [255,1,1,1,1,7,0],'M': [255,192,112,53,112,192,255],'N': [255,192,32,16,8,7,255],'O': [60,66,129,129,129,66,60],'P': [0,0,255,136,136,112,0],'Q': [62,66,129,137,70,62,1],'R': [127,200,136,136,140,114,1],'S':[0,2,98,146,146,140,128],'T':[128,128,128,255,128,128,128],'U':[252,2,1,1,1,2,252],'V':[224,56,14,3,14,56,224],'W':[124,2,3,124,3,2,124],'X':[193,66,36,24,24,36,199],'Y':[192,32,16,15,16,32,192],'Z':[195,131,133,137,145,161,199],'9':[0,114,137,137,137,126,0],'8':[0,110,145,145,145,110,0],'7':[0,224,128,143,144,224,0],'6':[0,126,137,145,145,78,0],'5':[0,0,243,145,145,142,0],'4':[0,24,40,72,255,8,0],'3':[0,66,129,145,145,110,0],'2':[0,97,131,133,137,113,0],'1':[0,33,65,255,1,0,0],'0':[0,126,129,129,129,126,0],' ':[0, 0, 0, 0, 0, 0, 0],'a':[255, 255, 255, 255, 255, 255, 255]}radio.on()RADIO_DELAY = 100def ani_banner(banner, d):for char in banner:lines = bitmaps[char]for i, line in enumerate(lines, 1):radio.send("go,{},{}".format(i, line))sleep(RADIO_DELAY)sleep(d)def ani_banner_shift(banner, d):all_chars = [0, 0, 0, 0, 0, 0]for char in banner:all_chars += bitmaps[char]all_chars += [0, 0, 0, 0, 0, 0, 0]for i in range(len(all_chars)-7):for j in range(i, i+7):radio.send("go,{},{}".format(j-i+1, all_chars[j]))sleep(RADIO_DELAY)sleep(d)banners = ['lNKUST']while True:if button_a.was_pressed():while True:display.show(Image.HAPPY)# ani_banner_shift("N K U S T ", 50)# sleep(2000)for banner in banners:ani_banner(banner, 1000)sleep(2000)else:display.show(Image.HEART)