上週做了一個micro:bit報數的小程式,幫每個micro:bit利用它出廠時的deviceSerialNumber來定址,今天,以這個定址程式為基礎,實作了以一個micro:bit控制多個micro:bit的小程式,這個小程式可選擇要控制哪些micro:bit,並且選擇這些micro:bit的LED要出現什麼圖案。
找一個micro:bit當做控制器,其他的micro:bit開機後會向控制器取得一個流水號當做自己的編號,主控端的micro:bit可利用A鍵或B鍵選擇要控制哪個號碼,也可以在號碼出現時搖一下,將該號碼儲存進一個陣列,被選擇到的號碼便可以被主控端一起控制,決定好號碼後同時按A+B鍵。接下來再按A鍵或B鍵可選擇受控的micro:bit要出現什麼LED圖案,選擇好後一樣按A+B鍵,便可以將圖案送到受控端的micro:bit。
這個範例只是展示一對多控制micro:bit的LED,當然,若要控制其他的動作也是可以的,例如伺服馬達或是一整群的機器人大軍..........。詳細的操作方式請看底下的影片:
靠A鍵及B鍵,可選擇要控制的micro:bit編號及圖案
可控制所有的micro:bit同時出現某個圖案
可在makecode輕鬆以積木程式編輯程式
可控制所有的micro:bit同時出現某個圖案
也可以控制個別的micro:bit出現不同的圖案
也可以在makecode上以文字語法編寫程式(我比較喜歡這樣)
控制方法:
1.先將主控端的micro:bit先開啟,被控端的micro:bit依序開起,被控端會向主控端取得流水編號,並顯示在自己的LED上。
2.主控端按A或B鍵,會顯示號碼,出現該號碼表示該號碼的micro:bit可被控制,若想控制多個,則在顯示該號碼時用力搖動,則該號碼會被記錄下來,以便可以被控制。選好後,同時按A+B鍵,則表示選號確定,這時LED上會顯示打勾,表示選號選好了。
3.接著主控端按A或B鍵則會顯示要傳送的圖案,選好後同時按A+B鍵,則表示選好圖案確定,這時LED上會顯示打勾,受控端的micro:bit便會出現圖案。
程式碼:
以下為主控端及被控端的程式,可將程式碼貼上makecode的javascript頁面上,可以直接轉成積木式的語法結構
主控端程式:
let bitsTemp: number[] = []let countBits = 0let myBits: string[] = []let myStep = 0let selectedBit = 0let selectedIcon = 0input.onButtonPressed(Button.B, () => { if (myStep == 1) { selectedBit += 1 if (selectedBit > countBits - 1) { selectedBit = countBits - 1 } if (selectedBit == -1) { basic.showString("A") } else { basic.showNumber(selectedBit) } } if (myStep == 2) { selectedIcon += 1 if (selectedIcon > 39) { selectedIcon = 39 } basic.showIcon(selectedIcon) }})radio.onDataPacketReceived(({ receivedString: receivedName, receivedNumber: receivedValue }) => { if (receivedValue == -1) { myBits.push(receivedName) radio.sendValue(receivedName, countBits) countBits += 1 basic.showNumber(countBits) }})input.onButtonPressed(Button.A, () => { if (myStep == 1) { selectedBit += -1 if (selectedBit < -1) { selectedBit = -1 } if (selectedBit == -1) { basic.showString("A") } else { basic.showNumber(selectedBit) } } if (myStep == 2) { selectedIcon += -1 if (selectedIcon < -1) { selectedIcon = -1 } if (selectedIcon == -1) { basic.showString("C") } else { basic.showIcon(selectedIcon) } }})input.onButtonPressed(Button.AB, () => { if (myStep == 1) { basic.showIcon(IconNames.Yes) basic.clearScreen() } if (myStep == 2) { basic.clearScreen() if (bitsTemp.length > 0) { for (let index = 0; index < bitsTemp.length; index++) { radio.sendValue("" + bitsTemp[index], selectedIcon) } } else if (selectedBit == -1) { radio.sendValue("all", selectedIcon) } else { radio.sendValue("" + selectedBit, selectedIcon) } basic.showString("send") } myStep += 1 if (myStep == 3) { myStep = 1 bitsTemp = [] }})input.onGesture(Gesture.Shake, () => { if (myStep == 1 && selectedBit != -1) { bitsTemp.push(selectedBit) basic.showIcon(IconNames.Happy) }})radio.setGroup(1)myBits = []bitsTemp = []countBits = 0myStep = 1selectedBit = -1selectedIcon = -1被控端程式:
let myIndex = 0radio.onDataPacketReceived( ({ receivedString: receivedName, receivedNumber: receivedValue }) => { if (receivedName == "" + control.deviceSerialNumber()) { myIndex = receivedValue basic.showNumber(myIndex) } if (receivedName == "" + myIndex) { if (receivedValue == -1) { basic.clearScreen() } else { basic.showIcon(receivedValue) } } if (receivedName == "all") { if (receivedValue == -1) { basic.clearScreen() } else { basic.showIcon(receivedValue) } }})basic.showString("?")radio.setGroup(1)myIndex = -1radio.sendValue("" + control.deviceSerialNumber(), myIndex)