工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

このチュートリアルでは、複数のNRF24L01トランシーバーモジュールで構成されるArduinoワイヤレスネットワークの構築方法を学びます。以下の動画をご覧いただくか、書面によるチュートリアルをお読みください。

概要

例として5つのノードからなるネットワークを作成しました。各ノードはネットワーク内の任意のノードと通信でき、同時に送信機と受信機の両方として動作します。この例は、より大規模なネットワークの構築方法を説明するように設計されており、正確には単一のRFチャネルで最大3125個のモジュールが相互通信可能です。仕組みを見ていきましょう。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

前回のチュートリアルでは、NRF24L01モジュールとRF24ライブラリを使用して2台のArduinoボード間でワイヤレス通信を行う方法を学びました。今回はこれに加えてRF24Networkライブラリを使用し、複数のボードが相互通信するArduinoワイヤレスネットワークを簡単に構築できるようにします。ネットワークトポロジーの仕組みは以下の通りです。

複数のNRF24L01モジュールによる通信

1つのNRF24L01モジュールは、同時に最大6つの他のモジュールをアクティブにリスニングできます。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

RF24Networkライブラリはこの能力を利用し、1つのノードをベース(親)とし、他のすべてのノードがそのノードまたは別のノードの子となるツリー型トポロジーのネットワークを生成します。各ノードは最大5つの子を持つことができ、これが5階層まで深くなるため、合計3125ノードのネットワークを作成可能です。各ノードには15ビットのアドレスを定義する必要があり、これがツリー内でのノードの位置を正確に示します。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

ノードのアドレスは8進数形式で定義できます。マスター(ベース)のアドレスは「00」、ベースの子ノードは「01」〜「05」、ノード01の子ノードは「011」〜「051」というようになります。

なお、ノード011がノード02と通信する場合、通信はノード01とベースノード00を経由する必要があるため、これら2つのノードが常時アクティブでなければ通信は成立しません。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

RF24Networkライブラリを使用したArduinoワイヤレスサーボモーター制御

メインの例に進む前に、ライブラリの動作をより理解するために、2台のArduinoボード間のシンプルな通信例を作成します。この例の回路図は以下の通りです。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

このチュートリアルに必要なコンポーネントは以下のリンクから入手できます:

  • NRF24L01トランシーバーモジュール
  • サーボモーター
  • ポテンショメーター
  • Arduino Nano

最初のArduinoのポテンショメーターを使用して、2番目のArduinoのサーボモーターを制御します。ソースコードを見てみましょう。

ポテンショメーター側(ノード00)のコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Example 01 - Servo Control / Node 00 - Potentiometer
   by Dejan, www.HowToMechatronics.com
   Libraries: nRF24/RF24, https://github.com/nRF24/RF24
              nRF24/RF24Network, https://github.com/nRF24/RF24Network */
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

RF24 radio(10, 9); // nRF24L01 (CE, CSN)
RF24Network network(radio); // 無線をネットワークに含める
const uint16_t this_node = 00; // このノードのアドレス(8進数形式)
const uint16_t node01 = 01;    // 相手ノードのアドレス

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node); // (チャネル, ノードアドレス)
}

void loop() {
  network.update();
  unsigned long potValue = analogRead(A0); // ポテンショメーターの値を読取
  unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // 0-180に変換
  RF24NetworkHeader header(node01); // データ送信先アドレス
  bool ok = network.write(header, &angleValue, sizeof(angleValue)); // データ送信
}

まずRF24とRF24Networkライブラリ、SPIライブラリをインクルードします。RF24オブジェクトを作成し、それをRF24Networkオブジェクトに含めます。ノードアドレスを8進数形式で定義します(このノードは00、相手は01)。

setup()では、チャネルとこのノードのアドレスを指定してネットワークを初期化します。

loop()では、常にupdate()関数を呼び出す必要があります。これがネットワーク内のすべてのアクションを処理します。ポテンショメーターの値を読み取り、サーボ制御に適した0〜180の値に変換します。ネットワークヘッダーを作成して送信先アドレスを指定し、write()関数でデータを送信します。第1引数にアドレス情報、第2引数に送信データへのポインタ、第3引数にデータサイズを指定します。

サーボ側(ノード01)のコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Example 01 - Servo Control / Node 01 - Servo motor */
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <Servo.h>

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 01; // このノードのアドレス(8進数)
Servo myservo;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  myservo.attach(3); // サーボピン
}

void loop() {
  network.update();
  while (network.available()) { // 着信データがあるか?
    RF24NetworkHeader header;
    unsigned long incomingData;
    network.read(header, &incomingData, sizeof(incomingData)); // データ読取
    myservo.write(incomingData); // サーボを指定角度に動かす
  }
}

受信側も同様にライブラリとオブジェクトを定義し、このノードのアドレスを01とします。loop()ではwhile()ループとavailable()関数で着信データを常時チェック。データがあればヘッダーを作成し、read()関数でデータを読み取ってincomingData変数に格納。このデータを使って、もう一方のノードのポテンショメーターに合わせてサーボを動かします。

複数のNRF24L01モジュールによるArduinoワイヤレスネットワーク

この例を理解したら、メインの例に進み、5台のArduinoが相互通信するワイヤレスネットワークを構築します。ブロック図は以下の通りです。

NRF24L01モジュールで堅牢なArduinoワイヤレスメッシュネットワークを構築する

ベースからポテンショメーターでノード01のサーボを制御し、2つ目のポテンショメーターでノード022のLEDを制御。ボタンでノード012のLEDを制御し、ベースのLEDはノード02のポテンショメーターで制御。さらにノード012の赤外線センサーでノード01のLEDを制御します。これにより、同時に送受信を行う方法や、異なるブランチのノードと通信する方法がわかります。各ノードのArduinoコードを見ていきましょう。

ベース(ノード00)のソースコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Base / Master Node 00
   by Dejan, www.HowToMechatronics.com
   Libraries: nRF24/RF24, https://github.com/nRF24/RF24
              nRF24/RF24Network, https://github.com/nRF24/RF24Network */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define button 2
#define led 3

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 00;
const uint16_t node01 = 01;
const uint16_t node012 = 012;
const uint16_t node022 = 022;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  radio.setDataRate(RF24_2MBPS);
  pinMode(button, INPUT_PULLUP);
  pinMode(led, OUTPUT);
}

void loop() {
  network.update();
  // ===== 受信 =====
  while (network.available()) {
    RF24NetworkHeader header;
    unsigned long incomingData;
    network.read(header, &incomingData, sizeof(incomingData));
    analogWrite(led, incomingData); // LEDのPWM調光(ノード02からのデータ)
  }
  // ===== 送信 =====
  // ノード01のサーボ制御
  unsigned long potValue = analogRead(A0);
  unsigned long angleValue = map(potValue, 0, 1023, 0, 180);
  RF24NetworkHeader header2(node01);
  bool ok = network.write(header2, &angleValue, sizeof(angleValue));
  // ノード012のLED制御
  unsigned long buttonState = digitalRead(button);
  RF24NetworkHeader header4(node012);
  bool ok3 = network.write(header4, &buttonState, sizeof(buttonState));
  // ノード022のLED制御
  unsigned long pot2Value = analogRead(A1);
  RF24NetworkHeader header3(node022);
  bool ok2 = network.write(header3, &pot2Value, sizeof(pot2Value));
}

ベース(マスターノード)では、ライブラリとオブジェクトを定義し、マスターがデータを送信するすべてのノードを定義します。loop()ではまず着信データを常時チェック。データがあれば読み取り、LEDの明るさを制御します(このデータはノード02のポテンショメーターから来ます)。ノード02のコードを見ると、setupはほぼ同じですが、データを送信したい正しいアドレス(マスターの00)を割り当てることが重要です。ポテンショメーターの値を読み取り、0〜255のPWM値に変換してマスターに送信します。ここではmillis()関数を使って10ミリ秒間隔でデータを送信しています。

ノード02のソースコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Node 02 (Child of Master node 00) */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 02;
const uint16_t master00 = 00;
const unsigned long interval = 10; // ms - データ送信間隔
unsigned long last_sent;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  radio.setDataRate(RF24_2MBPS);
}

void loop() {
  network.update();
  // ===== 送信 =====
  unsigned long now = millis();
  if (now - last_sent >= interval) {
    last_sent = now;
    unsigned long potValue = analogRead(A0);
    unsigned long ledBrightness = map(potValue, 0, 1023, 0, 255);
    RF24NetworkHeader header(master00);
    bool ok = network.write(header, &ledBrightness, sizeof(ledBrightness));
  }
}

次に、マスターからポテンショメーターデータをノード01に送信してサーボを制御します。

ノード01のソースコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Node 01 (Child of Master node 00) */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Servo.h>

#define led 2

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 01;
const uint16_t master00 = 00;
Servo myservo;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  radio.setDataRate(RF24_2MBPS);
  myservo.attach(3);
  pinMode(led, OUTPUT);
}

void loop() {
  network.update();
  // ===== 受信 =====
  while (network.available()) {
    RF24NetworkHeader header;
    unsigned long incomingData;
    network.read(header, &incomingData, sizeof(incomingData));
    if (header.from_node == 0) { // データがノード00(マスター)からの場合
      myservo.write(incomingData);
    }
    if (header.from_node == 10) { // データがノード012からの場合(8進数の012 = 10進数の10)
      digitalWrite(led, !incomingData);
    }
  }
}

ノード01は2つの異なるノードからデータを受信します。1つはサーボ制御用(マスターから)、もう1つはLED制御用(ノード012の赤外線センサーから)。このような場合、header.from_node属性を使ってデータがどのノードから来たかを判別します。マスターからのデータならサーボ制御に、ノード012からのデータならLED制御に使用します。

ノード012のソースコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Node 012 (Child of Node 01) */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define led 2
#define IR 3

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 012;
const uint16_t node01 = 01;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  radio.setDataRate(RF24_2MBPS);
  pinMode(led, OUTPUT);
  pinMode(IR, INPUT);
}

void loop() {
  network.update();
  // ===== 受信 =====
  while (network.available()) {
    RF24NetworkHeader header;
    unsigned long buttonState;
    network.read(header, &buttonState, sizeof(buttonState));
    digitalWrite(led, !buttonState); // マスターのボタンでLED制御
  }
  // ===== 送信 =====
  unsigned long irV = digitalRead(IR); // 赤外線センサー読取
  RF24NetworkHeader header8(node01);
  bool ok = network.write(header8, &irV, sizeof(irV)); // ノード01へ送信
}

ノード012では送受信の両方を行います。赤外線センサーでノード01のLEDを制御し、このノードのLEDはマスターのボタンで制御されます。

ノード022のソースコード

/* Arduino Wireless Network - Multiple NRF24L01 Tutorial
   Node 022 (Child of Node 02) */
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define led1 2
#define led2 3
#define led3 4
#define led4 5

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 022;
const uint16_t master00 = 00;

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);
  radio.setDataRate(RF24_2MBPS);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
}

void loop() {
  network.update();
  // ===== 受信 =====
  while (network.available()) {
    RF24NetworkHeader header;
    unsigned long potValue;
    network.read(header, &potValue, sizeof(potValue));
    // ポテンショメーターの値に応じてLEDを点灯
    if (potValue > 240) digitalWrite(led1, HIGH); else digitalWrite(led1, LOW);
    if (potValue > 480) digitalWrite(led2, HIGH); else digitalWrite(led2, LOW);
    if (potValue > 720) digitalWrite(led3, HIGH); else digitalWrite(led3, LOW);
    if (potValue > 960) digitalWrite(led4, HIGH); else digitalWrite(led4, LOW);
  }
}

最後に、ノード022のLEDはマスターのもう1つのポテンショメーターからのデータで制御されます。

まとめると、すべてが正しく接続され、すべてのノードが常時アクティブであれば、私たちの仕事はノードを正確にアドレッシングすることだけです。裏側の重い処理は、素晴らしいRF24Networkライブラリがすべて引き受けてくれます。

このArduinoプロジェクトをお楽しみいただけたら幸いです。ご質問はコメント欄でお気軽にお尋ねください。

製造プロセス

  1. 家庭用の低コストワイヤレスセンサーネットワークを構築
  2. Raspberry Piで手書き数字認識:TensorFlowとOpenCVを用いたディープラーニング実装
  3. ArduinoとInfineon 3D磁気センサーで作る無線磁気データ転送
  4. K30 CO2センサで室内空気質をリアルタイム監視する
  5. 1SheeldとArduinoで盲ろう者のコミュニケーションを支援する
  6. スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
  7. ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
  8. DFRobot静電容量式指紋センサーをArduino/ESP8266で使う – 登録・認証・削除の完全ガイド
  9. USB-MIDI機器をBluetooth LEでiOSに無線接続 ─ Arduinoベースの3つのアダプター設計
  10. Arduino MegaとNextion HMIで作る高機能ウェザーステーション
  11. Arduinoベースのヌンチャク操作6自由度ロボットアームキット