RaspberryとArduinoの無線通信

nRF24L01(その1)

nRF24L01モジュールを使ってRaspberryとArduinoの無線通信が動きましたので紹介します。

nRF24L01モジュールは技術基準適合証明等のマーク(通称技適マーク)が交付されていませんので
これ以降の記事は、あくまでも実験レベルと考えてください。

【Raspberry側】

必要なライブラリをダウンロード、インストールします。
デフォルトではBCM2835 driveを使いますので、/dev/spidevが無くても動きます。
以前はこちらでライブラリが公開されて いましたが、メンテナーが変わってこちらで公開され ています。
$ git clone https://github.com/nRF24/RF24

$ cd RF24

$ ./configure
[SECTION] Detecting arm compilation environment.
  [OK] arm-linux-gnueabihf-gcc detected.
  [OK] arm-linux-gnueabihf-g++ detected.
[SECTION] Detecting target machine.
./configure: line 66: warning: command substitution: ignored null byte in input
[OK] machine detected: SoC=BCM2835, Type=RPi, CPU=armv7l.
[SECTION] Detecting DRIVER
  [OK] DRIVER detected:RPi.
[SECTION] Detecting OS.
  [INFO] OS detected:LINUX.
[SECTION] Preparing configuration.
[SECTION] Saving configuration.
[SECTION] Cleaning previous builds.
[OK] Finished.

$ make

$ sudo make install

$ cd examples_linux

$ make

nRF24L01とRaspberryの接続は以下の通りです。
nRF24L01 Raspberry
VCC 3.3V
GND GND
MISO Pin#21
MOSI Pin#19
SCK Pin#23
CE Pin#15(*1)
CSN Pin#24(*2)
IRQ N/C


<*1>
CEピンを変更する場合、以下の1番目の引数を変更します。
指定するのはGPIO番号です。
RF24 radio(22, 0);

<*2>
CSNピンをCE1(Pin#26)に変更する場合、以下の様に指定します
RF24 radio(22, 1);

<*3>
RPI_V2_GPIO_P1_XXはマクロ定義で、ピン位置に対応するGPIO番号を戻します。
ソース中に以下のコメントが有りますが、間違っています。
Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
正しくは
Setup for GPIO 25 CE and CE0 CSN with SPI Speed @ 4Mhz
です。


RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0,BCM2835_SPI_SPEED_8MHZ);

RF24 radio(RPI_BPLUS_GPIO_J8_22,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
または
RF24 radio(25, 0);
と同じです。

GPIO22を使うときは以下のコードとなります。
RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0,BCM2835_SPI_SPEED_4MHZ);


モジュールを接続してgettingstartedを実行すると以下の表示となります。


正しそうですが、送信用アドレス、受信用アドレスが正しく表示されません。
1を入力するとエラーになりますが、これで初期値が設定されます。

ソースを見ると分かりますが、radio.printDetails()の後で、radio.openWritingPipe() と radio.openReadingPipe()が呼ばれています。
従って、初めて起動したときはアドレスは設定されていません。
プログラムを一旦止めて、プログラムを再実行すると、今度は正しく送信用アドレス、受信用アドレスが表示されます。
nRF24L01モジュールは前回の設定値を覚えているので、2回目以降に実行したときは前回の設定値を表示します。


ここで0を入力して受信モードを開始します。

【Arduino側】

前回紹介したこちらのライブラリとGettingStarted のサンプルを使用します。
nRF24L01とArduinoの接続は以下の通りです。
nRF24L01 Arduino
VCC 3.3V(注意)
GND GND
MISO D12
MOSI D11
SCK D13
CE D8
CSN D7
IRQ N/C

(注意)
Arduinoの互換機では3.3V出力の電流容量が正規品よりも小さいみたいで、
3.3Vを直接ボードから供給すると正しく動かないことがあります。
Arduinoの3.3V出力の電流容量についてはこ ちらに詳しく紹介されていますが
メーカやバージョンによってボードに実装されているレギュレータが違うみたいです。
ボードに実装されているレギュレータはとても小さな部品で、マーキングを読み取ることが困難なので、
外部レギュレータを使って5V→3.3Vに変換し、nRF24L01に供給したほうが確実に動作します。
レギュレータはAMS1117(最 大1000mA)の様に、できるだけ電流容量の大きなもののほうが安心ですが、
RF24L01はそれほど電気を食わないので、LP-2950(最大 100mA) でも動きます。

Arduinoのスケッチをビルドすると、シリアルモニターに以下が表示されます。


Tの文字を入力して送信モードに切り替えると、送信を開始します。


Raspberry側は受信データを表示します。


Raspberry側のプログラムを止めると、きちんと送信失敗を検出します。


Raspberry側のプログラムを再起動すると再び送信を始めます。




向きを逆にしてRaspberryを送信、Arduinoを受信にしてみましたが、問題なく動きます。




こちら
にBuild Optionsが公開されています。
デフォルトではBCM2835 driveを使いますが、標準のSPIデバイス(/dev/spidev)を使うこともできそうです。
そこで、raspi-configを使ってSPIデバイスを有効にし、SPIDEVのオプションでビルドしてみました。
$ ./configure --driver=SPIDEV
[SECTION] Detecting arm compilation environment.
  [OK] arm-linux-gnueabihf-gcc detected.
  [OK] arm-linux-gnueabihf-g++ detected.
[SECTION] Detecting target machine.
./configure: line 66: warning: command substitution: ignored null byte in input
[OK] machine detected: SoC=BCM2835, Type=RPi, CPU=armv7l.
[SECTION] Detecting OS.
  [INFO] OS detected:LINUX.
[SECTION] Preparing configuration.
[SECTION] Saving configuration.
[SECTION] Cleaning previous builds.
[OK] Finished.

$ make

$ sudo make install

$ cd examples_linux

$ rm gettingstarted

$ make

/dev/spidev0.0を8MHzで初期化していることを確認しましたが、正しく情報が取れません。
gpio操作は/sys/class/gpioデバイスを直接Read/Writeしています。
これ以上の追及はやめました。




nRF24L01はレジスターに送信モードと受信モードを持っている一方向通信を前提とした設計です。、
Enhanced ShockBurst機能を使って、受信側にデータが届いたかどうかを送信側で判定することができます。
このライブラリはレジスターの切り替えをうまく行うことで、送信モードと受信モードを動的に切り替えています。

続く...