自作キーボードでMCP23017というIOエキスパンダ(IO拡張モジュール)を使用しようとしたところ、沼ったので、その経緯とかなんかを書いておきます。
最終的な目標
最終的な目標は自作キーボードのメイン基板に搭載したPro Microから、サブ基板に搭載したMCP23017を制御することです。
ところが、さくっとQMKのI2Cドライバでアクセスしようとしたら、まったくMCP23017が動かず、困りました。
そのため、まずは確実に動くことを確認しようとするところから、この話は始まります。
問題:MCP23017がI2Cのスキャナに認識されていないようである
最初にブレッドボード上に回路を作成後、ArduinoのI2CScannerをPro Microに書き込み、I2CスレーブデバイスとしてMCP23017が検出されるか確認しました。
https://playground.arduino.cc/Main/I2cScanner/
結果、検出されませんでした。
回路は以下の様になっています。
SCLとSDAのプルアップ抵抗は1kΩを用いました。
実物の写真は以下です。
SDAとSCL、GND、VCCはメイン基板のOLED搭載用の端子と接続しています。
色々とググった結果、回路はこれでよさそうですが、どうにもスキャナに検出されず、頭を悩ませました。
OLEDをつないでみる
問題の切り分けのため、MCP23017の代わりに自作キーボード向けのOLEDを接続しました。
結果、スレーブアドレス0x3Cとして検出されました。
どうやら、基板上に引っ張り出しているSCL、SDA、GND、VCCは問題なさそうです。
Discordのフォーラムで助けを求める
回路とにらめっこし、何度確認しても間違いが見つからないため、サリチル酸さんのDiscordで助けを求めました。
状況を説明し、コメントを募ると2件の指摘をいただきました。
1.SCLとSDAのプルアップ抵抗が1kΩでは小さすぎるのではないか
1kΩにしていた理由は、ネットの誰かがやっていたからでしたが、さらに調べてみると、この手の回路では4.7kΩあたりが定番のようです。
そこで、プルアップ抵抗を4.7kΩに差し替えました。
結果、状況は変わりませんでした。
RESET端子をつながないとどうなるか
MCP23017を使用した例を探してくださった方の指摘でRESET端子はつないでいない例もあるとのことだったので、RESET端子を外してみました。
結果、状況は変わりませんでした。
確信したこと
ご指摘2件からもわかるとおり、致命的に回路を間違えている(ピンが間違っている)ということはないらしいと確信します。
では、なぜ動かないのか。
さらに問題を調査するため、続いてオシロスコープで波形を見たいと思いはじめました。
オシロスコープを買う
筆者はオシロスコープを持っていないどころか、今までオシロスコープを買おうと思ったこともないヒトでした。
ですが、確実に問題を切り分けるために、オシロスコープの購入を決心しました。
ググった感じ、オシロスコープでI2Cの波形を見るにはデコード機能付きが簡単で良いようです。
またI2C通信レベルだと、それほど高機能なものも求められていないようでした。
色々と調べた結果、購入したのはRIGOL社のDS1102Z-Eです。
https://jpmall.rigol.com/item.html?item_id=828
やりたいことはできそうで、思ったよりも安い、かつ、即納というのが決め手でした。
オシロスコープを使う
迅速に届いたオシロスコープを見様見真似、マニュアルを見ながら使ってみます。
まずは校正信号を見て、オシロ自体は初期不良はなさそう、正常に動いているようだと見当をつけました。
続いて、目的のSCLとSDAのうち、SCLを見てみます。
うねうねしていて、どう見てもクロックではありません。
ここで、なんで?とだいぶ頭を悩ませました。
筆者の想像では、AUTO機能を用いれば、SCLもSDAも簡単に波形を見られる公算でした。
オシロのコンセントのアースをつないでいないことが原因だろうか、それとも本当にこんな波形しか出ていないのだろうか。
でもそれにしては、OLEDをつないだときも同じような波形しか出ず、I2C通信が成立しているようには見えません。
だいぶ悩んだ後、原因はわかりました。
I2Cスキャナに入っているディレイです。
スキャナには5秒というディレイが入っていて、どうやら筆者はディレイ中の波形を見ているようでした。
と言うわけで、上で示したArduinoのI2Cスキャナのコードからディレイを削除。
すると、以下の様な波形が見え始めました。
これがほしかったんだよーと、ここで小躍りします。
それでは、肝心のMCP23017をつないだらどう見えるか確認します。
以下のようになりました。
見ると、スレーブアドレス、R/Wフラグに続く9番目のクロックの時、SDAがNACK応答(High)を返しているようです。
確かに、検出されないという状況と合致します。
どうもSCLとSDAの信号は問題なさそうです。
じゃあ、なんだろう?
ここでまたしばらく悩みます。
ブレッドボードを変える
現在テストするにあたって、ブレッドボード上にMCP23017向けの回路を構築しています。
ただ、なんか、ジャンパワイヤがスカスカする場所があることが気にかかっていました。
これはもしや……。
ということで、ブレッドボードを変えてみます。
(ELEGOO社のArduino互換スターターキットに付属したものを用いました)
すると、なんということでしょう。
I2Cスキャナがスレーブアドレス0x20を検出したのです。
ここでまた、小躍りしました。
さらにオシロも当ててみます。
新しく組んだ回路上にはSCLとSDAにプルアップ抵抗を入れていないため、波形がだいぶ丸いですが、見ると、9クロック目でSDAがLowになっています。
つまり、ACK応答があったのです。
これで、MCP23017をPro Microから動かすことができました。
スレーブデバイスとして検出されるようになったら、こっちのものです。
プルアップ抵抗をつける
では、ということでSCLとSDAにプルアップ抵抗を設けます。
すると、以下の様に綺麗な波形に生まれ変わりました。
これなら、安心してQMKのI2Cドライバを試せます。
QMKのI2Cドライバからのアクセス
QMKに搭載されているI2Cドライバの関数i2c_writeRegを一発やってみます。
すると、関数の戻り値が0、つまり、I2C_STATUS_SUCCESSとなりました。
これで、やりたいことのとっかかりは無事固まりました。
まとめ
というわけで、以上がIOエキスパンダMCP23017をPro Microで動かすのに苦労した経緯です。
本当のところ、最初に使っていたブレッドボード自体に問題があるのか、それとも筆者のジャンパワイヤの接続が甘かったのかは定かではありません。
でも、今回の経験で、確実にデバッグしていく方法を経験することができました。
やはり、デバッグ時は、確実につぶせるものからつぶしていくのがよいなと思います。
今回はオシロを用いて波形をみたことで、そこは問題がないと確信することができました。
結果、ブレッドボード上の回路の接続を疑うことができたのです。
さて、これでやりたいことが完成――ではありませんが、ひとしきり自分を褒めて、自己肯定感を高めた後、本番の作業に移ります。
この長い記事を読んだ皆さんは、ブレッドボード上の回路不良を問題の原因として疑うようにしておきましょう。
それでは、これで終わります。
以上、この記事が誰かの役に立ちますように。