電子工作を始めて色々作ってステップアップしていくと、『無線で操作できないかな・・・(#^.^#)』と妄想する場面がありませんか?
とはいえ・・・
- 無線ってちょっと難しそう・・・
- Bluetoothとかと何が違うかわからん
というように難易度高めという印象があるのではないでしょうか。
確かに回路設計からやっていくとなると非常に高度な知識が必要とされるのですが、無線通信モジュールと専用のライブラリを使用すれば比較的簡単に無線通信を行うことができます。
この記事では、5つのステップで無線通信モジュールの『nRF24L01』を使用した無線通信のやり方をご説明します。
[STEP 1] nRF24L01の概要

nRF24L01モジュールは、Nordic Semiconductor社製2.4GHz帯域用RFチップ(nRF24L01)を搭載した微弱無線送受信モジュールです。
モジュール化された製品はほとんどが中国製のものですが、製造元が違っても大体同じように使えます。
モジュールのピン配置は以下の通りです。

| ピン番号 | ピン名 | 内容 |
|---|---|---|
| 1 | GND | グラウンド(0V) |
| 2 | VCC | 電源(+1.9〜+3.6V) |
| 3 | CE | チップイネーブル (High: 5V、Low: 0V) |
| 4 | CSN | SPIチップセレクト (High: 5V、Low: 0V) |
| 5 | SCK | SPIクロック信号 (High: 5V、Low: 0V) |
| 6 | MOSI | マイコン→nRF24l01 データ通信 (High: 5V、Low: 0V) |
| 7 | MISO | nRF24l01→マイコン データ通信 (High: 5V、Low: 0V) |
| 8 | IRQ | 外部割り込み入力 (High: 5V、Low: 0V) |
nRF24l01が必要とする電流量(IVCC)は、出力する電波強度や通信速度によって変わりますが、20mA以上の入力が可能であれば問題なさそうです。
[STEP 2] 接続方法
Arduino Uno R4 WiFiと接続する場合を例にして説明します。

| Arduino Uno R4 WiFi | nRF24l01 |
|---|---|
| GND | GND |
| 3V3 | VCC |
| D9 (ピン番号:9) | CE |
| SSLA0 (ピン番号:10) | CSN |
| COPIA (ピン番号:11) | MOSI |
| CIPOA (ピン番号:12) | MISO |
| RSPCKA (ピン番号:13) | SCK |
| 未接続 | IRQ |
nRF24l01のVCCとGNDを電源供給先に繋ぎます。このとき、マイコンから20mA以上の電流供給ができるなら、マイコンの3.3V出力に繋いでもOKです。(もし足りない場合は、別途電源モジュールを用意して繋ぐようにしてください。)
そして、SCKはクロック信号なのでRSPCKAに、MISOはマイコン→nRF24l01へのデータ転送なのでCIPOAに、MOSIはnRF24l01→マイコンへのデータ転送なのでCOPIAに、CSNはチップセレクト信号なのでSSLA0に、CEはイネーブル信号でありポート出力ができるピンならどこでもよいのでD9に接続します。
なお、割り込み入力のIRQは特に使用しないので、未接続状態にしておきます。
[STEP 3] 通信仕様
| 動作周波数帯 | 2.4GHz ISMバンド |
| 伝送速度 | 最大2Mbps |
| 通信距離 | 100m(屋外平地) |
| 変調方式 | GFSK |
| インターフェース | 4線式SPIインターフェース |
| 伝送速度 | 最大8Mbps |
| バッファ | データ送信用:32Byte FIFO(3本) データ受信用:32Byte FIFO(3本) |
[STEP 4] プログラミング
Arduinoで使えるnRF24l01用のライブラリとして『RF24』をインストールします。
1 | RF24 m_NRFRadio( 9/* CE */, 10/* CSN */ ); |
1 2 3 4 5 6 7 | if ( m_NRFRadio.begin( ) == 0 ) { Serial.println( F( "radio hardware is not responding!!" ) ); while ( true ) { delay( 0 ); } } |
SPI通信が開始できないようであれば「radio hardware is not responding!!」というメッセージを表示して無限ループに入るようにします。
1 | m_NRFRadio.setPALevel( RF24_PA_LOW ); |
電波強度を低に設定しています。
1 | m_NRFRadio.setRetries( 15/* delay */, 15/* times */ ); |
250us×15=4000us(4ms)間隔で、最大15回送信リトライを行うよう設定しています。
1 2 | uint8_t address[6] = "MtoS"; m_NRFRadio.openWritingPipe( address ); |
5Byte以下の任意のアドレスでパイプを開きます。
1 2 | uint8_t address[6] = "MtoS"; m_NRFRadio.openReadingPipe( 1, address); |
1番パイプを任意のアドレスで開きます。
片方向だけの通信であれば0番パイプを使用してもよいですが、双方向通信をする場合はパイプを分けておくことをおすすめします。ここでは読み取り用パイプを1番にしています。
0番パイプは書き込み(送信)に使用するようなので、読み取り(受信)にも0番パイプを使っちゃうとwrite()を実行する前にいちいちopenWritingPipe()を呼び出す必要があったりと煩雑なようです。
1 2 3 4 5 6 7 8 9 10 | int8_t message[ 16 ] = "Button pushed!!"; m_NRFRadio.stopListening( ); bool report = m_NRFRadio.write( message, sizeof( message) ); if ( report ) { Serial.println( F( "Transmission successful! " ) ); } |
write()でmessageの文字列を送信します。
また、片方向だけの通信であれば本来stopListening()は不要ですが、双方向通信では必要なので一応クセ付けのため呼び出しています。
1 2 3 4 5 6 7 8 9 | int8_t message[ 16 ] = ""; m_NRFRadio.startListening( ); while ( m_NRFRadio.available( ) ) { m_NRFRadio.read( message, sizeof( message ) ); Serial.println( message ); } |
startListening()でリッスンを開始して、available()で読み取り可能なバイトがあるかを確認し、もしあればread()でバイトを読み取ります。
[STEP 5] 動作確認
2台のArduinoを用意し、それぞれを送信機・受信機としてテキストを無線転送するプログラムを作ってみます。


STEP2の接続方法にしたがって2台のArduinoをそれぞれnRF24l01に接続します。
送信側にはボタンを付け、ボタンを押したら送信側から受信側に「Button pushed!」という文字列を送るように設計します。
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 38 39 40 | #include <RF24.h> #include <RF24_config.h> #include <nRF24L01.h> #include <printf.h> static RF24 m_NRFRadio(9, 10); static uint8_t m_Address[6] = "MtoS"; void setup() { Serial.begin(115200); pinMode(D7, INPUT_PULLUP); delay(500); if (m_NRFRadio.begin() == 0) { Serial.println(F( "radio hardware is not responding!!" )); while(true) { delay(0); } } else { delay(1000); Serial.println(F("nRF24L01 online.")); } m_NRFRadio.setPALevel( RF24_PA_LOW ); m_NRFRadio.setRetries( 15, 15 ); m_NRFRadio.openWritingPipe( m_Address ); } void loop() { bool report; char message[16] = "Button pushed!"; if (digitalRead(D7) == LOW) { report = m_NRFRadio.write( message, sizeof(message) ); if ( report ) { Serial.println( F( "Transmission successful! " ) ); } delay(500); } } |
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 | #include <RF24.h> #include <RF24_config.h> #include <nRF24L01.h> #include <printf.h> static RF24 m_NRFRadio(9, 10); static uint8_t m_Address[6] = "MtoS"; void setup() { Serial.begin(115200); delay(500); if (m_NRFRadio.begin() == 0) { Serial.println(F( "radio hardware is not responding!!" )); while(true) { delay(0); } } else { Serial.println(F("nRF24L01 online.")); } m_NRFRadio.setPALevel( RF24_PA_LOW ); m_NRFRadio.openReadingPipe( 1, m_Address ); } void loop() { char message[16] = ""; m_NRFRadio.startListening( ); while ( m_NRFRadio.available( ) ) { m_NRFRadio.read( message, sizeof(message) ); Serial.println(message); } } |
送信するデータをJSON形式にすればオブジェクトデータの形で送信することもできるので、活用方法はもっと広がりそうです。

みなさんも是非nRF24l01で通信を無線化して楽しんでみてください。






