I2C通信の仕様-Arduinoで波形を解析する

Arduinoと部品のI2C通信データ Arduino
スポンサーリンク

I2C通信は、マイコンと周辺部品の通信でよく使われるシリアル通信です。
ここでは、ArduinoのI2C通信波形を実際に確認しながら、I2C通信の仕様についてまとめていきたいと思います。

こんな人にオススメ

I2C通信について具体的なイメージを持っていない

Arduinoにいろんな部品を接続してみたい

準備するもの

この記事では、以下の物を使います。

●Arduino Uno

amazonのスイッチサイエンスから購入する純正のArduinoは、永久保証を受けることができます。
ブレッドボードや電子部品が付いてくるので、すぐに工作を始めることができます。

●LCDディスプレイ

16文字×2行を表示することができるLCDディスプレイです。
本来LCDディスプレイはパラレル信号を入力しないといけませんが、この商品はパラレル通信⇔I2C通信を変換してくれる回路が元から付いているので、I2C通信によるやりとりが可能です。

●CO2センサー

I2C通信で接続することができるCO2センサーです。
精度はそれほど信用できるものではありませんが、手軽にArduinoでCO2を計測することができます。

詳細な使い方は以下の公式HPで紹介されています。
https://wiki.keyestudio.com/KS0457_keyestudio_CCS811_Carbon_Dioxide_Air_Quality_Sensor

●ジャンパーワイヤー

LCDディスプレイやセンサーは端子がオスになっているので、各種ワイヤーを揃えておくと便利です。

●ロジックアナライザ

このロジックアナライザを使用すれば、UART、IIC、SPIなどのシリアル通信のデータを見ることができます。

●解析ソフト pluseview

上記のロジックアナライザのデータを見るために、pluseviewというフリーソフトを使用します。
以下のサイト様でインストール方法から使用方法まで詳細に説明されているので、参考にしてください。

データベースエラー

I2C通信とは

I2C通信は組み込み機器のマイコンと、センサやLCDなどを接続するとき等によく使われるシリアル通信です。

2本の通信線で同時に複数の部品と通信するので、通信線が少なく省スペースにすることができますが、通信速度はそれほど早くありません。

I2C通信のシステム構成図

使用するスケッチ

ArduinoでCO2センサーから取得したデータを、LCDに表示するスケッチを使用します。
CO2センサーとLCDはI2C通信でArduinoと通信します。

詳細は以下の記事でご紹介しています。

ArduinoでCO2センサーの値をLCDに表示する
Arduinoを使って、CO2センサーから取った数値をLCDに表示するプログラムを作りたいと思います。 CO2センサーとLCD(液晶ディスプレイ)はI2C通信で接続をします。I2C通信はマイコンに対して複数の機器を同時に接続できる利点があり...

ソースコードで重要な箇所を抜粋します。

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27,16,2);

// CCS811 sensor(&Wire, /*IIC_ADDRESS=*/0x5A);
CCS811 sensor;

まず、LCDとCO2センサーのアドレスを設定しています。
I2C通信を使う部品は、それぞれ自分のアドレスを持っています。
あらかじめLCDとCO2センサーのアドレスを調べて、そのアドレスを指定してやる必要があります。

今回使用する部品のアドレスは以下の通りです。

部品アドレス
LCD0x27
CO2センサー0x5A
 if(sensor.checkDataReady() == true){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("CO2: ");
    lcd.print(sensor.getCO2PPM());
    lcd.print("ppm");
    lcd.setCursor(0,1);
    lcd.print("TVOC: ");
    lcd.print(sensor.getTVOCPPB());
    lcd.print("ppb");
  }

CO2センサーの準備ができていたら、CO2センサーからデータを取得してLCDに表示するスケッチです。

I2C通信の仕様

上記のスケッチを実際に動かして取得したI2Cの通信データを見てみましょう。
以下がその通信データです。

Arduinoと部品のI2C通信データ

ArduinoがSCLの線に流すクロックのタイミングに合わせて、SDLの線でデータをやり取りします。
今回使っている部品のアドレス「0x27」「0x5A」のうち、通信したい方のアドレスを指定して、データをやり取りしているのがわかります。

通信シーケンス

通信するときのシーケンスは以下の通りです。

チェック
  1. マスターからスタートコンディションを送る
  2. マスターから7bitのアドレスと、1ビットの「書き込み(0)」か「読み込み(1)」を送る
  3. 自分のアドレスを指定されたスレーブから、マスターに受信完了のAckを返す
  4. 「書き込み(0)」の場合、マスターからスレーブへデータを送る
    「読み込み(1)」の場合、スレーブからマスターへデータを送る
  5. データを受け取った方は、受信完了のAckを返す
  6. マスターからストップコンディションを送る

順番にI2Cの仕様を見ていきたいと思います。

電圧

最大の電圧は5Vで、よく使われる電圧は3.3Vです。

SCL(クロック)

シリアル通信には、信号を正しいタイミングで読み取るための方式として、同期式と調歩同期式の2方式があります。
I2Cは同期式です。

チェック
  • 同期式
    信号線にマイコンからクロック信号も一緒に送り、そのクロック信号のタイミングに合わせて通信データを読み取ることで正しくデータを送受信することができます。
  • 調歩同期式
    あらかじめ、お互いでデータを読み取るタイミングを決めておき、そのタイミングに合わせて通信データを読み取ることで正しくデータを送受信することができます。

マスターとなるマイコンからクロック信号をSCLに流して、そのクロック信号に合わせて通信データをやり取りします。

通信データの確認
I2C通信のクロック信号

SCLに規則正しいクロック信号が流れているのが分かります。
クロック信号がHighになる(立ち上がり)ときにSDAがHigh(1)かLow(0)かを判断すればいいわけです。

余談

I2Cは「SCL」と「SDA」の通信線2本でデータをやり取りしますが、片方の「SCL」はクロックを流す専用の線なので、肝心の通信データは「SDA」1本でやり取りすることになります。

なので、常にマスターであるArduinoからスレーブである周辺部品に指示を出して、通信データの書き込み / 読み込みをしています。

このような方式を半二重通信といいます。
反対に、UARTのような通信データ用に2本の線があり、お互いの好きなタイミングで通信データをやり取りできる方式を全二十通信といいます。

スタートコンディション・ストップコンディション

SDAで通信データをやり取りするときに、どこからがデータかを判別するための仕組みが「スタートコンディション」と「ストップコンディション」です。

チェック
  • スタートコンディション
    SCLがHighのときにSDAの立ち下がり(Low)を出力する
  • ストップコンディション
    SCLがHighのときにSDAの立ち上がり(High)を出力する

I2C通信は何もデータをやり取りしていないときは、Highの状態にプルアップされています。
この状態で通信データのHigh(1)が送られてくると、何も送られていないのか、High(1)が送られているのか区別がつきません。

そこで、必ず一番初めにスタートコンディションを送り、次から送られてきたデータから読み始めます。

また、上記のルールを守るためには、通信が終えたタイミングでSCLとSDAがHighになっている必要があります。
このため、通信が終われば必ず最後にストップコンディションを送ります。

通信データの確認
I2C通信のスタートコンディションとストップコンディション

確かに、ルールの通り通信が開始/終了しているのが分かります。

アドレス

2本の通信線だけで複数の部品と通信ができる仕組みを実現しているのがアドレスです。
各部品にはあらかじめアドレスが設定されているので、Arduinoは好きな宛先を指定して通信をすることができます。

チェック
  • アドレス
    各部品にあらかじめ設定された7bitのアドレス
通信データの確認
I2C通信のアドレス

今回使用しているLCDとCO2センサーのアドレスのうち通信したい方を指定して、そのあと通信データのやり取りがされています。

SDAの1本のみで、2つの部品と通信することができています。

書き込み(0) 読み込み(1)

7bitのアドレスの末尾が0か1かで、Arduinoが部品に対してデータを書き込むのか、Arduinoが部品からデータを読み込むのか、が変わります。

チェック
  • 書き込み : 0
  • 読み込み : 1
通信データの確認
I2C通信の書き込みと読み込みコマンド

7bitのアドレスの後ろに、Write(0)とRead(1)が付いているのが分かります。

Write(0)でまずArduinoからCO2センサーに対してこれから欲しいデータの指示を出して、Read(1)で指示したデータを取得しています。

CO2センサーはアドレスが「0x5A」なので、その後ろに0か1をつけた状態を16進数で表すと、書き込みのときは「B4」、読み込みのときは「B5」というデータをCO2センサに送ればいいことになります。

Ack・Nack

Arduinoも周辺部品も、何かのデータを正常に受信したときにはAckを、受信が失敗したときはNackを返します。

チェック
  • Ack
    正常に受信が完了したときに返す1bitのLow(0)
  • Nack
    受信に失敗したときに返す1bitのHigh(1)

この仕組みを使うことで、お互いに通信がうまくいっているのか確認しながらやり取りをすることができます。

通信データの確認
I2C通信のAck信号

まずはAckの例です。

ArduinoがCO2センサーに対して読み込みのコマンドを送った後に、信号がLowになりAckが帰ってきているのが分かります。

Arduinoは読み込みのコマンドを送ったら、信号をHigh(何も信号が流れていない状態)に戻しますが、すぐさまCO2センサーがLow(0)を出力することでAckとなります。

CO2センサーはArduinoからコマンドを受け取ったあと、かなりシビアな時間でAckを返すことが要求されますね。

I2C通信のNack信号

次にNackの例です。

ArduinoがCO2センサーからデータを受信したあとに、SDAがLow(0)にならずHigh(1)のままになっています。

通信に失敗したときや、そもそもアドレスが間違えたときなどは、このようにデータの後がHigh(1)のままとなり通信が失敗したことが分かります。

まとめ

ArduinoとLCD、CO2センサーがI2Cで通信するときの波形を参考に、I2C通信の仕様をご紹介しました。

I2Cは2本の通信線で複数の部品と通信するぶん、UARTなどに比べると少し複雑な通信の制御が必要になりますが、Arduinoではとても簡単に実現することができますね。

実際に波形を見ることでI2Cの理解もより深まると思いますので、ぜひ皆さんも一度波形を確認してみることをオススメします。

Arduino
スポンサーリンク
tsubablog

メーカーで組み込みプログラマーとして勤務しているサラリーマンです。
プログラミングの楽しさについて発信しています。

業務で扱っている言語はC、C++です。

tsubablogをフォローする
つばブログ

コメント

タイトルとURLをコピーしました