GoにいればGoに従え(7) TinyGoのmicro:bit向けI2C関数の挙動を観察

Joseph Halfmoon

今回からBBC micro:bitのI2CをTinyGoから操作してみたいと思います。しかしmachineモジュールの説明を読んでムムム。I2Cなんですが2個ありますな。過去、MakeCode、Mbed OS、MicroPythonなどでもmicro:bit使ってますがそんな選択迫られたことなかったデス。どっち?

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

参考文献

今回も以下の御本を参考にさせていただいております。

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

上記の御本はSeeed社のWio Terminalをターゲットなので、BBC micro:bit に適用する場合は以下のページを参照してコンスタント名など読み替える必要があります。

Machine package / microbit

今回は上記のmachineモジュールのドキュメントのI2C部分を読んで、頭に浮かんだ疑問を解消すべく、micro:bitからI2C信号線を引き出して観察してみた回です。バスを外に引き出して観察しているだけで何もデバイスは接続してないです。接続はまた次回ということで。

また、BBC micro:bitのI2Cバスの負荷容量とか、オンボードのI2Cデバイスのアドレスなどテクニカルな情報については以下のページを参照する必要があるかと思います。

I2C information for shared bus

ブレークアウトボード

BBC micro:bit のカードエッジからI2C信号を引き出す場合は、BBC micro:bit用に複数種類のブレークアウト・ボードが販売されているのでそれらを使うのが確実です。今回使用したものは以前以下の別シリーズ記事で取り上げさせていただいたものです。なお、I2C端子については要対応の小ネタがあるのでご参照くだされ。

部品屋根性(51) Kitronik、micro:bit用Breakout Board

なお、メーカページは以下です。micro:bitの本場?英国製。

Kitronik Edge Connector Breakout Board for the BBC micro:bit

TinyGoのBBC micro:bitのI2C関数への疑問点

さて、ドキュメントを読んだのだけれどわからなかった疑問点は以下の2つです。

    1. I2Cバス用に2つのペリフェラルが定義(unsafeポインタで)されているけれど、どっちを使ったらよいの?
    2. I2Cの制御用の関数がいくつか定義されており、それらはエラーを返せるようになっているけれど、途中でACKが返ってこない場合はその時点で転送は中断されるの?

多分、「ドッチでもよい」「その場で中断」なのだけれど、いざ周辺デバイス向けにソフトを書いているときに当てが外れるとシンドイので現物で確かめることにいたしました。泥縄式現物主義?

引き出したI2Cバス信号

引き出して観察した信号は以下のとおりです。

    1. P19、SCL
    2. P20、SDA

MakeCode、Mbed OS、MicroPython環境に共通してI2Cバス端子として扱われている micro:bit のカードエッジ端子です。なお、内部のI2Cバスデバイスも存在するのでプルアップされている筈と予想できるのですが、今回は念のため外部でも10kΩでプルアップしてます。

今回実験のmainプログラム

「疑問の解消」のためだけのプログラムなので、ごくごく簡単です。ただし、I2Cドッチ問題?の確認のため、2個のI2Cをコメントアウトで切り替えるようにしてあります。I2C0ならばI2Cのアドレス0x33、I2C1ならば0x5Aに書き込むので、外部でバスを観察していれば動いているペリフェラルが確認できるという目論見です。

package main

import (
    "machine"
    "time"
)

func main() {
    i2c := machine.I2C0
    //i2c := machine.I2C1
    i2c.Configure(machine.I2CConfig{
        Frequency: machine.TWI_FREQ_100KHZ,
        SCL:       machine.SCL_PIN,
        SDA:       machine.SDA_PIN,
    })
    for {
        i2c.WriteRegister(0x33, 0x55, []byte("abc"))
        //i2c.WriteRegister(0x5A, 0x55, []byte("abc"))
        time.Sleep(100 * time.Millisecond)
    }
}
実験結果

黄色C1がSCL、青色C2がSDAです。以下はI2C0でアドレス0x33への書き込みの様子。I2C0_waveform

今度はI2C1でアドレス0x5Aへの書き込みの様子。ハードの接続などは上記とまったく同じです。I2C1_waveform

上記から

    • I2C0でもI2C1でもどっちゃでもバスは動く。
    • 最初のフレームを送ったところで反応するデバイスが何もないのでACKが返らず、そこで転送は中断されている。

予想どおりと。だったら、さっさと何か周辺デバイスを接続してみんかい。

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

GoにいればGoに従え(8) TinyGoでmicro:bitにAQM1602をI2C接続 へ進む