Wire の解説と実装リファレンス

記事内には広告が含まれています。

【概要】

Wireライブラリは、Arduino環境においてI2C(Inter-Integrated Circuit)通信を制御するための標準的なインターフェースを提供します。I2Cは、2本の信号線(SDA: Serial Data, SCL: Serial Clock)を用いて、複数のデバイスをバス上に接続する同期式シリアル通信プロトコルです。Wireライブラリを使用することで、ユーザーは低レイヤーのビット操作や複雑なタイミング制御を意識することなく、MasterまたはSlaveとしてデバイスとデータをやり取りすることが可能になります。

【仕様】

主なメソッドおよび動作仕様は以下の通りです。

  • begin(): I2Cバスを初期化します。引数としてクロック周波数を指定することも可能です(ハードウェアに依存)。
  • requestFrom(uint8_t address, uint8_t quantity): Masterとして動作する際、指定したアドレスのデバイスから指定したバイト数を受信します。戻り値は実際に取得できたバイト数です。
  • write(uint8_t value): 現在のバス上のデバイスに対し、1バイトのデータを送信します。
  • endTransmission(): 送信バッファの内容を送信し、通信を完了させます。送信失敗時のエラーコードを返します。
  • onRequest(): Slaveとして動作する場合、データ要求があった際に呼び出されるコールバック関数を定義します。
  • requestWire(): Slaveとして動作する場合、Masterからのデータ要求を検知する際に呼び出されます。

データ型: 主に uint8_t (byte) 型を扱います。通信単位は基本として8ビットです。

【技術的特徴】

  1. マルチデバイス接続: 各デバイスには固有のアドレス(通常7ビット)が付与されており、単一のバス上に複数の周辺機器を統合できます。
  2. SPIとの比較:
  3. 配線数: SPIは通常4本(MOSI, MISO, SCK, SS)を必要としますが、I2Cは2本で済み、拡張性が高いです。
  4. 通信方式: SPIは全二重(Full-duplex)ですが、I2Cは半二重(Half-duplex)です。
  5. 速度: SPIはより高速なデータ転送に適していますが、I2Cは中低速のセンサーやメモリデバイスの制御において優れた省スペース性を発揮します。
  6. ACK/NACKメカニズム: 送信された各バイトに対して、受信側からの確認応答(Acknowledge)を監視し、通信の整合性を保ちます。

【注意点】

  1. プルアップ抵抗の必須性: I2Cバスはオープンドレイン構造であるため、物理的なプルアップ抵抗(通常4.7kΩ〜10kΩ)をSDAおよびSCLラインに実装する必要があります。これがない場合、通信は成立しません。
  2. ブロッキング挙動: Wireの標準的な関数はブロッキング処理を含みます。通信中にCPUが待機状態になるため、高精度なリアルタイム処理を行う場合は、通信の完了待ち時間を考慮するか、非同期的なアプローチを検討する必要があります。
  3. 割り込みの影響: I2C通信中に割り込みが発生すると、SCL/SDAのタイミングが狂い、通信エラーやデッドロックの原因となることがあります。特に長時間のデータ転送を行う場合は、割り込みの優先度や処理時間を考慮してください。
  4. クロックストレッチング: Slaveデバイスが処理に時間を要する場合、SCLラインをLowに保持してMasterを待機させますが、すべてのハードウェアがこの挙動を正しくサポートしているわけではありません。

【サンプルコード】

以下は、アドレス 0x3C のデバイスに対してデータを書き込み、再度読み出す基本的なMaster動作の例です。

#include <Wire.h>

#define DEVICE_ADDRESS 0x3C

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  // データの書き込み(例:レジスタアドレスの指定)
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(0x01);
  Wire.endTransmission();

  // データの読み出し
  Wire.requestFrom(DEVICE_ADDRESS, 1);
  if (Wire.available()) {
    uint8_t data = Wire.read();
    Serial.print("Received: ");
    Serial.println(data);
  }

  delay(1000);
}

【活用例】

  • 環境センサーの統合: 温度、湿度、気圧センサー(BME280など)を複数接続した環境モニタリングシステム。
  • ディスプレイ制御: OLEDやLCDディスプレイへの描画データ送信。
  • RTC(リアルタイムクロック): DS3231などを用いた正確な時刻情報の取得と更新。
  • 外部EEPROM/Flash: 大容量の構成データやログ情報の保存。

コメント

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