AT SAMの部屋(7) XiaoでもGo!TinyGoでポーリング、結果はChannelへ

Joseph Halfmoon

前回端子からの割り込みやってしまいました。普通は先にポーリングだったかなあ、ということで今回は端子のポーリングしてみます。ポーリングはGoroutineにお任せして、結果はchannelで受け取ると。ついでに無関係なLEDもチカチカさせたりして並行に処理している雰囲気をだすってもんかと。ありがち?

※実験は、MicroChip社のATSAMD21マイコン搭載のSeeduino XiaoボードにWindowsPC上でTinyGoが生成したオブジェクトを書き込んで行っています。多分、端子名を変えたソースは他の多くのマイコンで走るんじゃないかと思います。知らんけど。

ポーリング

ソフトウエアループの中で端子などを読み取って処理すべきイベントを検出するポーリングはよく使われるのではないかと思います。しかし、検出待ちループなどではイベント到来まで他の処理が止まるし、他の処理を進めながらにしたい場合は、無関係な処理の中で時々ポーリング関数を呼び出したりと直接的な割には問題も大有りです。

その点、Go言語にはGoroutineあり、疑似的とは言え並行に処理を進められます。ポーリング「待ち」の関数は「待って」いても、他の処理は粛々と進められます。ホントか?

今回は、以下のような設定設定です。

  • 端子D1に接続してあるタクトスイッチ(プルアップ抵抗付いており、スイッチOFF状態でHighが読める。スイッチONするとLow)のHighからLowへの遷移(ネガティブエッジ)をポーリングで捉えてイベントを発生する。ポーリングの周期はほぼ100m秒毎。前回がHighでその100m秒後にポーリングしたときにLowであったらmain()に知らせる
  • main()関数は上記のイベントをGo言語のGoroutine間の通信構造であるchannelを通じて受信する。受信したら青色LEDを1回2秒点灯。
  • 上記のポーリング動作と無関係に仕事ができることを赤色LEDのLチカ(毎秒周期)で示す
Channel

GoのChannelは、他のRTOSなどではQueueとかFIFOあるいは EVENT と呼ばれるような構造に似た制御構造じゃないかとおもいます。見やすいのでお世話になっている Go by Exampleのページが以下に。

Go by Example: Channels

実験に使用したソースコード

例によって前回のチョイ変に次ぐチョイ変。大して変わっておりませぬ。今回は、main()関数と pollingD1()関数の間にChannelを設置し、bool値、trueがpollingD1()関数からmain()関数に到来したら青色LEDを1回点灯の段取りです。

package main

import (
    "machine"
    "time"
)

func pollingD1(d1Chan chan bool) {
    oldValue := true
    newValue := true
    pinD1 := machine.D1
    pinD1.Configure(machine.PinConfig{Mode: machine.PinInput})
    for {
        time.Sleep(time.Millisecond * 100)
        newValue = pinD1.Get()
        if oldValue && (!newValue) {
            d1Chan <- true
        }
        oldValue = newValue
    }
}

func redLED() {
    ledRED := machine.D2
    ledRED.Configure(machine.PinConfig{Mode: machine.PinOutput})
    for {
        time.Sleep(time.Millisecond * 500)
        ledRED.High()
        time.Sleep(time.Millisecond * 500)
        ledRED.Low()
    }
}

func main() {
    ledBLUE := machine.D3
    ledBLUE.Configure(machine.PinConfig{Mode: machine.PinOutput})
    ledBLUE.High()
    d1Chan := make(chan bool)
    go pollingD1(d1Chan)
    go redLED()
    for {
        <-d1Chan
        ledBLUE.Low()
        time.Sleep(time.Millisecond * 2000)
        ledBLUE.High()
    }
}
実験結果

オブジェクトをXiaoに書き込めば、赤色LEDがLチカ始めます。そしてタクトスイッチ(テスト回路図は前回をご参照ください)を押すと青色LEDが2秒ほど点灯します。まあいい加減でやっつけだけれど、channelが動いていることは確かめられた?

AT SAMの部屋(6) XiaoでもGo! TinyGoでタクトスイッチからの割り込み受け へ戻る

AT SAMの部屋(8) XiaoでもGo!TinyGoでSPI、27LC512接続 へ進む