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

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

このチュートリアルでは、nRF24L01トランシーバーモジュールを使用して、2枚のArduinoボード間で無線通信を実現する方法を学びます。nRF24L01モジュールは、Arduinoで無線通信を行う際の非常に人気のある選択肢です。

私はこのモジュールを多数のArduinoプロジェクトで使用してきました。いくつかはこちらで確認できます:

  • DIY Arduino RC送信機
  • Arduino RC飛行機 | 100%自作
  • DIY ArduinoベースRCホバークラフト
  • Arduino無線気象観測ステーションプロジェクト

以下の動画を見るか、書面チュートリアルをお読みください。nRF24L01トランシーバーモジュールについて知っておくべきすべて(ピンアウト、動作原理、配線、複数のコード例)が含まれています。

概要

無線通信を説明するために2つの例を作成します。最初の例では、1台のArduinoからもう1台へシンプルな「Hello World」メッセージを送信します。2番目の例では、Arduinoボード間で双方向通信を行います。1台目のArduinoのジョイスティックで2台目のサーボモーターを制御し、逆に2台目のプッシュボタンで1台目のLEDを制御します。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

nRF24L01トランシーバーモジュール

nRF24L01トランシーバーモジュールを詳しく見てみましょう。2.4GHz帯を使用し、250kbpsから2Mbpsのボーレートで動作できます。開放空間で低ボーレートを使用すれば、通信距離は最大100メートルに達します。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

完全な仕様は以下の通りです:

周波数範囲2.4 – 2.5GHz ISM帯
データレート250Kbps / 1Mbps / 2Mbps
最大出力電力0dBm
動作電圧1.9 – 3.6V
最大動作電流12.3mA
スタンバイ電流22µA
ロジック入力5V耐圧
通信距離100m(開放空間)

動作原理

このモジュールは125の異なるチャネルを使用でき、1か所に125台の独立して動作するモデムを構築できます。各チャネルは最大6つのアドレスを持つことができ、つまり各ユニットは同時に最大6台の他ユニットと通信可能です。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

このモジュールの消費電力は送信時でわずか約12mAで、単一のLEDよりも低いです。動作電圧は1.9〜3.6Vですが、他のピンは5Vロジックに耐えられるため、ロジックレベルコンバーターなしでArduinoに簡単に接続できます。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

3つのピンはSPI通信用で、ArduinoのSPIピンに接続する必要があります。ただし、ArduinoボードごとにSPIピンが異なることに注意してください。CSNピンとCEピンはArduinoの任意のデジタルピンに接続でき、モジュールをスタンバイ/アクティブモードに設定したり、送信/コマンドモードを切り替えたりするために使用します。最後のピンは割り込みピンで、必ずしも使用する必要はありません。

モジュールのバリエーション

nRF24L01モジュールにはいくつかのバリエーションがあります。最も人気なのは、オンボードアンテナ搭載タイプです。これによりモジュールがコンパクトになりますが、反面、伝送距離が約100メートルに制限されます。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

2つ目のバリエーションは、オンボードアンテナの代わりにSMAコネクタを備え、ダックアンテナを取り付けて伝送距離を延ばせます。

ここに示す3つ目のバリエーションは、ダックアンテナに加えて、PA(パワーアンプ)とLNA(低雑音アンプ)を含むRFX2401Cチップを搭載しています。これによりnRF24L01信号が増幅され、開放空間で最大1000メートルの伝送距離を実現します。

nRF24L01モジュールピンアウト

nRF24L01ピンアウトと、nRF24L01+ PA/LNAモジュールの詳細を見てみましょう。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

nRF24L01とnRF24L01+ PA/LNAの両モジュールは同じピンアウトを持つため、同じように回路接続できます。

nRF24L01をArduinoに接続する方法

nRF24L01モジュールをArduinoボードに接続する方法は以下の通りです。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

前述の通り、ArduinoボードごとにSPIピンが異なるため、自分のボードに合わせて接続してください。

ArduinoSCKMISOMOSISS
Uno13121110
Nano13121110
Mega52505153

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

  • nRF24L01トランシーバーモジュール………
  • Arduinoボード……………………………………
  • ブレッドボードとジャンパーワイヤー…………

ArduinoとnRF24L01のコード

nRF24L01モジュールをArduinoボードに接続したら、送信側と受信側両方のコードを作成します。

まず、プログラミングを容易にするRF24ライブラリをダウンロードしてインストールする必要があります。Arduino IDEのライブラリマネージャーから直接インストールすることも可能です。「rf24」で検索し、「TMRh20, Avamander」によるものを探してインストールしてください。

以下に無線通信用の2つのコードとその説明を示します。

送信側コード

/* 
 * Arduino無線通信チュートリアル 
 * 例1 - 送信側コード 
 * by Dejan Nedelkovski, www.HowToMechatronics.com 
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ 
 */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
RF24 radio(7, 8); // CE, CSN 
const byte address[6] = "00001"; 
void setup() { 
  radio.begin(); 
  radio.openWritingPipe(address); 
  radio.setPALevel(RF24_PA_MIN); 
  radio.stopListening(); 
} 
void loop() { 
  const char text[] = "Hello World"; 
  radio.write(&text, sizeof(text)); 
  delay(1000); 
}

受信側コード

/* 
 * Arduino無線通信チュートリアル 
 * 例1 - 受信側コード 
 * by Dejan Nedelkovski, www.HowToMechatronics.com 
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ 
 */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
RF24 radio(7, 8); // CE, CSN 
const byte address[6] = "00001"; 
void setup() { 
  Serial.begin(9600); 
  radio.begin(); 
  radio.openReadingPipe(0, address); 
  radio.setPALevel(RF24_PA_MIN); 
  radio.startListening(); 
} 
void loop() { 
  if (radio.available()) { 
    char text[32] = ""; 
    radio.read(&text, sizeof(text)); 
    Serial.println(text); 
  } 
}

コード解説

基本のSPIライブラリと新しくインストールしたRF24ライブラリをインクルードし、RF24オブジェクトを作成します。2つの引数はCSNピンとCEピンです。

RF24 radio(7, 8); // CE, CSN

次に、2つのモジュールが通信するためのアドレス、いわゆる「パイプ」を表すバイト配列を作成します。

const byte address[6] = "00001";

このアドレスの値は任意の5文字の文字列に変更でき、どの受信機と通信するかを選択できます。今回は送信側と受信側で同じアドレスを使用します。

setupセクションでは、radioオブジェクトを初期化し、radio.openWritingPipe()関数で送信先受信機のアドレス(先ほど設定した5文字の文字列)を設定します。

radio.openWritingPipe(address);

一方、受信側ではradio.openReadingPipe()関数で同じアドレスを設定し、2つのモジュール間の通信を有効にします。

radio.openReadingPipe(0, address);

次に、radio.setPALevel()関数でパワーアンプレベルを設定します。ここではモジュール同士が非常に近いため、最小に設定します。

radio.setPALevel(RF24_PA_MIN);

より高いレベルを使用する場合は、モジュールのGNDと3.3V間にバイパスコンデンサを入れ、動作中の電圧を安定させることを推奨します。

次に、radio.stopListening()関数でモジュールを送信モードに、受信側ではradio.startListening()関数で受信モードに設定します。

// 送信側で 
radio.stopListening();
// 受信側で 
radio.startListening();

loopセクションで、送信側では送信したいメッセージ「Hello World」を文字配列に代入し、radio.write()関数で受信側へ送信します。第1引数は送信したい変数です。

void loop() { 
  const char text[] = "Hello World"; 
  radio.write(&text, sizeof(text)); 
  delay(1000); 
}

変数名の前に「&」を付けることで、送信したいデータを格納する変数のアドレスを指定し、第2引数でその変数から何バイト取得するかを指定します。ここではsizeof()関数で文字列「text」の全バイト数を取得しています。最後に1秒の遅延を入れます。

radio.write()関数では、最大32バイトまで一度に送信可能です。

受信側では、loopセクションでradio.available()関数を使って受信データがあるか確認します。真であれば、まず32要素の配列「text」を作成し、受信データを格納します。

void loop() { 
  if (radio.available()) { 
    char text[32] = ""; 
    radio.read(&text, sizeof(text)); 
    Serial.println(text); 
  } 
}

radio.read()関数でデータを読み取り、「text」変数に格納します。最後にシリアルモニタに出力します。両方のプログラムをアップロードし、受信側でシリアルモニタを開くと、毎秒「Hello World」が表示されるのが確認できます。

トラブルシューティング

電源ノイズは、nRF24L01モジュールで通信を成功させようとする際に最もよく遭遇する問題の一つです。一般的に、RF回路や無線周波数信号は電源ノイズに敏感です。したがって、電源ラインにデカップリングコンデンサを入れるのが常に良いアイデアです。コンデンサは10µF〜100µF程度で構いません。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

もう一つのよくある問題は、Arduinoボードの3.3Vピンが、nRF24L01モジュールに十分な電力を供給できない場合があることです。外部電源でモジュールに給電するのも良い対策です。

2つのnRF24L01とArduinoによる双方向無線通信

2つ目の例、2台のArduinoボード間の双方向無線通信を見てみましょう。回路図は以下の通りです:

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

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

  • nRF24L01トランシーバーモジュール…………
  • Arduinoボード………………………………….
  • ジョイスティックモジュール………………………
  • サーボモーター……………………………………
  • プッシュボタン……………………………………
  • LED…………………………………………………

nRF24L01ソースコード

以下に2つのコードとその説明を示します。

送信側コード

/* 
 * Arduino無線通信チュートリアル 
 * 例2 - 送信側コード 
 * by Dejan Nedelkovski, www.HowToMechatronics.com 
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ 
 */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
#define led 12 
RF24 radio(7, 8); // CE, CSN 
const byte addresses[][6] = {"00001", "00002"}; 
boolean buttonState = 0; 
void setup() { 
  pinMode(12, OUTPUT); 
  radio.begin(); 
  radio.openWritingPipe(addresses[1]); // 00002 
  radio.openReadingPipe(1, addresses[0]); // 00001 
  radio.setPALevel(RF24_PA_MIN); 
} 
void loop() { 
  delay(5); 
  radio.stopListening(); 
  int potValue = analogRead(A0); 
  int angleValue = map(potValue, 0, 1023, 0, 180); 
  radio.write(&angleValue, sizeof(angleValue)); 
  delay(5); 
  radio.startListening(); 
  while (!radio.available()); 
  radio.read(&buttonState, sizeof(buttonState)); 
  if (buttonState == HIGH) { 
    digitalWrite(led, HIGH); 
  } else { 
    digitalWrite(led, LOW); 
  } 
}

受信側コード

/* 
 * Arduino無線通信チュートリアル 
 * 例2 - 受信側コード 
 * by Dejan Nedelkovski, www.HowToMechatronics.com 
 * Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ 
 */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
#include <Servo.h> 
#define button 4 
RF24 radio(7, 8); // CE, CSN 
const byte addresses[][6] = {"00001", "00002"}; 
Servo myServo; 
boolean buttonState = 0; 
void setup() { 
  pinMode(button, INPUT); 
  myServo.attach(5); 
  radio.begin(); 
  radio.openWritingPipe(addresses[0]); // 00001 
  radio.openReadingPipe(1, addresses[1]); // 00002 
  radio.setPALevel(RF24_PA_MIN); 
} 
void loop() { 
  delay(5); 
  radio.startListening(); 
  if (radio.available()) { 
    while (radio.available()) { 
      int angleV = 0; 
      radio.read(&angleV, sizeof(angleV)); 
      myServo.write(angleV); 
    } 
    delay(5); 
    radio.stopListening(); 
    buttonState = digitalRead(button); 
    radio.write(&buttonState, sizeof(buttonState)); 
  } 
}

前回の例と異なるのは、双方向通信のために2つのパイプ(アドレス)を作成する必要がある点です。

const byte addresses[][6] = {"00001", "00002"};

setupセクションで両方のパイプを定義し、1台目のArduinoの書き込みアドレスが2台目の読み込みアドレスになり、逆に1台目の読み込みアドレスが2台目の書き込みアドレスになることに注意してください。

// 送信側で 
radio.openWritingPipe(addresses[1]); // 00001 
radio.openReadingPipe(1, addresses[0]); // 00002
// 受信側で 
radio.openWritingPipe(addresses[0]); // 00002 
radio.openReadingPipe(1, addresses[1]); // 00001

loopセクションで、radio.stopListening()関数を使って1台目のArduinoを送信モードにし、ジョイスティックの値を0〜1023から0〜180にマッピングし、radio.write()関数でデータを受信側へ送信します。

radio.stopListening(); 
int potValue = analogRead(A0); 
int angleValue = map(potValue, 0, 1023, 0, 180); 
radio.write(&angleValue, sizeof(angleValue));

受信側では、radio.startListening()関数で2台目のArduinoを受信モードにし、データがあるか確認します。データがある間は読み取り、「angleV」変数に保存し、その値でサーボモーターを回転させます。

radio.startListening(); 
if (radio.available()) { 
  while (radio.available()) { 
    int angleV = 0; 
    radio.read(&angleV, sizeof(angleV)); 
    myServo.write(angleV); 
  }

次に、送信側で1台目のArduinoを受信モードにし、空の「while」ループで2台目からデータが送られるのを待ちます。これはプッシュボタンが押されているかどうかの状態データです。ボタンが押されていればLEDが点灯します。このプロセスが常に繰り返され、両Arduinoボードが継続的にデータを送受信します。

例3 – 単一パッケージで複数変数を送信

nRF24L01モジュールを使用したもう一つのコード例を見てみましょう。前回の例とすべて同じですが、データの構造化と送信方法が異なります。

送信側コード

/* Arduino無線通信チュートリアル 例1 - 送信側コード by Dejan Nedelkovski, www.HowToMechatronics.com Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
RF24 radio(7, 8); // CE, CSN 
const byte address[6] = "00001"; 
// この構造体の最大サイズは32バイト - nRF24L01バッファ制限 
struct Data_Package { 
  byte a = 0; 
  byte b = 125; 
  byte c = 255; 
  int d = 1024; 
  float e = 3.141592; 
  String f = "Test"; 
}; 
Data_Package data; // 上記構造体の変数を作成 
void setup() { 
  radio.begin(); 
  radio.openWritingPipe(address); 
  radio.setPALevel(RF24_PA_MIN); 
  radio.stopListening(); 
} 
void loop() { 
  // 構造体から受信側へデータ全体を送信 
  radio.write(&data, sizeof(Data_Package)); 
  delay(500); 
}

構造体(struct)を作成できます。これはさまざまな型の変数のコレクションです。

// この構造体の最大サイズは32バイト - nRF24L01バッファ制限 
struct Data_Package { 
  byte a = 0; 
  byte b = 125; 
  byte c = 255; 
  int d = 1024; 
  float e = 3.141592; 
  String f = "Test"; 
}; 
Data_Package data; // 上記構造体の変数を作成

この構造体データの最大サイズは32バイトであることに注意してください。ここではbyte型変数3つ、int型変数1つ(4バイト)、float型変数1つ(4バイト)、4文字のString(4バイト)を含めており、合計15バイトです。

受信側コード

/* Arduino無線通信チュートリアル 例1 - 受信側コード by Dejan Nedelkovski, www.HowToMechatronics.com Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */ 
#include <SPI.h> 
#include <nRF24L01.h> 
#include <RF24.h> 
RF24 radio(7, 8); // CE, CSN 
const byte address[6] = "00001"; 
// この構造体の最大サイズは32バイト - nRF24L01バッファ制限 
struct Data_Package { 
  byte a = 0; 
  byte b = 125; 
  byte c = 255; 
  int d = 1024; 
  float e = 3.141592; 
  String f = "Test"; 
}; 
Data_Package data; // 上記構造体の変数を作成 
void setup() { 
  Serial.begin(9600); 
  radio.begin(); 
  radio.openReadingPipe(0, address); 
  radio.setPALevel(RF24_PA_MIN); 
  radio.startListening(); 
} 
void loop() { 
  // 受信データがあるか確認 
  if (radio.available()) { 
    radio.read(&data, sizeof(Data_Package)); 
    // データ全体を読み取り、'data'構造体に格納 
  } 
  Serial.print("a: "); Serial.print(data.a); 
  Serial.print(" b: "); Serial.print(data.b); 
  Serial.print(" c: "); Serial.print(data.c); 
  Serial.print(" d: "); Serial.print(data.d); 
  Serial.print(" e: "); Serial.print(data.e); 
  Serial.print(" f: "); Serial.println(data.f); 
}

受信側でも同じ構造体を定義することで、受信データを正しく解釈できます。無線通信が正常に動作するかテストするため、各変数をシリアルモニタに出力しました。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

結論

nRF24L01モジュールは、Arduinoプロジェクトで無線通信が必要な際の優れた選択肢です。私はこのモジュールを多くのArduinoプロジェクトで使用してきました。

私がこれまでこのモジュールを使用したプロジェクトをすべてリストアップします。

  • Arduinoロボットカー無線制御:HC-05 Bluetooth、nRF24L01、HC-12トランシーバーモジュール使用
  • Arduino無線気象観測ステーションプロジェクト
  • DIY Arduino RC送信機
  • Arduinoアリ型ヘキサポッドロボット
  • DIY ArduinoベースRCホバークラフト
  • Arduinoメカナムホイールロボット
  • DIY Arduino RC受信機(RC模型・Arduinoプロジェクト用)
  • Arduino RC飛行機 | 100%自作

これらのプロジェクト/チュートリアルそれぞれに、nRF24L01モジュールの使用方法、回路図、通信改善のための改良コード実装などの詳細な説明があります。

私のお気に入りプロジェクトは、このカスタム設計のArduino RC送信機です。実際には14チャネルのRCコントローラーで、ほぼあらゆるArduinoプロジェクトの制御に使用できます。

nRF24L01をマスター:無線通信、Arduino連携、回路図・コード完全ガイド

このチュートリアルは以上です。お楽しみいただけたし、何か新しいことを学んでいただけたら幸いです。いつものように、ご質問があれば下のコメント欄でお気軽にお尋ねください。

製造プロセス

  1. OpenSensorsで空気質を測定: ArduinoとPythonによるガイド
  2. ArduinoでユニバーサルIRリモコンを自作:ステップバイステップガイド
  3. デジタル身長計の自作:Arduino Nanoとレーザー距離センサーで成長記録
  4. JX Wave Generator – Arduino互換DDS発振器(OLEDディスプレイ搭載)
  5. Arduino、Google Cardboard、Bluetoothで作るDIY VRスケートボード
  6. Arduino MegaとNEO-6M GPSモジュールの接続:ステップバイステップガイド
  7. サーミスタを使った温度測定: Arduinoステップバイステップガイド
  8. Arduinoで楽器演奏:音階生成のステップバイステップガイド
  9. ArduinoでModbusをマスターする:ステップバイステップガイド
  10. ArduRadio:Arduino自作FMラジオ付き目覚まし時計
  11. 脳・コンピューターインターフェース:思考を行動に再接続