RaspberryとArduinoの無線通信(nRF24L01 その8)

今まで色々試してきましたが、全てRaspberry側がサーバー、Arduino側がクライアントの動作ばかりでした。






そこで、今回はRaspberry側がクライアント、Arduino側がサーバの動作を紹介します。



Raspberryはアナログ入力が無いので、Arduinoを無線アナログサーバにすることができます。

【Arduino側】

Arduino側のスケッチは以下の通りです。
クライアントから受信したデータを+1して応答する簡単なものです。
/*
 * nRF24L01 Receive And Send Demo for ATmega
 *
 * VCC  3.3V
 * MISO 12
 * MOSI 11
 * SCK  13
 * CE   14
 * CSN  10
 */
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(8,7);

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xE0E0E0E0E0LL, 0xE0E0E0E0E1LL };

void setup(void)
{
  Serial.begin(9600);
  Serial.println("nRF24L01 Receive And Send Demo");
  printf_begin();

  //
  // Setup and configure rf radio
  //
  radio.begin();
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1,pipes[1]);
  radio.startListening();
  radio.printDetails();
}

void loop(void)
{
  uint8_t rdata[32];
  uint8_t sdata[32];

  // if there is data ready
  if ( radio.available() )
  {
    // Fetch the payload, and see if this was the last one.
    radio.read( rdata, sizeof(rdata) );

    // Spew it
    sdata[0]=rdata[0]+1;
    Serial.print("rdata=");
    Serial.print(rdata[0]);
    Serial.print("-->sdata=");
    Serial.println(sdata[0]);
    radio.stopListening();
    radio.write( &sdata, sizeof(sdata) );
    radio.startListening();   
  } // end if
}


【Raspberry側】

Raspberry側のコード(SendSimple.cpp)は以下の通りです。
Arduinoの場合、radio.write()の戻り値で送信成功したかどうか判断できましたが、
Raspberryの場合、相手が動いていなくても常に「0」が戻ってきました。
そこで、相手からの応答を待って、応答が無いときは再送信しています。

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <climits>
#include <RF24/RF24.h>


using namespace std;
//
// Hardware configuration
//

// CE Pin, CSN Pin, SPI Speed

// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS1, BCM2835_SPI_SPEED_4MHZ);

// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);

// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xE0E0E0E0E0LL, 0xE0E0E0E0E1LL };

#define RETRY    10
#define DEBUG    1

int RadioAvailable() {
  int i;
  for (i=0;i<RETRY;i++) {
    if (radio.available()) return 1;
if(DEBUG)printf("Waiting..\n");
    sleep(1);
  }
  return 0;
}

int main(int argc, char** argv){
  uint8_t sdata[32];
  uint8_t rdata[32];
  int loop,loopMax;
  int ret;

  loopMax=INT_MAX;
  if (argc == 2) loopMax=1;

  radio.begin();                           // Setup and configure rf radio
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(0,pipes[0]);
  radio.printDetails();
if(DEBUG)radio.startListening();


  // forever loop
  for(loop=0;loop<loopMax;loop++) {
    sdata[0]=loop;
    bool ok = false;
    while(!ok) {
      radio.stopListening();
      ret=radio.write( sdata, sizeof(sdata) );
      printf("radio.write ret=%d sdata=%d\n",ret,sdata[0]);

// Now, continue listening
      radio.startListening();
      if ( RadioAvailable() ) break;
    } // end while

    radio.read( &rdata, sizeof(rdata) );
    printf("rdata=%d\n",rdata[0]);
    sleep(1);
  } // end while
}

次にexamplesディレクトリにあるMakefileの「PROGRAMS =」の行に「SendSimple」を追加してMakeします。
実行すると以下の表示となります。
「Waiting」が1回は表示されますので、すぐには応答が戻ってこないようです。



時々、以下のようにArduinoからの応答の受信に失敗することがあります。



Arduino側のnRF24L01のGNDと3.3Vの間に100μFのバイパスコンデンサーを入れてみましたが、
改善しませんでした。

今までArduino側はATmega(UNO/Nano/ProMini)を使ってきましたが、このページを見て ATtiny84/85でも動くことが分かりました。
早速試してみました