Arduino DUE + nRF24L01

dardik
Offline
Зарегистрирован: 09.03.2013

Здравствуйте. Сделал беспроводной датчик температуры и влажности на основе DHT22, Arduino Mini PRO и nRF24L01 (передатчик). Сделал приемник на основе Arduino Mini PRO и nRF24L01 (приемник). Данные температуры и влажности передаются без ошибок, все хорошо. Подсоединил nRF24L01 к Arduino DUE и сделал его как приемник. Данные получает, но не верные! То есть Arduino Mini PRO передает данные на Arduino DUE с ошибками, а Arduino Mini PRO на Arduino Mini PRO - без ошибок. Код не менял. Может кто знает в чем дело?

Код приемника: (Arduino DUE)

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

typedef struct {
  int W;
  int X;
  int Y;
  int Z;
}
B_t;
B_t duino2;

RF24 radio(9, 10);  //RF24 radio(uint8_t _cepin, uint8_t _cspin); для DUE
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

void setup()
{
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1, pipes[0]);
  radio.startListening();
}

void loop(void)
{
  //Serial.println("Begining.");
  if ( radio.available() )
  {
    bool done = false;
    while (!done)
    {
      done = radio.read( &duino2, sizeof(duino2) );

      Serial.print("Controller = ");
      Serial.println(duino2.W);
      Serial.print("T= ");
      Serial.println(duino2.X);
      Serial.print("H = ");
      Serial.println(duino2.Y);
      Serial.print("DP = ");
      Serial.println(duino2.Z);
    }
  }

}

Код передатчика: (Arduino Mini PRO)

#include <SPI.h>
#include "RF24.h"
#include <avr/sleep.h>
#include <avr/wdt.h>


//int battVolts;
int count;    //переменная для счётчика циклов
int h = 0; //влажность
int t = 0; //температура
int dp = 0; //точка росы
volatile boolean wdt_tripped = 1;

RF24 radio(9, 10);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };


#include <dht22.h>
dht22 DHT22;

//создаём структуру для передачи 4х значений
typedef struct {
  int W;
  int X;
  int Y;
  int Z;
}
B_t;
B_t duino2;


//режим сна для МК
void system_sleep() {
  delay(2);                            // Wait for serial traffic
  _SFR_BYTE(ADCSRA) &= ~_BV(ADEN);     // Switch ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();                        // System sleeps here
  sleep_disable();
  _SFR_BYTE(ADCSRA) |= _BV(ADEN);      // Switch ADC on
}
void wdt_interrupt_mode() {
  wdt_reset();
  WDTCSR |= _BV(WDIE); // Restore WDT interrupt mode
}
ISR(WDT_vect) {
  wdt_tripped = 1; // set global volatile variable
}


void setup()
{
  pinMode(5, OUTPUT); //Пин на который подключено питание DHT22
  digitalWrite(5, HIGH);
  DHT22.attach(2); //Инициализируем датчик DHT
  Serial.begin(9600);
  wdt_disable();
  wdt_reset();
  wdt_enable(WDTO_8S);   //пробуждение каждые 8 сек
  count = 0;
  radio.begin();
  radio.setRetries(15, 15); // Кол-во попыток и время между попытками
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1, pipes[1]);
}

void loop(void)
{
  //тут можно увеличить интервал времени между отправками данных по RF24 за счёт счётчика циклов
  Serial.println("Wakeup duino");
  wdt_interrupt_mode();
  if (wdt_tripped) {
    count++;
    wdt_tripped = 0;
    Serial.print("Run mine module #");
    Serial.println(count);
    if (count == 9) { // каждые 8 сек * 9 циклов = 72 секунды делаем измерения и отправляем на базу:
      Serial.println("Reding sensor DHT");
      int chk = DHT22.read();
      h = int(floor(DHT22.humidity + 0.5)); //Влажность
      t = int(floor(DHT22.temperature + 0.5)); //Температура
      dp = int(floor(DHT22.dewPoint() + 0.5)); //Точка росы
      //записываем в структуру данные для передачи
      if (isnan(t) || isnan(h)) {
        duino2.W = 1;  // этот номер передатчика для идентификации в принятом пакете данных
        duino2.X = 0;
        duino2.Y = 0;
        duino2.Z = 0;
      }
      else {
        duino2.W = 1;  // этот номер передатчика для идентификации в принятом пакете данных
        duino2.X = t;  // передаём температуру
        duino2.Y = h;   // передаем влажность
        duino2.Z = dp;   // передаем точку росы
      }

      Serial.print("Controller = ");
      Serial.println(duino2.W);
      Serial.print("Battery voltage= ");
      Serial.println(duino2.X);
      Serial.print("Temperature = ");
      Serial.println(duino2.Y);
      Serial.print("Humidity = ");
      Serial.println(duino2.Z);

      radio.powerUp();  //подаём питание на NRF24
      radio.stopListening(); // отключаем режим приёма
      Serial.println("Start send");
      bool ok = radio.write( &duino2, sizeof(duino2) ); //отправляем данные по RF24
      Serial.println("End send");
      delay(20);
      count = 0;
      radio.powerDown(); //отключаем питание RF24 штатно
    }
  }
  system_sleep();   //МК засыпает
}

 

 

 

dardik
Offline
Зарегистрирован: 09.03.2013

Приведу еще пример, как неправильно показывает значения:

Controller = 1572865
T= 524324
H = 0
DP = 0
 

А должно быть к примеру:

Controller = 1
T= 24
H = 36
DP = 8
 

maksim
Offline
Зарегистрирован: 12.02.2012

В том что Mini PRO имеет 8-ми битное ядро, а DUE 32-битное.

http://arduino.cc/en/Reference/Int

И ваши переданные 4 инта по 16 бит с атмеги поместились в 2 инта по 32 бита на саме.

То есть  int W;(16) и int X;(16) сидят в int W;(32), а int Y;(16) и int Z;(16) в int X;(32).

maksim
Offline
Зарегистрирован: 12.02.2012

Попробуйте на дуе сделать так:

typedef struct {
  int16_t W;
  int16_t X;
  int16_t Y;
  int16_t Z;
}

если не прокатит, можно так:

   done = radio.read( &duino2, sizeof(duino2) );

   duino2.Y = duino2.X&0xFFFF;
   duino2.Z = duino2.X>>16;
   duino2.X = duino2.W>>16;
   duino2.W = duino2.W&0xFFFF;

   Serial.print("Controller = ");

 

dardik
Offline
Зарегистрирован: 09.03.2013

Спасибо огромное!! получилось сразу!


typedef struct {
  int16_t W;
  int16_t X;
  int16_t Y;
  int16_t Z;
}
BelkinVadim
Offline
Зарегистрирован: 09.12.2013

Может кому интересно будет, тут http://hackaday.com/2013/09/21/sending-data-over-bluetooth-low-energy-with-a-cheap-nrf24l01-module/http://dmitry.gr/index.php?r=05.Projects&proj=15&proj=11.%20Bluetooth%20LE%20fakery про отправку с nrf24l01 на bluetooth и в обратном порядке

ryzhuk
Offline
Зарегистрирован: 05.05.2014

Если не секрет к каким пинам на дуе подключали nRF24?

 

ryzhuk
Offline
Зарегистрирован: 05.05.2014

Перепробовал уже и так и сяк в результате коменды  radio.printDetails(); получаю следующее

STATUS = 0xff RX_DR=1 TX_DS=1 MAX_RT=1 RX_P_NO=7 TX_FULL=1
RX_ADDR_P0-1 = 0xffffffffff 0xffffffffff
 
RX_ADDR_P2-5 0xff 0xff 0xff 0xff
EN_AA = 0xff
и далее тоже всё одни FF
 
Модуль на другой дуине работает без проблем. На дуо никак не могу запустить.
Перепробовал уже всё из 
 

 

Mike72
Offline
Зарегистрирован: 06.05.2014

Пробовал так:

 

Но тоже столкнулся с проблемой - модуль не отправляет данные, а только может прнять...

ryzhuk
Offline
Зарегистрирован: 05.05.2014

А пример кода можеш скинуть?

Mike72
Offline
Зарегистрирован: 06.05.2014

Код есть в примерах самой библиотеки RF24. 

Использовал "Getting Started". Также где-то находил модифицированный код:

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"


//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 

RF24 radio(9,10);

//
// Topology
//

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

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes
// in this system.  Doing so greatly simplifies testing.  
//

// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role = role_pong_back;

void setup(void)
{
  //
  // Print preamble
  //

  Serial.begin(9600);
  while(!Serial.available()){
    Serial.println("Enter any key then ENTER to begin.");
    delay(1000);
  }
  
  Serial.println("\n\rRF24/examples/GettingStarted/\n\r");
  Serial.println("ROLE: ");
  Serial.println(role_friendly_name[role]);
  Serial.println("*** PRESS 'T' then ENTER to begin transmitting to the other node. ***\n\r");

  //
  // Setup and configure rf radio
  //

  radio.begin();

  // optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);

  // optionally, reduce the payload size.  seems to
  // improve reliability
  //radio.setPayloadSize(8);

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens two pipes for these two nodes to communicate
  // back and forth.
  // Open 'our' pipe for writing
  // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

  //if ( role == role_ping_out )
  {
    //radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  //else
  {
    //radio.openWritingPipe(pipes[1]);
    //radio.openReadingPipe(1,pipes[0]);
  }

  //
  // Start listening
  //

  radio.startListening();

  //
  // Dump the configuration of the rf unit for debugging
  //

  radio.printDetails();
}

void loop(void)
{
  //
  // Ping out role.  Repeatedly send the current time
  //

  if (role == role_ping_out)
  {
    // First, stop listening so we can talk.
    radio.stopListening();

    // Take the time, and send it.  This will block until complete
    unsigned long time = millis();
    Serial.print("\n\rNow sending: ");
    Serial.println(time);
    bool ok = radio.write( &time, sizeof(unsigned long) );
    
    if (ok)
      Serial.print("ok...");
    else
      Serial.print("failed...");

    // Now, continue listening
    radio.startListening();

    // Wait here until we get a response, or timeout (250ms)
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 200 )
        timeout = true;

    // Describe the results
    if ( timeout )
    {
      Serial.println("\n\rFailed, response timed out.");
    }
    else
    {
      // Grab the response, compare, and send to debugging spew
      unsigned long got_time;
      radio.read( &got_time, sizeof(unsigned long) );

      // Spew it
      Serial.print("\n\rGot response: ");
      Serial.println(got_time);
      Serial.print("round-trip delay: ");
      Serial.println(millis()-got_time);

    }

    // Try again 1s later
    delay(1000);
  }

  //
  // Pong back role.  Receive each packet, dump it out, and send it back
  //

  if ( role == role_pong_back )
  {
    // if there is data ready
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      unsigned long got_time;
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( &got_time, sizeof(unsigned long) );

        // Spew it
        Serial.print("Got payload: ");
        Serial.println(got_time);

	// Delay just a little bit to let the other unit
	// make the transition to receiver
	delay(20);
      }

      // First, stop listening so we can talk
      radio.stopListening();

      // Send the final one back.
      radio.write( &got_time, sizeof(unsigned long) );
      Serial.println("Sent response.");

      // Now, resume listening so we catch the next packets.
      radio.startListening();
    }
  }

  //
  // Change roles
  //

  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'T' && role == role_pong_back )
    {
      Serial.println("*** CHANGING TO TRANSMIT ROLE ***");
      Serial.println("Press 'R' then ENTER to switch back to Receive Role.");

      // Become the primary transmitter (ping out)
      role = role_ping_out;
      radio.openWritingPipe(pipes[0]);
      radio.openReadingPipe(1,pipes[1]);
    }
    else if ( c == 'R' && role == role_ping_out )
    {
      Serial.println("*** CHANGING TO RECEIVE ROLE ***");
      Serial.println("Press 'T' then ENTER to switch back to TRANSMIT ROLE");
      
      // Become the primary receiver (pong back)
      role = role_pong_back;
      radio.openWritingPipe(pipes[1]);
      radio.openReadingPipe(1,pipes[0]);
    }
  }
}
// vim:cin:ai:sts=2 sw=2 ft=cpp 

 

Townfine
Offline
Зарегистрирован: 28.08.2014

Здравствуйте dardik. Подскажите пожалуйста, что надо изменить в вашем коде чтобы температура и заряд батарей отображались в таком виде "26,1"  и   "3,7".Заранее спасибо за ответ.

maksim
Offline
Зарегистрирован: 12.02.2012
LexaBu
Offline
Зарегистрирован: 06.09.2014

Здравствуйте. Подскажите неграмотному, к каким пинам Arduino DUE подключить nRF24L01. Есть UNO - передает данные, и есть DUE - должна принимать. Пробовал и как к Меге 2560 и к SPI, результата никакого. Библиотека RF24

9ser
Offline
Зарегистрирован: 18.11.2012

Соединять прямо к выводам SPI расположенным в центре платы

dim770
Offline
Зарегистрирован: 15.02.2016

Здравствуйте. Если возможно обновите ссылку на библиотеку DHT22. Спасибо