nRF24L01モジュールで無線通信

電子工作で無線通信をするならXBeeが有名です。
技適も通ってますしトランスペアレントモードなどで簡単に通信ができます。
しかしXBeeは高いので、組み込みにはためらってしまいます。
1つ約2000円でそれを2つなので4000円にもなりますからね。

スポンサーリンク

そこで取って代わるのがnRF24L01という無線モジュールです。
このモジュールは安いところでは1つ100円ぐらいととても安価です。
このnRF24L01を使ってArduinoで無線通信をしてみたいと思います。

用意するもの

  • nRF24L01 モジュール ×2
  • Arduino(互換品でも何でもいいです)×2
  • Arduinoの開発環境
  • その他(ブレッドボード、LED、スイッチなど)

nRF24L01のモジュールは国内で有名どころだとAitendoで売っています。

Amazonでも一応売ってました。

私は安ければ品質は気にしない性格ですのでAliexpressで買いました。
中国から輸入するので時間はかかりますがかなり安いです。
私は10個セットで約10ドルのものを買いました、1つ当たり約100円でかなり安いです。
ちなみに、届いた時はほとんどのモジュールのピンヘッダが曲がってましたよ(´・ω・`)

モジュールに搭載しているICにはnRF24L01とnRF24L01+がありますが”+”のが機能的に色々と向上しているみたいです。
下位互換はあるみたいなのでどっちでもいいのかなと思います、たぶん。

このモジュールは1対1の双方向通信しかできないらしいです。
スター型の1対nや、メッシュ型などは無理だと思われます。
そういう通信はXBeeなどに任せましょう。

Arduinoのスケッチ

今回はArduino公式に載っているライブラリを使って通信します。

とりあえず上記URLよりMirfライブラリをダウンロードしてArduino IDEで使えるようにします。

nRF24L01は双方向通信が可能ですがここでは単方向の通信を紹介します。
とは言うものの双方向にするのも簡単ですのですぐにわかると思います。
電子工作で双方向通信ってする機会が案外無いんですよね・・・

今回のスケッチはサーバー側でスイッチを押して、クライアント側のLEDを付けるというものです。

サーバー側

サンプルスケッチのping_server.inoを少し編集しました。

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

const int buttonPin = 2;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"serv1");
  Mirf.payload = sizeof(unsigned long);
  Mirf.config();
  Serial.println("Listening...");
}

void loop() {
  const byte buttonOpen = 10;
  const byte buttonClose = 20;
  byte sendData[Mirf.payload]; // 最大32bit, byteの行列なので要素数は4

  if (!Mirf.isSending() && Mirf.dataReady()) {
    Serial.println("Got packet");
    Mirf.getData(sendData);  // 適当な信号を受信
    Mirf.setTADDR((byte *)"clie1");
    int val = digitalRead(buttonPin);
    if (val == HIGH) {  // スイッチを押さなければ"10"を送信
      sendData[0] = buttonOpen;
    } else {            // スイッチを押せば"20"を送信
      sendData[0] = buttonClose;
    }
    Mirf.send(sendData);
    Serial.println("Reply sent.");
  }
}

クライアント側

こちらもping_client.inoを少し編集したものです。

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

const int ledPin = 2;

void setup(){
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"clie1");
  Mirf.payload = sizeof(unsigned long);
  Mirf.config();
  Serial.println("Beginning ... ");
}

void loop(){
  const byte buttonOpen = 10;
  const byte buttonClose = 20;
  unsigned long time = millis();
  byte recvData[Mirf.payload];  // 最大32bit, byteの行列なので要素数は4

  Mirf.setTADDR((byte *)"serv1");
  Mirf.send(recvData);  // 適当な信号を送信
  while(Mirf.isSending()) {
  }
  while (!Mirf.dataReady()) {
    if ((millis() - time) > 1000 ) {
      Serial.println("Timeout on response from server!");
      return;
    }
  }
  Mirf.getData(recvData);
  if (recvData[0] == buttonOpen) {  // スイッチを押していない情報であれば
    digitalWrite(ledPin, LOW);
  } else {                          // スイッチを押した情報であれば
    digitalWrite(ledPin, HIGH);
  }
  Serial.print("recvData: ");
  for (int i = 0;i < Mirf.payload;i++) {
    Serial.print(recvData[i]);
    Serial.print(" ");
  }
  Serial.println();
  delay(100);
}

回路

送受信どちらとも次の表のように接続します。
nRF24L01の電源電圧は1.9~3.6Vですので注意しましょう。
じゃあ5Vの信号線はどうなんだってことになりますけど、入力ピンは5Vトレラントらしいので安心です。

nRF24L01
Module
Arduino
VCC 3.3V
MISO 12
MOSI 11
SCK 13
CE 8 (default)
CSN 7 (default)
GND GND
IRQ 未接続

あとは送信側のスイッチと受信側のLEDです。 送信側のスイッチはプログラムから見て分かる通りプルアップしていますので、もう片方はGNDにつなぎます。

送信側 Arduino
スイッチ 2
受信側 Arduino
LED 2

配線はこのようになります。
ちなみにLEDは抵抗内蔵ですので、この写真には抵抗が写っていません。
無線通信モジュールとArduino
このモジュールは2列のピンヘッダですので、いつか作ったブレッドボードアダプタでブレッドボードにつなげています。

Arduinoを使った無線通信

送受信の状態をどちらも同時に確認するにはシリアルポートを2つ同時に開く必要があります。
ですので、一方はArduino IDEについているシリアルポート、他方をTera Termなどのターミナルエミュレータを使うか、別でパソコンを用意します。
今回はデータがスイッチのHIGHかLOWですのでシリアルモニターを使わなくても大丈夫です。

とりあえずスイッチを押してみましょう。
LEDが付けば無線通信が成功しています。

今回はスイッチのHIGHとLOWを”10″と”20″という適当な値で送りましたが、一度に伝送できるのは32bitですので余裕でADCで読み込んだ値(10bit)もそのまま送ることができます。
上記のスケッチでは配列ですが、もちろん普通の変数でも可能です。
32bitも無線で送ることはなかなかないので8bitで何個かに分けて送ればいいかなと思ったので配列なだけです。
送る時はだいたい最小限に収めてから送りますしね。

また、サーバー側は送信のみ、クライント側は受信のみのスケッチでしたがどちらも送受信しています。
これは送信、または受信のみにするとデータが得られなかったりするからです。
なぜかは知りません・・・

最大通信距離は遮蔽物無しでだいたい20mぐらい?
ブースターを付ければ1kmに達しますが、電力が余裕で許容範囲を越える気がするので違反です。
これだけ離れても使えるので個人利用では十分でしょう。

無線通信モジュールについて

ノルディック社のnRF24L01は2.4GHz帯を使って通信を行っています。
この2.4GHz帯は免許不要で自由に利用できます。
と言いたいところですが、日本の電波法では免許と登録なしで使えるのは微弱無線(2.4GHz帯の場合3mで35uV/m以下)の場合だけです。
それ以上の出力となると特定小電力無線局扱いとなって、技術基準適合証明いわゆる技適の取得もしくは、自分で無線局として開局をするしかありません。

特定小電力無線局に該当する場合、空中線電力が1W以下で・・・
と3項目ぐらいの条件があり、これを満たし技適マークがついていればセーフです。
しかしnRF24L01のモジュールはXBeeなどと違い技適を取っていませんので、技適マークはもちろんありません。
それでもこれが微弱無線であればまったく問題ありません。

特定小電力無線局に該当したとして、私が買ったモジュールの最大送信電力は0dBmつまり1mWでなわけで、大丈夫そうですが・・・
技適マークがついてないので認められるはずもありません。

個人利用それも実験レベルであれば問題ないレベルだとは思いますがグレーな感じはします。
不安であれば技適を取得しているXBeeやTWE-Liteを使いましょう。

スポンサーリンク

Leave a Comment