ブロックをつみながら(29) BBC micro:bit、EEPROMをI2C接続

Joseph Halfmoon

前回はライトオンリのLCDモジュールをmicro:bitのI2Cに接続してみました。今回はリードとライト両方あるものということでEEPROM、24LC64を接続してみました。micro:bitから読み書きはできたのですが、MakeCodeエディタのI2C書き込み用のブロック、使いずらいデス。なんとかならないものか。

※「ブロックを積みながら」投稿順 index はこちら

今回も micro:bit v1.5 を使用していますが v2 でも同様に動作するのではないかと思います。接続するのはシリアルEEPROM(E2PROM)といわれるカテゴリのメモリです。読み書き可能で、電源切っても記憶が飛ばないメモリ。フラッシュメモリのような大容量ではないけれど、その代わり書き換え可能回数と記憶の保持時間ではフラッシュを圧倒する性能の一品であります。実際に接続してみましたのはMicrochip社の 24LC64というもの。64Kbit(8Kバイト)の製品です。既に以下の投稿でRaspberry Pi Picoには接続してみたことがあります。

MicroPython的午睡(17) ラズパイPico、I2CシリアルEEPROM接続

ハードウエアの接続は簡単

以下にmicro:bitと24LC64の接続図を示します。電源、グランド、SCL、SDAの4本を接続するだけなので簡単です(SCL、SDAにはプルアップ抵抗いれてありますが。)mbg_24LC64Schematic

MakeCodeエディタでの「コーディング」に戸惑う

BBC micro:bitの主力開発環境であります MakeCodeエディタでは、Advancedカテゴリの下に Pins という項目があり、さらにその下に more というサブ項目があって、その中にI2Cバス制御用のブロックが提供されています。read用とwrite用に一つずつです。

24LC64用の書き込み/読み出し関数を作ろうとしてハタと手が止まりました。

  1. 24LC64はI2Cバスの7ビットアドレス 0x50~0x57に配置可能。今回下3ビットはオール0にしたので0x50を指定する。
  2. I2Cバスのアドレスに続く2バイトで24LC64内のメモリアドレス13ビット(上位3ビットは無視のはずだが、とりあえず0詰めとして16ビットのビッグエンディアンで送る)を指定。
  3. それに続けてメモリに書き込むデータのバイト列(最大32バイトまで)を書き込む

問題は、3のところです。MakeCodeエディタの以下のブロックの説明を読むと、引数にとれるのは、I2Cバスのアドレスとそれに引き続いて送信される1個のデータだけです。

i2c Write Number

1個のデータといっても、8ビット、16ビット、32ビット、64ビット幅の値を引数にとれ、かつ符号なし、ビッグ/リトルの選択が可能です。前回LCDモジュールを接続したときは、コマンドバイトとデータバイトの合計2バイトのデータを送信する必要があったので、16ビット幅の引数の上位にコマンドバイト、下位にデータバイトを乗せて対応しました。

しかし、今回、24LC64の最小読み書き単位であるバイト(8ビット)で書き込もうとすると メモリアドレス2バイト+データ1バイトで3バイト(24ビット)を送信せねばなりません。ちょうど良い入れ物がないです。

困りました。しかし、良い方法を思いつかなかったので

書き込み単位は16ビット

としてしまいました。これであればメモリ2バイト、データ2バイトで32ビットの「箱」に収まるためです。カッコ悪いな~、なんとかならないのか?

読み出しはバイト単位でも可能であったのですが、書き込みにあわせてこちらも16ビット単位にしました。

実際に使用した関数ブロックがこちら。

なお、MakeCodeエディタは、16進で 0x50 と入力することはできるのですが、何かのきっかけで十進変換をしてくれるので80となってしまいます。

また、メモリアドレス16ビットとデータ16ビットを合わせて32ビット値にするために、アドレスを左シフトしてデータとORとっています。しかしMakeCodeエディタにはビット演算などは用意されていません。掛け算と足し算で書いても良いのですが、好みとしてビット演算で書きたいです。そこで JavaScript(実際にはTypeScript)モードに切り替えて、ビット演算子で書き、ブロックモードに戻ると、書き込み関数の中の灰色のブロックのような記述となります。

上記の関数を呼び出すテスト用のメイン部分は以下です。開始時に 24LC64のメモリアドレス0x100番地(十進で256番地)に0x1234(十進で4660)を書き込みます。その後、メモリアドレス256番地を読み出して4660であれば、マトリックスLEDに丸(四角?)を表示し、値が期待値と異なればバツ印を表示します(書き込みの後に少しお休み時間を入れた方が良いかも。下のコードでは抜けています。)

MakeCode_24LC64test

実動作

アイキャッチ画像に掲げたとおり、LEDマトリックスに丸が表示されました。そのときの24LC64の読み出し波形が下に。前半でメモリアドレスを設定し、後半でデータ2バイトを読み出し。黄色がSCL、青がSDAです。

mbg_24LC64readWaveFormオシロの波形から目視で通信を解読することも可能ですが、しんどいです。Digilent Analog Discovery2のロジアナ機能に解読してもらった方が簡単、確実。こんな感じ。

mbg_24LC64readLogi前半で、I2Cアドレス0x50にメモリアドレス 0x01_00 を書き込み。続いて後半で、I2Cアドレス0x50から0x12_34を読みだしています(読み出しは、直前で書き込まれたメモリアドレス位置から行われるため、メモリアドレスの指定はい不要。)

まあね、読み書きできているけれど、バイト・ライト出来ないのはカッコが悪いなあ、何か気づいていない良い方法があるのかなあ。。。

ブロックを積みながら(28) BBC micro:bit、外付けLCDをI2C接続 へ戻る

ブロックを積みながら(30) BBC micro:bit、512K SRAMをSPI接続 に進む