- I2C通信プロトコルとは何ですか?
- I2C通信はどのように機能しますか?
- I2C通信はどこで使用しますか?
- ArduinoのI2C
- 必要なコンポーネント
- 回路図
- 動作説明
- ArduinoでのI2Cプログラミング
- マスターArduinoプログラミングの説明
- スレーブArduinoプログラミングの説明
以前のチュートリアルでは、ArduinoでのSPI通信について学びました。今日は、別のシリアル通信プロトコルであるI2C(Inter Integrated Circuits)について学習します。I2CとSPIを比較すると、I2Cは2本のワイヤしかありませんが、SPIは4本を使用し、I2Cは複数のマスターとスレーブを持つことができますが、SPIは1つのマスターと複数のスレーブしか持つことができません。そのため、プロジェクトにはマスターである必要のあるマイクロコントローラーが複数あり、I2Cが使用されます。I2C通信は通常、ジャイロスコープ、加速度計、気圧センサー、LEDディスプレイなどとの通信に使用されます。
このArduinoI2Cチュートリアルでは、2つのarduinoボード間のI2C通信を使用し、ポテンショメータを使用して相互に(0〜127)値を送信します。値は、各Arduinoに接続された16x2LCDに表示されます。ここでは、1つのArduinoがマスターとして機能し、もう1つがスレーブとして機能します。それでは、I2C通信についての紹介から始めましょう。
I2C通信プロトコルとは何ですか?
用語IICは「の略インター集積回路」。通常、I2CまたはI squared Cとして、あるいは2線式インターフェースプロトコル(TWI)として示される場所もありますが、すべて同じ意味です。I2Cは同期通信プロトコルです。つまり、情報を共有する両方のデバイスが共通のクロック信号を共有する必要があります。情報を共有するためのワイヤーは2本だけで、そのうちの1つはコック信号に使用され、もう1つはデータの送受信に使用されます。
I2C通信はどのように機能しますか?
I2C通信は、フィリップスによって最初に導入されました。前に述べたように、2本のワイヤーがあり、これらの2本のワイヤーは2つのデバイス間で接続されます。ここでは 、一方のデバイスをマスター と呼び、もう一方のデバイスをスレーブと呼び ます。通信は、2つのマスターとスレーブの間で常に発生する必要があります 。I2C通信の利点は、複数のスレーブをマスターに接続できることです。
完全な通信は、これら2つのワイヤ、つまりシリアルクロック(SCL)とシリアルデータ(SDA)を介して行われます。
シリアルクロック(SCL): マスターによって生成されたクロック信号をスレーブと共有します
シリアルデータ(SDA): マスターとスレーブ間でデータを送受信します。
いつでもマスターだけが通信を開始できます。バスには複数のスレーブがあるため、マスターは異なるアドレスを使用して各スレーブを参照する必要があります。アドレス指定されると、その特定のアドレスを持つスレーブのみが情報を返信し、他のスレーブは終了し続けます。このようにして、同じバスを使用して複数のデバイスと通信できます。
I2Cの電圧レベルは事前定義されていません。I2C通信は柔軟です。つまり、5vボルトで給電されるデバイスは、I2Cに5vを使用でき、3.3vデバイスはI2C通信に3vを使用できます。しかし、異なる電圧で動作している2つのデバイスが、I2Cを使用して通信する必要がある場合はどうなるでしょうか。5V I2Cバスは、3.3Vのデバイスに接続することはできません。この場合、電圧シフターを使用して、2つのI2Cバス間の電圧レベルを一致させます。
トランザクションを構成する条件のセットがいくつかあります。送信の初期化は、SDAの立ち下がりエッジで始まります。これは、下の図で「START」条件として定義され、マスターがSDAをローに設定しながらSCLをハイのままにします。
下の上の図に示すように、
SDAの立ち下がりエッジは、START条件のハードウェアトリガーです。この後、同じバス上のすべてのデバイスがリスニングモードになります。
同様に、SDAの立ち上がりエッジは、上の図で「STOP」状態として示されている送信を停止します。この場合、マスターはSCLをHighのままにし、SDAを解放してHIGHにします。したがって、SDAの立ち上がりエッジで送信が停止します。
R / Wビットは次のバイトの送信方向を示します。HIGHの場合はスレーブが送信し、Lowの場合はマスターが送信します。
各ビットは各クロックサイクルで送信されるため、バイトの送信には8クロックサイクルかかります。各バイトが送信または受信された後、ACK / NACK(確認済み/未確認)に対して9番目のクロックサイクルが保持されます。このACKビットは、状況に応じてスレーブまたはマスターのいずれかによって生成されます。ACKビットの場合、SDAは9番目のクロックサイクルでマスターまたはスレーブによってローに設定されます。したがって、それはACKと見なされ、それ以外の場合はNACKと見なされます。
I2C通信はどこで使用しますか?
I2C通信は、短距離通信にのみ使用され ます。それはそれをスマートにするために同期されたクロックパルスを持っているので、それは確かにある程度信頼できます。このプロトコルは主に、マスターに情報を送信する必要があるセンサーまたはその他のデバイスと通信するために使用されます。マイクロコントローラが最小限のワイヤのみを使用して他の多くのスレーブモジュールと通信する必要がある場合に非常に便利です。長距離通信をお探しの場合はRS232をお試しください。より信頼性の高い通信をお探しの場合は、SPIプロトコルをお試しください。
ArduinoのI2C
下の画像は、ArduinoUNOに存在するI2Cピンを示しています。
I2Cライン | Arduinoでピン留め |
SDA | A4 |
SCL | A5 |
2つのArduinoを使用してI2Cのプログラミングを始める前に。ArduinoIDEで使用されているWireライブラリについて学ぶ必要があります。
ライブラリー
1. Wire.begin(address):
用途: このライブラリは、I2Cデバイスとの通信に使用されます。これにより、Wireライブラリが開始され、マスターまたはスレーブとしてI2Cバスに参加します。
アドレス:7ビットのスレーブアドレスはオプションであり、アドレスが指定されていない場合は、このようにマスターとしてバスに参加します。
2. Wire.read():
使用法:この関数は、 requestFrom()の 呼び出し後にスレーブデバイスからマスターデバイスに送信された、またはマスターからスレーブに送信された、マスターまたはスレーブデバイスから受信したバイトを読み取るために使用されます 。
3. Wire.write():
用途:この機能は、スレーブまたはマスターデバイスにデータを書き込むために使用されます。
スレーブからマスターへ:マスターで Wire.RequestFrom() が使用されている場合、スレーブはマスターにデータを書き込みます。
マスターからスレーブへ:マスターからスレーブデバイスへの送信では、 Wire.write() は、 Wire.beginTransmission() と Wire.endTransmission()の 呼び出しの間に使用され ます。
Wire.write()は次のように書くことができます:
- Wire.write(value)
value:1バイトとして送信する値。
- Wire.write(string):
string:一連のバイトとして送信する文字列。
- Wire.write(data、length):
data:バイトとして送信するデータの配列
長さ:送信するバイト数。
4. Wire.beginTransmission(address):
使用法:この機能は、指定されたスレーブアドレスでI2Cデバイスへの送信を開始するために使用されます。続いて、 write() 関数を使用して送信するバイトのキューを作成し、 endTransmission() 関数を呼び出して送信し ます。デバイスの7ビットアドレスが送信されます。
5. Wire.endTransmission();
使用法:この関数は、 beginTransmission() によって開始されたスレーブデバイスへの送信を終了し、 Wire.write() によってキューに入れられたバイトを送信するために使用されます 。
6. Wire.onRequest();
使用法:この関数は、マスターがスレーブデバイスから Wire.requestFrom() を使用してデータを要求したときに呼び出されます。ここに、マスターにデータを送信するための Wire.write() 関数を含めることができます。
7. Wire.onReceive();使用法:この関数は、スレーブデバイスがマスターからデータを受信したときに呼び出されます。ここに Wire.read();を 含めることができます 。 マスターから送信されたデータを読み取る機能。
8. Wire.requestFrom(address、quantity);
使用法:この関数は、マスターでスレーブデバイスにバイトを要求するために使用されます。関数 Wire.read() は、スレーブデバイスから送信されたデータを読み取るために使用されます。
アドレス:バイトを要求するデバイスの7ビットアドレス
数量:要求するバイト数
必要なコンポーネント
- Arduino Uno(2-Nos)
- 16X2LCDディスプレイモジュール
- 10Kポテンショメータ(4-Nos)
- ブレッドボード
- 接続線
回路図
動作説明
ここでは、ArduinoでのI2C通信を示すために、2つの16X2LCDディスプレイが互いに接続された2つのArduinoUNOを使用し、両方のarduinoで2つのポテンショメータを使用して、マスターからスレーブへ、およびスレーブからマスターへの送信値(0〜127)を変更して決定します。ポテンショメータ。
ポテンショメータを使用して、arduinoピンA0の入力アナログ値を(0〜5V)から取得し、それらをアナログ-デジタル値(0〜1023)に変換します。次に、I2C通信を介して送信できるのは7ビットデータのみであるため、これらのADC値はさらに(0〜127)に変換されます。I2C通信は、両方のarduinoのピンA4とA5にある2本のワイヤーを介して行われます。
Slave ArduinoのLCDの値は、マスター側のPOTを変更することで変更され、その逆も同様です。
ArduinoでのI2Cプログラミング
このチュートリアルには、マスターArduino用とスレーブArduino用の2つのプログラムがあります。双方のための完全なプログラムは、デモンストレーションビデオでこのプロジェクトの終わりに与えられます。
マスターArduinoプログラミングの説明
1.まず、I2C通信機能を使用するためのWireライブラリとLCD機能を使用するためのLCDライブラリを含める必要があります。また、16x2LCDのLCDピンを定義します。LCDとArduinoのインターフェースについて詳しくは、こちらをご覧ください。
#include
2. void setup()で
- ボーレート9600でシリアル通信を開始します。
Serial.begin(9600);
- 次に、ピン(A4、A5)でI2C通信を開始します。
Wire.begin(); //ピン(A4、A5)でI2C通信を開始します
- 次に、LCDディスプレイモジュールを16X2モードで初期化し、ウェルカムメッセージを表示して、5秒後にクリアします。
lcd.begin(16,2); // LCDディスプレイを 初期化し ますlcd.setCursor(0,0); //ディスプレイの最初の行にカーソルを設定しますlcd.print( "Circuit Digest"); // CIRCUITDIGEST をLCDに出力lcd.setCursor(0,1); //ディスプレイの2行目にカーソルを設定しますlcd.print( "I2C 2 ARDUINO"); // I2C ARDUINOをLCDdelay (5000);で出力します。// 5秒間遅延 lcd.clear(); // LCDディスプレイをクリアします
3. void loop()内
- まず、スレーブからデータを取得する必要があるため、スレーブアドレス8で requestFrom() を使用し、1バイトを要求します。
Wire.requestFrom(8,1);
受信した値は、Wire.read()を使用して読み取られます。
バイトMasterReceive = Wire.read();
- 次に、ピンA0に接続されたマスターarduinoPOTからアナログ値を読み取る必要があります
int potvalue = analogRead(A0);
その値を1バイトで0から127に変換します。
バイトMasterSend = map(potvalue、0,1023,0,127);
- 次に、これらの変換された値を送信する必要があるため、8アドレスのスレーブarduinoで送信を開始します
Wire.beginTransmission(8); Wire.write(MasterSend); Wire.endTransmission();
- 次に、500マイクロ秒の遅延でスレーブarduinoから受信した値を表示し、それらの値を継続的に受信して表示します。
lcd.setCursor(0,0); // LCDの1行目にCurrsorを設定します lcd.print( ">> Master <<"); //印刷>>マスター<< LCD lcd.setCursor(0,1); // LCDの2行目にカーソルを設定します lcd.print( "SlaveVal:"); // SlaveValを出力します:LCDで lcd.print(MasterReceive); //スレーブから受信したLCDにMasterReceiveを出力します Serial.println( "Master Received From Slave"); //シリアルモニターで 出力Serial.println(MasterReceive); delay(500); lcd.clear();
スレーブArduinoプログラミングの説明
1.マスターと同じように、まず、I2C通信機能を使用するためのワイヤーライブラリとLCD機能を使用するためのLCDライブラリを含める必要があります。また、16x2LCDのLCDピンを定義します。
#include
2. void setup()で
- ボーレート9600でシリアル通信を開始します。
Serial.begin(9600);
- 次に、スレーブアドレスを8としてピン(A4、A5)でI2C通信を開始します。ここでは、スレーブアドレスを指定することが重要です。
Wire.begin(8);
次に、スレーブがマスターから値を受け取ったとき、およびマスターがスレーブから値を要求したときに、関数を呼び出す必要があります。
Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent);
- 次に、LCDディスプレイモジュールを16X2モードで初期化し、ウェルカムメッセージを表示して、5秒後にクリアします。
lcd.begin(16,2); // LCDディスプレイを 初期化し ますlcd.setCursor(0,0); //ディスプレイの最初の行にカーソルを設定しますlcd.print( "Circuit Digest"); // CIRCUITDIGEST をLCDに出力lcd.setCursor(0,1); //ディスプレイの2行目にカーソルを設定しますlcd.print( "I2C 2 ARDUINO"); // I2C ARDUINOをLCDdelay (5000);で出力します。// 5秒間遅延 lcd.clear(); // LCDディスプレイをクリアします
3.次に、リクエストイベント用と受信イベント用の2つの関数があり ます。
リクエストイベントの場合
マスターがスレーブから値を要求すると、この関数が実行されます。この関数は、スレーブPOTから入力値を取得し、それを7ビットに変換して、その値をマスターに送信します。
void requestEvent() { int potvalue = AnalogRead(A0); バイトSlaveSend = map(potvalue、0,1023,0,127); Wire.write(SlaveSend); }
受信イベントの場合
マスターがスレーブアドレス(8)でスレーブにデータを送信すると、この機能が実行されます。この関数は、マスターから受信した値を読み取り、 バイト 型の変数に格納し ます 。
void receiveEvent(int howMany { SlaveReceived = Wire.read(); }
4. Void loop()の場合:
マスターから受け取った値をLCDディスプレイモジュールに継続的に表示します。
void loop(void) { lcd.setCursor(0,0); // LCDの1行目にCurrsorを設定します lcd.print( ">> Slave <<"); //印刷>>スレーブ<< LCDで lcd.setCursor(0,1); // LCDの2行目にカーソルを設定します lcd.print( "MasterVal:"); // MasterValを印刷します:LCDで lcd.print(SlaveReceived); //マスターから受信したLCDにSlaveReceived値を出力します Serial.println( "Slave Received From Master:"); //シリアルモニターで 出力Serial.println(SlaveReceived); delay(500); lcd.clear(); }
一の側にポテンショメータを回転させ、あなたは別の側にLCD上の様々な値を見ることができます。
これがArduinoでのI2C通信の方法です。ここでは2つのArduinoを使用して、データの送信だけでなく、I2C通信を使用したデータの受信も示しています。これで、任意のI2CセンサーをArduinoに接続できます。
マスターおよびスレーブArduinoの完全なコーディングは、デモビデオとともに以下に示されています。