micro:bit一對多控制
上週做了一個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 = 0
let myBits: string[] = []
let myStep = 0
let selectedBit = 0
let selectedIcon = 0
input.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 = 0
myStep = 1
selectedBit = -1
selectedIcon = -1
被控端程式:
let myIndex = 0
radio.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 = -1
radio.sendValue("" + control.deviceSerialNumber(), myIndex)