
皆さんこんにちは!メカ旦那です。
電子工作やマイコンでよく聞く「I2C(アイツーシー)」。
シリアル通信の一種で、少ない配線で多数のデバイスと通信できるため、様々なセンサに利用されている規格です。
奥が深いですが、イラストを用いてわかりやすく解説します!
伝送方式
種類
通信方式は多種多様に存在し、色々な区分け方がありますが、データの伝送方式に着目すると、以下に分ける事ができます。

I2C(アイツーシー)は「デジタル、シリアル、クロック同期、半二重、シングルエンド、主従関係あり、1対多」の特徴をもつ通信です。
よくわかりませんね、、、一つずつ解説します!
アナログ / デジタル

アナログは連続的な値を取りますが、デジタルは0と1の2値を用います。電話やラジオはアナログ通信が多いですが、PC、マイコン通信だとデジタルが主流となり、I2Cもデジタルになります。
パラレル / シリアル

デジタルは0か1を多数のbitで送受信しますが、パラレルは複数の信号線でまとめて通信します。対して、シリアルは1本の信号線を用いて通信します。その為、配線数が少なくて済むのが特長です。例としてパラレルはプリンター、シリアルはマウスやキーボードで利用されています。
一見、パラレル通信の方が一度に多くのデータを送信でき効率的に思えますが、配線が長くなると、各信号の時間ズレが発生し、上手く送受信できないことがあります。その為、最近の高速通信ではシリアルが主流になっています。I2Cもシリアル通信です。
クロック同期 / 非同期

デバイス間で送受信する際、いつ送るのか、いつ受け取るのか、といったタイミング(クロック)を両者で認識する必要があります。クロックが両者で共有されている状態での通信はクロック同期と呼ばれています。対して、共有はされていませんが、各々独自のクロックを持って通信することを非同期(調歩同期)と言います。イメージは、クロック同期が同じ壁掛け時計を見ながら通信、非同期はそれぞれの腕時計を見ながら通信、ですかね。
同期通信はクロック専用の信号線がいるため、その分配線が多くなりますが、クロックが共有されているため、送受信にズレが生じないです。そのため、安定した高速通信が可能となります。I2Cは同期通信になります。
全二重 / 半二重

データを送受信する際、2本の伝送路で別々に行う方式を全二重通信(フルデュプレックス)と呼びます。対して、1本でまとめて行う方式を半二重通信(ハーフデュプレックス)と言います。全二重は送受信を同時に行うことができるのに対し、半二重は同時に行えません。ただし信号線が1本で済むのがメリットです。I2Cは半二重になります。
シングルエンド / 差動

先ほどデジタル通信で「0と1の2値を用いる」と説明しましたが、何を0とするのか、1とするのかの基準があります。信号電圧が、ある基準電圧より低い状態を0、高い状態を1とする方式をシングルエンド(不平衡)と呼びます。対して、信号が2つあり、電圧の差分から0,1を判別する方式を差動(平衡)と言います。
シングルエンドは信号線が1本で済むメリットがありますが、ノイズが入った時に0を1(もしくはその逆)と誤認識してしまう恐れがあります。対して差動信号は信号線は2本いるものの、電圧差を見ている関係上、ノイズによる影響が少ないメリットがあります。I2Cはシングルエンドになります。
主従関係
シリアル通信は半二重のように1本の伝送路を複数の機器で共有することがあり、「どこがいつ何のデータを送るのか」を決めないとデータ衝突(同時送信)が発生します。このルールは主従関係と呼ばれており、優先権を持つデバイス(主)をマスター、それに応じるデバイス(従)をスレーブと呼びます。具体的には、
- マスターが通信の開始・クロック・アドレス指定を実施
- スレーブは命令を受けて応答
します。ちなみにマスター/スレーブ は「主人/奴隷」という意味で、アメリカの奴隷制度を連想させる為、最近では以下の呼び方をされる事もあります。
I2Cは主従関係があるため、マスター/スレーブとなるデバイスを決める必要があります。
リレーション

通信方式によって送受信できるデバイス数をリレーションと言います。
- ユニキャスト:1対1
- マルチキャスト:1対多(複数)
- ブロードキャスト:1対多(全数)
- マルチマスター:多対多
I2Cはマルチキャストになります。
配線

なるほど、伝送方式の特徴はなんとなくわかったよ。で、使うにはどうやって配線すればいいの?

そうですね、実際の配線イメージと注意点について解説します。

配線図はこちらです。 ポイントは「信号線はSCL,SDAの2本、バス接続、プルアップ抵抗をつける、GNDを合わせる、配線長は短く」です。
SCL, SDA

信号線はSCL(Serial Clock)、SDA(Serial Data)の2本を使います。 SCLはマスターからスレーブへクロックを送る線、SDAはお互いにデータを送り合う線になります。
バス接続

前述の通りI2Cは半二重の為、1つのマスターに対して複数のスレーブを繋ぐ場合、信号線の共用化、いわゆるバス接続が可能です。 例えばUART(全二重)はスレーブ毎に通信ポートや配線を増やさないといけないですが、I2Cはバス接続により最小限に抑える事が可能です。またスレーブの設置場所によって、電線の分岐点を変えることができ、柔軟な配線が可能です。
プルアップ抵抗

一般的にマイコンやICから信号出力する際、プッシュプル、オープンドレイン(コレクタ)の2種類があります。I2Cはオープンドレインになります。つまり、0は出力できても1はできません。1を出力するには、プルアップ抵抗を接続する必要があります。
抵抗値としては4.7〜10 kΩが一般的です。ただし接続するモジュールやセンサには最初からプルアップ抵抗が実装されていることがあります。 また、Arduino Unoなどのマイコンでは関数を使う事で内部プルアップを有効にできる場合があります。 それらの抵抗値が4.7〜10 kΩの場合、外付けは不要です(抵抗値がこれより低かったり高かったりすると通信が不安定になる可能性がある為、その場合は外付けした方が無難です。)。プルアップについては、下記で具体例を用いて詳しく解説していますのでご参考にしてください。
ちなみに、I2Cとよく比較されるSPI、UARTはプッシュプルの為、プルアップ抵抗が不要になります。
GNDを合わせる
前述の通り、シングルエンドは信号電圧によって0、1が決まります。ここで重要なのが、接続される全デバイスのGND電位を合わせる事です。 電位が合ってない場合、例えばマスターから0を送っても、スレーブでは不安定領域の電圧で1と誤認識されることがあります。 その為それぞれで電源が異なるなどGND電位が合っていない場合、必ずGND間を配線するようにしてください。

長配線には弱い
I2Cは短距離通信を目的に設計されているため、配線が長くなるほど通信が不安定になります。更に、通信速度(クロックの速度)が速いほど不安定となります。イメージは以下になりますが、できるだけ配線は短く、通信速度は最小限を心がけてください。
| 通信速度 | 最大配線長(目安) |
|---|---|
| 100kHz(標準) | 約0.5~1m |
| 400kHz | 約0.3~0.5m |
| 1MHz | 数十cm |
もし長くしたい場合は、I2Cリピータを配線間に接続したり、シールドケーブルを使うのがオススメです。このリピータですと、Texas Instrumentsのデータシート上では最大50 m まで可能と記載されています。
接触不良にも弱い
これはブログ主の経験則になりますが、上記の長距離配線&リピータありでI2C通信を行った所、通信が頻繁に途絶えるという事がありました。色々調べたところ、ブレッドボードやジャンパーワイヤー接続部分の接触不良が原因と判明しました。その為ユニバーサル基板、コネクタをはんだづけして接触不良を極力なくした所、問題は解決しました。
普通のIO通信ですと、多少接触が悪くても動作が止まることは少ないですが、I2Cは高速で連続的なビットが送受信される為、1ビットでもおかしくなるとデータ全体が破損し、結果通信が途絶える事があります。
もし接触不良が疑われる場合、ユニバーサル基板でのはんだづけや、コネクタを利用するなど接触不良を極力少なくすることを心がけてみてください!
マイコンのI2C端子
先ほどの配線について、ハード側に機能が無いとそもそも使う事ができません。そこで、よく使われるマイコン/コンピュータのI2C用端子について解説します。
Arduino Uno

Arduino UnoはD18にSDAが、19にSCLが割り当てられています。左右に端子がありますが、内部で配線が繋がっており、系統が独立しているわけではありません。
I2Cは前述の通りプルアップ抵抗が必要になりますが、D18,19は初期状態でハイインピーダンスの為、別途プルアップ抵抗を外付けする必要があります。もしくはソフト的に内部プルアップ機能を有効にする事もできます。内部プルアップはこちらで解説しています。
Raspberry Pi A+, B+, 2, 3, 4, 5

一般的なラズパイ(Raspberry Pi A+, B+, 2, 3, 4, 5)はGPIO2にSDA、3にSCLが割り当てられています。この2つは最初からプルアップの状態となっているため、別途抵抗を外付けする必要はありません。
Raspberry Pi Pico 1, 2, W

ラズパイピコは他のマイコンと比較し、多数の端子にI2Cが割り当てられいます。
更にI2C0,1の2つの独立した系統があるため、2つのI2Cバスを形成する事ができます。
I2Cは前述の通りプルアップ抵抗が必要になりますが、全端子初期状態でハイインピーダンスの為、別途プルアップ抵抗を外付けする必要があります。もしくはソフト的に内部プルアップ機能を有効にする事もできます。内部プルアップはこちらで解説しています。
通信手順

SCLはクロックだからマスターからスレーブへ一定のパルスを送るんだろうけど、SDAって何のデータを送ってるの?

SCLはその通りです!SDAは送信方向別に解説します!
マスターからスレーブへ

マスターからスレーブへデータを送る場合、以下の順序になります。
スレーブからマスターへ

逆にスレーブからマスターへデータを送る場合、以下の順序になります。
(先ほどとの違いを太字にしています。)
ライブラリ
通信手順は以上となりますが、ライブラリ(smbus2、Wire.hなど)を用いることで、簡単に構築する事ができます。 実際に構築してみたので、気になる方は下記をご覧ください。
UART、SPI、I2Cの違い
マイコンによく付いているシリアル端子として、UART、SPI、I2Cがあります。どれもマイコン⇔センサ間にはよく用いられる規格ですが、違いについて表にまとめてみました。
| 項目 | UART | SPI | I2C |
|---|---|---|---|
| クロック同期/非同期 | 非同期 | 同期 | 同期 |
| 全二重/半二重 | 全二重 | 全二重 | 半二重 |
| リレーション | 1対1 | 1対多 | 1対多 |
| 配線本数 (GNDは含めない) | 2~4本 (Tx,Rx,RTS,CTS) | 3本+スレーブ数分のCS (SCLK, MOSI, MISO, CS) | 2本 (SCL, SDA) |
| 通信相手の特定 | 不要 | CSで特定 | スレーブアドレスで特定 |
| 通信速度 [bps] | 中速 (9.6k~1M) | 高速 (1M〜10M) | 中速 (100k〜3.4M) |
| IO出力 | プッシュプル | プッシュプル | オープンドレイン |
| 端子接続 | クロス | ストレート | ストレート |
| プルアップ抵抗 | 不要 | 不要 | 必要 |
| 長距離配線 | 強い (~数百m) | 弱い (~1m) | 弱い (~0.5m) |
| 1フレーム長さの基準 | 設定 (データビット数) | クロック停止 | プロトコルで規定 (8bit+ACK/NACK) |

なるほど、全然違いますね。でも結局どの場面でどれを使えばいいんですかね?。。。

基本的には接続するセンサ・モジュールがどれか1つに対応しているのでそれを使えばよいです。ただこれらの規格はマイコン通信でよく出てくるが故に混同しやすいので、違いを知っておくことで配線ミスや通信不具合を防ぐことができます!SPI、UARTはこちらでも詳しく解説していますので、ぜひご覧ください!
まとめ
I2Cの特徴をまとめると、以下になります。
省配線で複数デバイスと通信できるため、様々なセンサで利用されています。

とりあえず読んではみたけど、、、やっぱり手を動かさないとイメージできないな、、、

実際にI2Cを使った電子工作をしてみたので、ぜひチャレンジしてみてください!
また他のシリアル通信についても解説しているのでぜひご覧ください!







コメント