M5Stackは筐体の側面に各種端子が出ています。結構な数があるようでいて、それぞれの用途を活かして使おうと考えると「単なるGPIO」の数がちょっと足らない感じがしないでもない。そこで今回はIO ExpanderをM5Stackに接続してみました。1チップの接続でなんと16本のGPIO増。最大8チップで128本MAX。
※「MicroPython的午睡」投稿順 Indexはこちら
※M5Stack Grayに書き込んだUIFlow2.0 (Alpha-27)対応のMicroPython処理系とWindowsパソコン上で動作しているThonny 4.0.1で動作確認しています。
MCP23017 IOExpander
マイクロチップ社 MCP23017の製品ページが以下に。
I2Cバスに接続するIO Expanderです。I2Cバス接続なので実質このチップのために1ピンもつぶすことなくGPIO端子を拡張することが可能です(割り込み使いたいときは要るけど。)I2Cアドレス的には0x20から0x27の8個のアドレスにチップを接続可能(アドレスは配線による)なので、最大8個、128本までのGPIO端子まで拡張可能です。入出力の設定はI2C経由で個別端子毎にプログラマブル。I2Cバスの速度の制約をうけますが、単純なIOを追加したいときには非常に使いやすいデバイスじゃないかと思います。またI2Cバスインタフェースなので、ちょっとした回路を工夫すればホストと異なる電源を使うようにすることも可能。なかなかお役立ち。
今回、M5Stackに接続した実験回路は以下のごとし。実験のため、本体の3.3V電源直結で使っています。
なおこのチップについては、以下の別シリーズにて調べてます。
部品屋根性(32) マイクロチップ MCP23017、IO Expander
今回実験のMicroPythonスクリプト
さて、このチップをMicroPythonで制御することは、以前にラズパイPico上のMicroPythonでやってみています。
MicroPython的午睡(35) ラズパイPico、MCP23017でIO端子数拡張
ラズパイPicoのMicroPythonでやれているので、後はピン設定とか「コマケー話」をちょっとM5Stackに合わせてやれば、即動作するハズ。今回の実験用のスクリプトの動作は以下の通り。
-
- 接続するMCP23017は1チップのみ。I2Cアドレスは0x20番地
- まず接続確認を行い、接続がavailableであったら、MCP23017の全端子(ポートAとポートB各8ビット)を出力設定とする
- 3秒おきに端子にハイとローを出力。その際、隣り合う端子の出力は必ずハイとローが異なるパターンとする。
# testMCP23017.py from machine import I2C, Pin import M5 import time IOEX0 = 0x20 IOCONA = 0x0A IOCONB = 0x0B IODIRA = 0x00 IODIRB = 0x01 GPIOA = 0x12 GPIOB = 0x13 OLATA = 0x14 OLATB = 0x15 device = IOEX0 i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000) def isIOEXavailable(): global i2c lis = i2c.scan() if IOEX0 in lis: return True return False def readByte(i2cADR, regADR): global i2c bufW = bytes([regADR]) ackW = i2c.writeto(i2cADR, bufW) bufR = bytearray(1) ackR = i2c.readfrom_into(i2cADR, bufR) return int.from_bytes(bufR, 'little') def writeByte(i2cADR, regADR, dat): global i2c bufW = bytes([regADR, dat]) ackW = i2c.writeto(i2cADR, bufW) return ackW def initDevice(): global device writeByte(device, IOCONA, 0x20) writeByte(device, IODIRA, 0x00) writeByte(device, IODIRB, 0x00) writeByte(device, OLATA, 0xFF) writeByte(device, OLATB, 0xFF) def main(): global i2c, device M5.begin() print("M5Stack Gray, MCP23017 IO Expander OUTPUT test") print("IO Expander is ", end="") if not isIOEXavailable(): print("not available.") else: print("available.") initDevice() while True: writeByte(device, OLATB, 0xAA) writeByte(device, OLATA, 0xAA) time.sleep(3) writeByte(device, OLATB, 0x55) writeByte(device, OLATA, 0x55) time.sleep(3) if __name__ == "__main__": main()
実機実行結果
16本も出力端子があるのに、端っこのポートAの7番と6番のみLEDに接続して点滅を見ています。交互に点滅しておるよ。
端子はゴッソリ増やすことができるようになったので、その先に接続するものが楽しみだな。