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)