I2C通信はどのように機能しますか? ArduinoとI2Cチュートリアル
このチュートリアルでは、I2C通信プロトコルがどのように機能するかを学び、Arduinoボードとこのプロトコルを使用するセンサーを使用した実際の例を示します。次のビデオを見るか、以下のチュートリアルを読むことができます。
I2C通信バスは、マスターと複数のスレーブデバイス、さらには複数のマスターデバイス間の通信を必要とする多くの電子設計に簡単に実装できるため、非常に人気があり、多くの電子デバイスで広く使用されています。簡単な実装には、7ビットアドレス指定を使用する場合は最大約128(112)デバイス、10ビットアドレス指定を使用する場合は最大約1024(1008)デバイス間の通信に必要なワイヤは2本だけであるという事実があります。
どうしてそんなに多くのデバイス間の通信を配線だけで行うことができるのでしょうか?各デバイスには事前設定されたIDまたは一意のデバイスアドレスがあるため、マスターはどのデバイスと通信するかを選択できます。
2本のワイヤまたはラインは、シリアルクロック(またはSCL)およびシリアルデータ(またはSDA)と呼ばれます。 SCLラインは、I2Cバス上のデバイス間のデータ転送を同期させるクロック信号であり、マスターデバイスによって生成されます。もう1つの回線は、データを伝送するSDA回線です。
2つのラインは「オープンドレイン」です。つまり、I2Cバス上のデバイスはアクティブローであるため、ラインがハイになるようにプルアップ抵抗を接続する必要があります。抵抗器に一般的に使用される値は、約400 kbpsの高速の2Kから、約100kbpsの低速の10Kまでです。
データ信号は8ビットのシーケンスで転送されます。したがって、特別な開始条件が発生した後、データの送信先のスレーブのアドレスを示す最初の8ビットシーケンスが発生します。各8ビットシーケンスの後に、確認応答と呼ばれるビットが続きます。ほとんどの場合、最初の確認応答ビットの後に別のアドレス指定シーケンスがありますが、今回はスレーブデバイスの内部レジスタ用です。アドレス指定シーケンスの直後は、データが完全に送信され、特別な停止条件で終了するまで、データシーケンスの数だけ続きます。
これらのイベントをさらに詳しく見てみましょう。開始条件は、クロックラインがまだハイである間にデータラインがローに低下したときに発生します。この後、クロックが開始し、各クロックパルス中に各データビットが転送されます。
デバイスのアドレス指定シーケンスは、最初に最上位ビット(MSB)で始まり、最下位ビット(LSB)で終わります。これは、8番目の
のため、実際には7ビットで構成されています。 ビットは、マスターがスレーブに書き込むか(ロジックロー)、スレーブから読み取るか(ロジックハイ)を示すために使用されます。
次のビットAKC/NACKは、スレーブデバイスが前のビットシーケンスを正常に受信したかどうかを示すために使用されます。したがって、この時点で、マスターデバイスはSDAラインの制御をスレーブデバイスに引き渡し、スレーブデバイスが前のシーケンスを正常に受信した場合、SDAラインを確認応答と呼ばれる状態にプルダウンします。スレーブがSDAラインをプルダウンしない場合、その状態はNot Acknowledgeと呼ばれ、いくつかの理由で前のシーケンスを正常に受信できなかったことを意味します。たとえば、スレーブがビジー状態である、受信したデータまたはコマンドを理解していない、それ以上データを受信できないなどの可能性があります。このような場合、マスターデバイスがどのように進行するかを決定します。
次は、内部レジスタのアドレス指定です。内部レジスタは、さまざまな情報またはデータを含むスレーブのメモリ内の場所です。たとえば、ADX345加速度計には、X、Y、およびZ軸用の一意のデバイスアドレスと追加の内部レジスタアドレスがあります。したがって、X軸のデータを読み取る場合は、最初にデバイスアドレスを送信し、次にX軸の特定の内部レジスタアドレスを送信する必要があります。これらのアドレスは、センサーのデータシートから見つけることができます。
アドレス指定後、データ転送シーケンスは、R/Wビットで選択されたモードに応じてマスターまたはスレーブのいずれかから開始されます。データが完全に送信された後、転送は停止状態で終了します。これは、SCLラインがハイのときにSDAラインがローからハイに移行したときに発生します。
例として、5つの異なるセンサーで構成されるGY-80ブレークアウトボードと、3つの異なるセンサーで構成されるGY-521ブレークアウトボードを使用します。したがって、I2Cバスを使用して2本のワイヤーで8つの異なるセンサーからデータを取得できます。
これらのコンポーネントは、以下のいずれかのサイトから入手できます。
ボードを接続する方法は次のとおりです。 Arduinoボードのシリアルクロックピンは2つのブレークアウトボードのシリアルクロックピンに接続されます。同じことがシリアルデータピンにも当てはまり、ArduinoボードのGndピンと5Vピンでボードに電力を供給します。ここでは、ブレークアウトボードにすでにプルアップ抵抗が使用されているため、プルアップ抵抗を使用していないことに注意してください。
これらのチップまたはセンサーと通信するには、それらの一意のアドレスを知る必要があります。それらはセンサーのデータシートから見つけることができます。 GY-80ブレークアウトボードには、次の4つのアドレスがあります。3軸加速度センサーの場合は16進数の0x53、3軸ジャイロの場合は16進数の0x69、3軸磁力計の場合は16進数の0x1E、気圧計と温度計の場合は16進数の0x77です。センサー。
GY-521ブレークアウトボードの場合、アドレスは1つだけで、16進数の0x68です。 Arduinoの公式ウェブサイトから入手できるArduinoI2Cスキャナーのスケッチを使用してアドレスを取得または確認することもできます。したがって、ここでそのスケッチをアップロードして実行すると、I2Cバスに接続されているデバイスのアドレスが取得されます。
センサー部品番号I2Cアドレス
3軸加速度計アナログデバイセズADXL3450x530x530データシート
3軸GyroSTマイクロエレクトロニクスL3G4200D0x690x690データシート
3軸磁力計HoneywellMC5883L0x1Eデータシート
バロメーター+温度計BoschBMP0850x770x770データシート
デバイスのアドレスを見つけたら、デバイスからデータを読み取るために、デバイスの内部レジスタのアドレスも見つける必要があります。たとえば、GY-80ブレークアウトボードの3軸加速度センサーからX軸のデータを読み取りたい場合は、X軸のデータが保存されている内部レジスタアドレスを見つける必要があります。センサーのデータシートから、X軸のデータが実際には2つのレジスタに格納されていることがわかります。16進アドレス0x32のDATAX0と16進アドレス0x33のDATAX1です。
次に、X軸のデータを取得するコードを作成しましょう。そのため、スケッチに含める必要のあるArduinoワイヤーライブラリを使用します。ここでは、最初に、以前に見つけたセンサーアドレスと2つの内部レジスタアドレスを定義する必要があります。 Wire.begin() 関数はWireライブラリを開始します。また、シリアルモニターを使用してセンサーからのデータを表示するため、シリアル通信を開始する必要があります。
loop()内 Wire.beginTransmission()から始めます 特定のセンサー、この場合は3軸加速度計への送信を開始する機能。次に、 Wire.write()を使用します 関数は、X軸の2つのレジスタから特定のデータを要求します。 Wire.endTransmission() 送信を終了し、レジスタからデータを送信します。 Wire.requestFrom()を使用します 関数は、送信されたデータまたは2つのレジスタからの2バイトを要求します。
Wire.available() 関数は、取得可能なバイト数を返し、その数が要求されたバイト(この場合は2バイト)と一致する場合は、 Wire.read()を使用します。 関数は、X軸の2つのレジスタからバイトを読み取ります。最後に、データをシリアルモニターに印刷します。これがそのデータですが、これは生データであり、X軸の正しい値を取得するにはいくつかの計算を行う必要があることに注意してください。その詳細については、Arduinoボードで加速度計を使用するための次のチュートリアルを参照してください。ArduinoI2C通信の仕組みを説明することが主な目的であったため、このチュートリアルを過負荷にしたくないためです。I2Cのしくみ
I2Cプロトコル
ArduinoI2Cコード
/*
* How I2C Communication Protocol Works - Arduino I2C Tutorial
*
* by Dejan, www.HowToMechatronics.com
*
*/
#include <Wire.h>
int ADXLAddress = 0x53; // Device address in which is also included the 8th bit for selecting the mode, read in this case.
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#define Power_Register 0x2D // Power Control Register
int X0,X1,X_out;
void setup() {
Wire.begin(); // Initiate the Wire library
Serial.begin(9600);
delay(100);
// Enable measurement
Wire.beginTransmission(ADXLAddress);
Wire.write(Power_Register);
// Bit D3 High for measuring enable (0000 1000)
Wire.write(8);
Wire.endTransmission();
}
void loop() {
Wire.beginTransmission(ADXLAddress); // Begin transmission to the Sensor
//Ask the particular registers for data
Wire.write(X_Axis_Register_DATAX0);
Wire.write(X_Axis_Register_DATAX1);
Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
Wire.requestFrom(ADXLAddress,2); // Request the transmitted two bytes from the two registers
if(Wire.available()<=2) { //
X0 = Wire.read(); // Reads the data from the register
X1 = Wire.read();
}
Serial.print("X0= ");
Serial.print(X0);
Serial.print(" X1= ");
Serial.println(X1);
}
Code language: Arduino (arduino)
製造プロセス
- Raspi 2WIOTとのArduinoI2C通信
- Arduinoエネルギーモニターとデータロガーを構築する方法
- 温度および湿度データロガー
- Python3とArduinoコミュニケーション
- ArduinoでNMEA-0183を使用する方法
- Arduinoチュートリアル:JARVIS v1 |ホームオートメーションの作り方
- Arduinoをマルチスレッド化する方法(プロトスレッドチュートリアル)
- nRF24L01 –仕組み、Arduinoインターフェース、回路、コード
- ArduinoとMPU6050加速度計とジャイロスコープのチュートリアル
- ArduinoとADXL345加速度計で向きを追跡する方法
- ArduinoおよびHC-12長距離無線通信モジュール