2台のNano 33 BLE SenseボードをI2Cで接続する
i
このチュートリアルは、すでに製品ライフサイクルの終了(EOL)を迎えた製品を対象としています。

Nano 33 BLE SenseボードからI2C経由で別のボードにデータを送信する方法を学びます。


Author:Benjamin DannegårdLast revision:2024/07/17

このチュートリアルでは、Arduino Nano 33 BLE Senseの内蔵LEDを、別のArduino Nano 33 BLEから制御します。このために、I2Cと呼ばれる有線プロトコルで両方のボードを接続します。

注意: この例は、Arduino BLE Senseボードと、どのようなArduinoボードを接続しても動作します。しかし、他のボードを使うときの接続は異なるかもしれないことに注意してください。接続が異なるときには、異なるボードのI2Cピンに適合するように、コードを修正する必要があるかもしれません。

この例では、両方のArduinoボードにPCから給電し、シリアルモニタで、33 BLE SenseボードのLEDをオン・オフするコマンドをいくつか作ります。

目的

このプロジェクトの目的は以下の通りです。

  • I2Cプロトコルとは何かを理解する
  • Wire.hライブラリを使う
  • 2台のArduinoボードでI2C通信を行う

必要なハードウェアとソフトウェア

このプロジェクトで必要なものは以下の通りです。

  • Arduino Nano 33 BLE Sense
  • Arduino Nano 33 BLE Sense(もしくはI2Cをサポートする他のArduinoボード)
  • ミニブレッドボード 2個
  • ジャンプワイヤー 10本
  • 4.7kΩの抵抗 2個

I2Cプロトコル

I2C(Inter Integrated Circuits)は、よく知られていて、幅広く利用されているプロトコルです。複数の受信機器を一つの送信機器に接続することができます。すなわち、I2Cを使えば、1つ以上のセンサーをArduinoボードの同じピンに接続することができるということです。各センサーが異なるアドレスを持つことが唯一の要件です。

I2Cプロトコルでは、データの送受信に2本の信号線を利用します。一つは、シリアルクロックピン(Serial CLock pin: SCL)で、Arduinoの送信側のボードが一定間隔でパルスを送信します。もう一つは、シリアルデータピン(Serial DAta pin: SDA)で、2つのデバイス間でデータ送信します。

クロックラインがLOWからHIGHになると、指定したアドレスのデバイスからコマンドもしくはデータの1ビットの情報が、ボードからSDA線を通じてI2Cデバイスに送信されます。この情報が送られると、呼び出されたデバイスは要求を実行し、要求されていれば、送信側がSCLに生成しているクロック信号を使って同じ信号線で、データをボードに返します。

I2Cプロトコルや動作方法をより深く知りたければ、I2C規格を参照してください。

Wireライブラリ

I2Cプロトコルを簡単に利用するために、Arduinoでは"Wire"ライブラリを使います。このライブラリにより、異なるArduinoボードで、このプロトコルの実装と利用が可能です。このライブラリは、ボードのいくつかの特定のピンでのみ利用できます。これらのピンは、SCLとSDAと呼ばれ、Arduino Nanoファミリーボードでは、SDA(データ線)とSCL(クロック線)は、それぞれ、A4とA5ピンヘッダです。

Wire.hについて、さらに知りたければ、こちらを参照してください。

回路

2台のArduinoボードで通信するには、以下の図のように配線します。

接続する際には、このプロトコルではSCL(クロック)とSDA(データ)の2つの専用線があるので、一方のボードのSCLピンをもう一方のボードのSCLピンに接続する必要があります。図に示すように、SDAについても同様です。

最後に、双方のボードのGNDピン同士を接続します。

注意: シリアル通信を行うには、双方のArduinoボードをUSBでPCに接続する必要があります。

プログラム作成

  1. 設定

Arduino Nano 33 BLE SenseボードをPCに接続し、Arduino Create Cloudエディタを起動します。このボードは受信側です。新しいスケッチを開始し、Nano_I2C_Readerと名付けます。

  1. 受信側コードの説明

#include <Wire.h>指令を追加して、Wire.hを追加します。setup()で、Wire.begin(8)を追加して、ライブラリを開始し、受信側ボードにアドレスとして8を設定します。これにより送信側はデータをどのボードから送受信する必要があるのかが特定できます。送信側からデータを受信したときに毎回呼び出されるWire.onReceive()も使います。

1
2
3
4
5
6
#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // function that executes whenever data is received from writer
}

I2Cで何か受信するまでは何もしないので、このコードのloop()は重要ではありません。このため、loop()関数は空のままにしておきます。

ボードがデータを受信したときに実行されるreceiveEvent()関数を作成します。簡単に使うために、受信したデータをcという変数に格納します。受信するデータは文字なので、文字を比較します。if文で、送信されたデータが1か0かを確認します。受信したデータに応じて、内蔵LEDを点灯するか消灯させます。

1
2
3
4
5
6
7
8
9
void receiveEvent(int howMany) {
   char c = Wire.read(); // receive a character
   if(c == '0'){
     digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
   }
   if(c == '1'){
     digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
   }
}
  1. コードを受信側にアップロードする

コードが完成したら、Arduino Nano 33 BLE Senseボードにアップロードします。このシナリオでは、このボードは受信側として動作するようにプログラムされています。コードがアップロードされたら、別のボードをPCに接続します。

注意: 受信側のボードにコードをアップロードしたら、ボードを動作させるのにPCと接続し続けるする必要はありません。しかし、動作させるには給電する必要があります。

  1. 送信側のコード

新しいスケッチを開き、Nano_I2C_Writerと名付けます。そして、以前のコードと同じようにWireライブラリを追加します。

setup()に、シリアルポートを開き、データレートを9600ビット毎秒(baud)に設定するSerial.begin(9600)を追加します。次に、while (!Serial);を追加し、Arduinoがメッセージを送信開始する前に、USB接続の反対側に通信できるものがあることを確認します。そうしないと、メッセージは送信されますが、表示されません。Wire.begin()も追加し、Wireライブラリを開始し、送信側あるいは受信側としてI2Cバスに参加します。

1
2
3
4
5
6
7
#include <Wire.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Wire.begin(); // join i2c bus (address optional for writer)
}

loop()では、何を入力すればいいかを知らせるメッセージを表示します。その後、ledValという変数を定義します。この変数は、シリアルモニタに入力した値を保持します。readSerial()で、シリアルモニタに入力された値を取得し、ledValに格納します。その後、I2C通信を始めます。

Wire.beginTransmission(8)で、データをどの受信者に送信するかを指定します。受信側のコードでは、ボードのアドレスを8にしました。通信が開始すると、Wire.write()で、受信側に送信するデータを選びます。今回は、ledValの値を送信します。その後、Wire.endTransmission()で送信を終了します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
void loop() {
  Serial.print("Enter 0 to turn off led, enter 1 to turn it on ");
  char ledVal[0];
  readSerial(ledVal);
  Serial.println(ledVal);
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write(ledVal);        // sends the given value
  Wire.endTransmission();    // stop transmitting
  delay(500);
}

readSerial()関数では、シリアルモニタに入力された値を取得し、変数に格納することで、I2C経由で送信できるようにします。この関数はエンターが送信されたのを検出し、エンターが入力さる前の文字を変数に格納します。必要ならばより長い文字列を格納できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
int readSerial(char result[]) {
  int i = 0;
  while (1) {
    while (Serial.available() > 0) {
      char inChar = Serial.read();
      if (inChar == '\n') {
        result[i] = '\0';
        Serial.flush();
        return 0;
      }
      if (inChar != '\r') {
        result[i] = inChar;
        i++;
      }
    }
  }
}
  1. コードを送信側にアップロードする

コードが完成したら、Arduino Nano 33 BLE Senseボードにアップロードします。このボードは送信側として動作するようにプログラムされています。

  1. コードを完成させる

コード作成セクションをスキップした場合のために、以下の受信側と送信側の完全なコードを示します。

受信側:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // function that executes whenever data is received from writer
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany) {
   char c = Wire.read(); // receive a character
   if(c == '0'){
     digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
   }
   if(c == '1'){
     digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
   }
}

送信側:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <Wire.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Wire.begin(); // join i2c bus (address optional for writer)
}

void loop() {
  Serial.print("Enter 0 to turn off led, enter 1 to turn it on ");
  char ledVal[0];
  readSerial(ledVal);
  Serial.println(ledVal);
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write(ledVal);        // sends the given value
  Wire.endTransmission();    // stop transmitting
  delay(500);
}

/* Read input serial */
int readSerial(char result[]) {
  int i = 0;
  while (1) {
    while (Serial.available() > 0) {
      char inChar = Serial.read();
      if (inChar == '\n') {
        result[i] = '\0';
        Serial.flush();
        return 0;
      }
      if (inChar != '\r') {
        result[i] = inChar;
        i++;
      }
    }
  }
}

テスト

スケッチの検証と2台のボードへのアップロードが成功したら、送信側のボードの接続を確認し、シリアルモニタを開いてください。1か0かを入力するよう求める文字が表示されているはずです。値を入力したら、その値は受信側のボードに送信されます。

トラブルシュート

エラーが起きることもあります。コードが動作しないときはいくつかの共通の問題があり、解決できます。

  • 括弧やセミコロンが抜けている。
  • Arduinoボードが、間違ったポートに接続されている。
  • Arduinoボード間の接続が間違っている。
  • ケーブル接続の予期しない切断。

おわりに

この簡単なチュートリアルでは、Wire.hライブラリを利用し、2台のボードを接続し、I2Cで通信するための方法を学びました。

オリジナルのページ

https://docs.arduino.cc/tutorials/nano-33-ble-sense/i2c/

最終更新日

August 16, 2026

inserted by FC2 system