RaspberryとArduinoの無線通信(nRF24L01+ATtiny84)

今までArduino側はATmega(UNO/Nano/ProMini)を使ってきました。
このページを見て ATtiny84/85でも動くことが分かりましたので、ATtin84を使って早速試してみます。
「Software Driven SPI」に切り替えていた場合は、オリジナルの「Hardware Driven SPI」に戻します。

ATtiny84とnRF24L01の結線はこのページを参考に以下の様に なります。
ATtiny84への供給電圧は5Vです。
nRF24L01モジュールのVCCは3.3Vなので、 5V→3.3Vのレギュレータを使って3.3Vを供給しています。
またレギュレータのGNDと3.3V出力(オレンジのライン)の間に、100μF(程度)のバイパスコンデンサーをかましています。
バイパスコンデンサーがないと正しく動きませんでした。




最初はRaspberry側がサーバ、Tiny側がクライアントの確認です。
Raspberry側のプログラムはこちらで紹介しているものを使いました。

ATtiny84側のスケッチは以下の様になります。
今までのスケッチとは少し変えています。
というのはATtiny84の場合、radio.write()での戻り値が常に「0(送信失敗)」で戻ってきます。
スケッチの書き込みでは、こちらで紹介している FemtoCowのアドオンでなければ動きません。(理由はこちら

/*
 * nRF24L01 Sample Program for ATtiny84/85
 * Build with FemtoCow AddOn
 *
 * for ATtiny84
 * VCC  3.3V
 * MISO PA6(D4 Pin#7)
 * MOSI PA5(D5 Pin#8)
 * SCK  PA4(D6 Pin#9)
 * CE   PA2(D8 Pin#11)
 * CSN  PA3(D7 Pin#10)
 *
 * for ATtiny85
 * VCC  3.3V
 * MISO PB0(D0 Pin#5)
 * MOSI PB1(D1 Pin#6)
 * SCK  PB2(D2 Pin#7)
 * CE   PB3(D3 Pin#2)
 * CSN  PB4(D4 Pin#3)
 */
//#include <SPI.h>
//#include "nRF24L01.h"

#include "RF24.h"
#include "printf.h"

// Set up nRF24L01 radio on SPI bus plus pins
#if defined(__AVR_ATtiny84__)
  RF24 radio(8,7);
#elif defined(__AVR_ATtiny85__)
  RF24 radio(3,4);
#endif

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

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

void loop(void)
{
  static int value = 0;
  uint8_t sdata[32];

  // Take the time, and send it.  This will block until complete
  sdata[0]=value;
  value++;

#if 1
  radio.write( sdata, sizeof(sdata) );
#else
  bool ok = false;
  while(!ok) {
    ok = radio.write( data, sizeof(data) );
    if (ok)
      Serial.println("ok...");
    else
      Serial.println("failed.");
  }
#endif
  delay(1000);

}


スケッチを書き込むとATmegaと同じように動きますが、radio.write()での戻り値をまったく判定していないので、
本当に相手にデータが届いたのかどうか、信頼性はゼロです。
また、D3(PA7)は制御不能になります。
これはRF24ライブラリの中で以下のように、D3(PA7)をSSピン(Slave Select)として使っているためです。

#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
// these depend on the core used (check pins_arduino.h)
// this is for jeelabs' one (based on google-code core)
#    define DI   4   // PA6
#    define DO   5   // PA5
#    define USCK 6   // PA4
#    define SS   3   // PA7

Raspberry側で確認すると一応受信しています。



そこで、スケッチを変更してRaspberry側からの応答を待つようにしてみました。
Raspberry側のプログラムはこちらで紹介しているものを使いました。

Raspberryからの応答データが正しく受信できているかどうか確認するために、
受信したデータを次の送信データとしています。
Tiny ---0--> Raspberry
Tiny <--1--- Raspberry(受信したデータを+1して応答)
Tiny -->1--> Raspberry
Tiny <--2--- Raspberry(受信したデータを+1して応答)
ATtiny84側のスケッチは以下の様になります。

/*
 * nRF24L01 Sample Program for ATtiny84/85
 * Build with FemtoCow AddOn
 *
 * for ATtiny84
 * VCC  3.3V
 * MISO PA6(D4 Pin#7)
 * MOSI PA5(D5 Pin#8)
 * SCK  PA4(D6 Pin#9)
 * CE   PA2(D8 Pin#11)
 * CSN  PA3(D7 Pin#10)
 *
 * for ATtiny85
 * VCC  3.3V
 * MISO PB0(D0 Pin#5)
 * MOSI PB1(D1 Pin#6)
 * SCK  PB2(D2 Pin#7)
 * CE   PB3(D3 Pin#2)
 * CSN  PB4(D4 Pin#3)
 */
//#include <SPI.h>
//#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// Set up nRF24L01 radio on SPI bus plus pins
#if defined(__AVR_ATtiny84__)
  RF24 radio(8,7);
#elif defined(__AVR_ATtiny85__)
  RF24 radio(3,4);
#endif

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

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

void loop(void)
{
  static int value = 0;
  uint8_t sdata[32];
  uint8_t rdata[32];

  // Take the time, and send it.  This will block until complete
  sdata[0]=value;

#if 1
  radio.write( sdata, sizeof(sdata) );
#else
  bool ok = false;
  while(!ok) {
    ok = radio.write( data, sizeof(data) );
    if (ok)
      Serial.println("ok...");
    else
      Serial.println("failed.");
  }
#endif

  // Now, continue listening
  radio.startListening();
  while ( ! radio.available() ) {
  }
  radio.read( &rdata, sizeof(rdata) );
  radio.stopListening();

  value=rdata[0]; // Next send data
  delay(1000);

}


Raspberry側で確認すると、受信データが増えていますので、ATtiny側も正しく受け取れているようです。




次にRaspberry側がクライアント、Tiny側がサーバーの確認です。
Raspberry側のプログラムはこちらで紹介しているものを使いました。
ATtiny84側のスケッチは以下の様になります。
クライアント側から受け取ったデータを+1して送り返す簡単なものです。

/*
 * nRF24L01 Receive And Send for ATtiny84/85
 * Build with FemtoCow AddOn
 *
 * for ATtiny84
 * VCC  3.3V
 * MISO PA6(D4 Pin#7)
 * MOSI PA5(D5 Pin#8)
 * SCK  PA4(D6 Pin#9)
 * CE   PA2(D8 Pin#11)
 * CSN  PA3(D7 Pin#10)
 *
 * for ATtiny85
 * VCC  3.3V
 * MISO PB0(D0 Pin#5)
 * MOSI PB1(D1 Pin#6)
 * SCK  PB2(D2 Pin#7)
 * CE   PB3(D3 Pin#2)
 * CSN  PB4(D4 Pin#3)
 */
//#include <SPI.h>
//#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// Set up nRF24L01 radio on SPI bus plus pins
#if defined(__AVR_ATtiny84__)
  RF24 radio(8,7);
#elif defined(__AVR_ATtiny85__)
  RF24 radio(3,4);
#endif

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

void setup(void)
{
  //
  // 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;
    radio.stopListening();
    radio.write( &sdata, sizeof(sdata) );
    radio.startListening();   
  } // end if
}


Raspberry側で確認しましたが、送信データが+1されて戻ってきています。



ATtiny4313でも動くようなので試してみました。

続く...