Pro MicroでI2Cを動かす (2) - I2Cで接続
お知らせ: この記事の内容を大幅に加筆修正してまとめた書籍ができました。まとまった情報が欲しい場合はぜひ確認してみてください。
シリーズ2つ目のこの記事では、I2Cの基礎とPro Microでの利用を見ていきます。
I2Cの基礎
本当はI²C(アイスクエアドシー)ですが、面倒なのでI2Cと呼ばれています。
クロック信号(SCL)とデータ信号(SDA)の2本を使い、各ICでそれぞれ接続するだけで通信ができます。拡張性の必要なシステムに良さそうな規格です。互換性のある上位版のI3Cもあるらしいです。
引用: https://www.rohm.co.jp/electronics-basics/micon/mi_what7
繋がれたデバイスを操作するICをマスター、繋がれた機器たちをスレーブと呼び、1:多で処理するのが一般的です。
規格の詳細はこちら: https://www.nxp.com/docs/ja/user-guide/UM10204.pdf
通信速度と規格
通信速度は繋がっているデバイスたちがどのI2C規格に対応しているか、および回路の設計に依存します。
引用: https://en.wikipedia.org/wiki/I²C
I2C規格の中でも、規格によってはだいぶ別物になります。通信速度が遅いと制約が緩いですが、徐々に厳しくなっていき、Ultra-fast modeに至っては単方向通信になります。
Pro Micro (ATmega32U4) はFast modeの400kbit/sや1Mbit/sに対応しているように見えます(要出典)。自作キーボード用途ではおそらく400kbit/sあれば何とかなると思われるので、ここからは制約も緩いFast modeでの対応を考えていきます。
接続方法
SCL, SDAをそれぞれ繋ぐだけで通信ができます。デイジーチェーン、つまり1つのICからさらにケーブルを伸ばして別のICに繋ぐということも可能です。ここで重要なのが、適切な大きさのプルアップ抵抗を挟む必要があるということです。
Fast modeでは、立ち上がり時間(lowからhighに変化する時間)は300ns
が最大となっています(参考)。これを満たすように抵抗を置くのですが、計算が中々大変です。要は大きすぎてもだめ。小さすぎてもだめ。しかもケーブル、デバイスに依存します。最大静電容量は400pF
ですが、これは大体3-4mくらいの(一般的な)ケーブルに相当しそうです(参考)。難しいので計算サイトを使いました。便利。
I2Cバスプルアップ抵抗の計算 keisan.casio.jp
試しに計算すると、下図のようになります。大きめの350pFを見積もるとだいぶギリギリで、1kΩがピッタリだと分かります。長いケーブルを想定している場合、1kΩを置いておくと良さそうです。消費電力は増えるので、短い場合は大きな抵抗で良いです(要計算)。
https://keisan.casio.jp/exec/user/1649986426
通信方法
マスターからアドレスを指定して送受信します。そのため、事前にスレーブ機器のアドレスを知っておく必要があります。繋がっている機器のアドレスをスキャンするプログラムも書けるので、初期化タイミングでいい感じに処理するのが良さそうです。プログラム作成の時点で詳しく見ていきます。
規格上、アドレスは7bit使えます。そのため理論上は2^7=128機器に対応しています。が、色々な方法で制限されたり増やしたりされます。これも後述します。
今回使うI2Cモジュール
世の中には色々なI2C対応モジュールがありますが、今回はピンを増やしてくれるIOエキスパンダーに活躍してもらいます。
IOエキスパンダーは、IOピンを拡張するためのICです。Pro Microは18個ほど汎用ピンを持っていますが、もっとたくさん欲しい時にもってこいです。
今回使用するのはMCP23017(秋月で190円)で16bit(16ピン)増やせます。ただし、アドレスは3ビットしか設定できず、上位4bitは固定されています(0x20-0x27)。そのため普通に繋ぐと8個が頭打ちになります。
MCP23017はI/Oピンに内部プルアップ抵抗を使うことができます。自分で用意しなくて良いので楽ですが、100kΩと弱いので自分で付けるケースも多いようです。
用意するパーツ
ここからはブレッドボード上で実際に動かしてみましょう。まず1つ繋いで動くか見てみましょう。動作確認には、適当なピンにスイッチを繋いで、押して反応するかを見ることとします。
今回は1kΩの抵抗でプルアップしたI2C通信をして、MCP23017が動作するかを確認します。
第1回で使用したパーツは、既に持っているものとします。一応後述して必要なパーツを概観できるようにします。
- MCP23017 x1
- 1kΩの抵抗 x2
- ブレッドボード(BB-801など)x1
- ブレッドボードを分けたい場合。1つで収まる場合はそれでも良い
第一回で使ったもの
- ブレッドボード(BB-801など)x1
- Pro Micro + ピンヘッダ x1
- リセット用スイッチ x1
- ジャンパーワイヤ x沢山
- Pro MicroとPCを繋ぐケーブル
配線
何度も見ることになるPro Microのピンアサインを確認して、SCL/SDAをチェックします。
引用: https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/ProMicro16MHzv1.pdf
MCP23017のデータシートも見つつ、どのピンにどれを挿すかを決めます。SCLとSDAの位置を間違えがちなので注意します。他にはMCP23017のGPB0(1ピン)にテスト用スイッチを繋げ、VCCとGNDを繋げ、#RSTにVCCを繋ぐなどの定型作業をしたら完了です。今回、アドレスはすべてlowにし、0x20
にします。
実績: I2Cデバイスを一つ繋いだ
データシートの詳細は次回の記事で見ていきます。
プログラム作成(I2C Scanner編)
I2Cを使う場合、セットアップ時点でどの機器が繋がっているかを確認し、それに対して処理を行います。
まずは、簡単に接続ができているかどうかだけ確認してみましょう。このような時に便利な I2C Scanner というプログラムがあります。コピペして実行してみましょう。
Arduino Playground - I2cScanner playground.arduino.cc
上手くいくと、次のような表示がSerial Monitorに出てきます。アドレスの配線をパチパチ変えて、表示が変わるかも確認してみましょう。
I2C Scanner
Scanning...
I2C device found at address 0x20 !
done
デバイスをちゃんと認識しない場合は、#RESETとアドレスx3がちゃんと配線されているかを疑いましょう。
また、I2C Scannerは今後デバッグに頻繁に使うので、メモしておくと良いでしょう。
まとめ
ちょっと複雑になりましたが、SDAとSCLの2本を繋ぐだけで色々なデバイスと通信ができるのは非常に便利ですね。
次回は、繋いだデバイスの入力を受け取ってみましょう。