GoにいればGoに従え(5) micro:bitのA, Bキーを割り込み受けね。

Joseph Halfmoon

前回はTinyGoでも使えるgoroutineを使ってmicro:bit(v1.5)のLED点灯ルーチンを並行処理化。メインループでは点灯処理のことを「忘れておける」ようになりました。今回はmicro:bitの表面にある2つのキーを割り込みで処理してみます。Aキーを押されたらバッテン、Bキーを押されたらマルを表示っと。

※「GoにいればGoに従え」Go関連記事の総Index

参考文献

今回も最近頼り切りの以下の御本を参考に、前回のTinyGoプログラムを 改変してみたの回です。

高砂様著、「TinyGoの組み込み開発」

上記の御本は、Seeed社のWio Terminalをターゲットに書かれています。デバイス毎の違いは、TinyGoのmachineパッケージの中に押し込められているので、BBC micro:bit に適用する場合は、TinyGoの御本家の以下のページを参照すれば、どのようにしたらよいか分かるかと。VScode使ってソースを書いている場合は自動でコンテキストに沿った候補が出てくるので見る必要さえないかもですが。

Machine package / microbit

今回実験のソース

キー割り込みを設定して、割り込みハンドラを定義する今回のキモの部分は以下のようです。

keyA := machine.BUTTONA
keyB := machine.BUTTONB
keyA.Configure(machine.PinConfig{Mode: machine.PinInput})
keyB.Configure(machine.PinConfig{Mode: machine.PinInput})
keyA.SetInterrupt(machine.PinFalling, func(machine.Pin) {
    pat = 1
})
keyB.SetInterrupt(machine.PinFalling, func(machine.Pin) {
    pat = 2
})

micro:bit用のmachineモジュール内で micro:bitの表面?のAと書かれているボタンはBUTTONA、BはBUTTONBというお名前で定義してくれています。それらキーを入力(machine.PinInput)に設定した後、それらピンのフォーリング・エッジで引数内で記述が完結している小さい「割り込みハンドラのユーザ処理関数(コールバック)」を呼び出すように設定してます。

こうしておけば、実際にキーがおされて入力端子がハイからロウへ遷移すると、真の割り込みハンドラが起動し、その中で先ほど設定した「ユーザ処理関数」を呼び出してくれる筈。ソフト的にはなにも切っ掛けを作る必要がないのでお楽。

全体のコードが以下に。

package main

import (
    "machine"
    "time"
)

func main() {
    InitLED()
    var dispPattern [4]uint32
    dispPattern[0] = 0x00000000
    dispPattern[1] = 0x01151151
    dispPattern[2] = 0x00E8C62E
    dispPattern[3] = 0x01FFFFFF
    var pat = 0
    var row = 1

    keyA := machine.BUTTONA
    keyB := machine.BUTTONB
    keyA.Configure(machine.PinConfig{Mode: machine.PinInput})
    keyB.Configure(machine.PinConfig{Mode: machine.PinInput})
    keyA.SetInterrupt(machine.PinFalling, func(machine.Pin) {
        pat = 1
    })
    keyB.SetInterrupt(machine.PinFalling, func(machine.Pin) {
        pat = 2
    })

    go func() {
        for {
            switch row {
            case 1:
                DispLED1(dispPattern[pat])
            case 2:
                DispLED2(dispPattern[pat])
            case 3:
                DispLED3(dispPattern[pat])
            }
            row++
            if row > 3 {
                row = 1
            }
            time.Sleep(time.Millisecond * 10)
        }
    }()

    for {
        if pat != 0 {
            pat = 0
        }
        time.Sleep(time.Second * 5)
    }
}

なお、上記のmain.goファイルと同じフォルダに、前回作成したLEDのダイナミック駆動用の関数群を収めた mbdisp.go ファイルを置いておく必要があります、念のため。

ビルドして実行

ビルドしてフラッシュ書き込みは、BBC micro:bit (V1.5)をUSBポートに接続後、以下一行でOKの筈。

$ tinygo flash -target=microbit

点灯しているところは前回同様なので写真は掲げませぬが、

Aボタンを押すとバッテン点灯

Bボタンを押すとマル点灯

上記とは無関係なタイミングで「回っている」メインループ内で5秒に一度消灯しています。よって、点灯時間は最大5秒、最小?秒とな。

GoにいればGoに従え(4) micro:bitのLED、goroutineで動的駆動じゃ へ戻る

GoにいればGoに従え(6) BBC micro:bit (v1.5)で超簡単、温度計よ へ進む