Go Down

Topic: nRF24L01+ RF24 Help sending byte array (Read 10122 times) previous topic - next topic

clumzy

Hello,

I am pretty new to this forum except have been following it for awhile looking for help on different issues I have come about with however I can not find anything on this particular issue and this has been eating me alive trying to figure out!

My equipment:
2 Arduino Due's
2 nRF24L01+'s

My issue:
I am trying to send an int array from one arduino to the next via the RF24 protocols and have cut the arrays down to 32 bytes to send individual packets of data.  On my transmitting arduino I have the large int array casted to a byte array and cut down at every 32 bytes for a different packet.  I am able to see that this portion works except when sending this 32 byte array to the other arduino it reads every byte as a 1 that is received.  The strange part is that when forcibly changing the total number of packets on the receiving side to a higher number then one- such as 3- the data received will go from 1-2-3 depending on the packet it is on.  I am completely clueless as to how to fix this or what could be the problem with it. 
Attached below is the ino files for the receiving and transmitting arduino code.  Any help would greatly appreciated!!

Thank you so much for your time too!
-Matt

PaulS

Code: [Select]
          sending[i+2] = (byte)IRsignal_PWR[i+(pkt*30)];  //shift sending by 2 (Header) to start at 3rd position
If the value in the array CAN be treated as a byte, why isn't the array type byte? What is the array type? What size ARE the values in the array?
The art of getting good answers lies in asking good questions.

clumzy

Hey Pauls,
Thank you for your response--

I tried changing the array to a byte array and still the same problem.  The array I am trying to send as multiple packets is actually the timing from a remote control in 10's of ms.  They are rather small numbers but there are alot of them which is why im trying to convert them to bytes to send.  Before sending the packet I have it dump the entire array into the Serial window and I see the correct values as well as the sending being 32 bytes of data.  The problem comes about when receiving -- it sets every element of the array equal to the packet number (index of 0).

A cut down version of the array to be transmitted is right below to show sizes--(70 bytes long which is why I cut it in 3):
Code: [Select]
byte IRsignal_PWR[] = {
884, 444,
54, 60,
54, 58,
58, 162,
62, 50,
64, 52,
62, 50,
64, 48,
58, 62,
54, 164
}

crofter

clumzy

I have had a go with your code and found a few problems. In the TX code there are a number of places where you are access the data array using an index of 32 when it should be 30 as that is the amount of data you are sending. You also are not sending the first 30 bytes as you are starting with the wrong index.

The problem you are seeing with the repeated pkt number at the received is caused by memory corruption. I haven't worked out why yet but allocating a minimum byte array of 32 is not enough. It appears that the read routine is returning more bytes. The first time I run the rx program it all works fine but if I use the R command to rerun then the second packet is corrupted. I have increased the array size to 40 and the problem goes away.

Below are my test tx and rx sketches where I have replaced your IR array with a sequential array that shows indexing errors very easily.
Code: [Select]

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"
//#include "ircodes.h"

#define DEBUG
//
// Hardware configuration
//

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

RF24 radio(9,10);

const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

byte sending[32];
int pkt,sizeArray,total_pkts;
bool confirmed,sendArray;

byte source_data[210];

void setup(void)
{
 
// initialise dummy array
  for (int i = 0; i < 210; i++)
  {
    source_data[i] = i; 
  }
 
  Serial.begin(57600);
  printf_begin();
 
  radio.begin();

  radio.setRetries(15,15);
 
  radio.openReadingPipe(1,pipes[1]); //Open Reading pipe
  radio.openWritingPipe(pipes[0]);   //Open Writing pipe

  radio.startListening();

  radio.printDetails(); //Details of radio
 
  //Set initial Values
  pkt = 0;
  sendArray = true;
  confirmed = true;
   sizeArray = sizeof(source_data);  //total length of array
  Serial.print ("Sizearray: ");
  Serial.println(sizeArray);
  total_pkts = sizeArray/30;
}

void loop(void)
{
  //
  // Send Array to other arduino
  //
  if (sendArray)
  {
    while((pkt < total_pkts)&&(confirmed)){ //packet place holder
      radio.stopListening();      //stop listening to talk
      if(confirmed){               //if response confirming it obtained the previous packet, continue
        pkt++;
        //Header for each packet
        sending[0] = pkt;                 //Header for packet number
        sending[1] = total_pkts;   //total packets sent
#ifdef DEBUG
        Serial.print ("Packet: ");
        Serial.print(pkt);
        Serial.print(" of ");
        Serial.println(sending[1]);
#endif
        for (int i = 0; i < 30; i++){     //Next 30 bytes to fill
          sending[i+2] = source_data[i+((pkt-1)*30)];  //shift sending by 2 (Header) to start at 3rd position
                                                  //IRsignal -> shift packetnumber*30 for last packet left off
#ifdef DEBUG
          Serial.print(i+2);
          Serial.print(" = ");
          Serial.println(sending[i+2]);
#endif
        }
        confirmed = false;
        Serial.print("Sending packet of size: ");  //make sure 32 bytes or less
        Serial.println(sizeof(sending));
       
        bool ok = radio.write( &sending, sizeof(sending));    //Sends first packet to radio

        if (ok){
          Serial.print("Packet Sent: ");
          Serial.println(pkt);
        }
        else {
          printf("failed.\n\r");
        }
         
        byte packetReceived = 0;  //packetReceived (feedback) = 0th packet
       
        radio.startListening();    //start listening for a response
        delay(400);
        radio.read(&packetReceived, sizeof(packetReceived));    //save response
       
#ifdef DEBUG
        Serial.print(" Packet sent: ");
        Serial.print(pkt);
        Serial.print(" PacketReceived: ");
        Serial.println(packetReceived);
#endif
        if (packetReceived == pkt){   //If packet number received == packet sent               
          confirmed = true;
          Serial.println("Packet was confirmed, proceed to send next packet.");
        }
        else{
          confirmed = false;
          sendArray = false;
          Serial.println("Either nothing sent/no confirmation/Mismatch of packets (resend??)");
        }
      }
    }
  }
 
  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'R' )
    {
      printf("*** Printing RF Details\n\r");
      radio.printDetails();
     
      Serial.println("RESETING");
      sendArray = true;//Reset Variables
      pkt = 0;
      confirmed = true;
    }
  }
}


Rx sketch
Code: [Select]
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"
#define DEBUG

RF24 radio(9,10);

const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
byte received[40];             //data holder for received data
bool allReceived;

void setup(void)
{

  Serial.begin(57600);
  printf_begin();
 
  radio.begin();

  radio.setRetries(15,15);
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1,pipes[0]);

  radio.startListening();

  radio.printDetails(); //Debug
 
  //Variable Initialization
  allReceived = false;
}

void loop(void)
{
//  radio.startListening();        //start listening for data
 
  if ( radio.available() )
    {
      bool done = false;
      while (!done&&!allReceived)  //If everything isnt received and not doen receiving
      {
        done = radio.read( &received, sizeof(received) );//place received data in byte structure

//        received[1] = 3; //Force total packets = 3 for testing bc otherwise 1

#ifdef DEBUG
        Serial.print("Packet: ");
        Serial.print(received[0]);
        Serial.print(" of ");
        Serial.println(received[1]);
        for (int i = 2; i < 32; i++){
          Serial.print(i);
          Serial.print(" = ");
          Serial.println(received[i]);
        }
#endif
delay(20);
        radio.stopListening();    //stop listening to transmit response of packet received.
        byte pkt = received[0];  //part of header, packet number received
        bool ok = radio.write(&pkt, sizeof(pkt));  //send packet number back to confirm
        if (ok){
          Serial.print("Done Sending Response of packet:");
          Serial.println(pkt);
        }
        if (pkt == received[1]){  //if packet received == total number of packets
          allReceived = true;
          printf("got all the packets\n");
        }
        Serial.println("Done Receiving");
        radio.startListening();
      }
     
    }   
  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'R' )
    {
      radio.printDetails();
      //Reset Variables
      allReceived = false;
    }
  }
}


If you need to send integers I suggest you define a structure which has 2 bytes and an array of int[15] and then send the structure.

clumzy

Crofter,
Ahh you saved me! Thank you so much!
I do not see where you said I was going over the array index of 32, I was sending arrays of 32 bytes with 2 bytes in the beginning as a header which was why I offset everything by 2 and went up 32 (30 bytes of data).  I have adapted it to set the array you made(source_data) to equal the values I had in the other array otherwise make them a 0 and it would send.  If I just tried replacing source_data with the array I was importing it would corrupt again so kinda of strange still but I'm not complaining if it works this way instead haha.

Thank you again!!

crofter


I do not see where you said I was going over the array index of 32

The memory corruption appears to occur after calling  radio.read with the array and max length. It could be that the read routine in the RF24 library is making changes to the array beyond byte 32. I haven't done any debugging to investigate it  but increasing the array size gives a safety buffer. So this is not something you have done but has occurred because you allocated a receive buffer of 32 bytes.
I could be completely wrong and something else is causing the memory corruption.

hugo007

#6
Apr 17, 2014, 12:58 pm Last Edit: Apr 17, 2014, 01:16 pm by HugoPT Reason: 1
Quote
byte IRsignal_PWR[] = {
   884, 444,
   54, 60,
   54, 58,
   58, 162,
   62, 50,
   64, 52,
   62, 50,
   64, 48,
   58, 62,
   54, 164
}

My eyes are telling me that its not possible to store 884 or 444 in a byte so a good guess for memory corruption here
Quote
A byte stores an 8-bit unsigned number, from 0 to 255.


In you receive skeetch you have:
Quote
byte received[40];  

Why 40 byte if you just expect 32 bytes.This is very bad because:
Quote
while (!done&&!allReceived)  //If everything isnt received and not doen receiving
     {
       done = radio.read( &received, sizeof(received) );//place received data in byte structure

sizeof received is 40 and the function read uses that lenght in a while loop to read all those 40 bytes.Guess what your payload only have 32 so you are telling the function to read more than you have!
Look for your self:
Quote

uint8_t RF24::read_payload(void* buf, uint8_t len)
{
 uint8_t status;
 uint8_t* current = reinterpret_cast<uint8_t*>(buf);

 uint8_t data_len = min(len,payload_size);
 uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
 
 //printf("[Reading %u bytes %u blanks]",data_len,blank_len);
 
 csn(LOW);
 status = SPI.transfer( R_RX_PAYLOAD );
 while ( data_len-- )//----------------------------->>>>>>>>>>>>>Your 40 magic number enters here!!
   *current++ = SPI.transfer(0xff);
 while ( blank_len-- )
   SPI.transfer(0xff);
 csn(HIGH);

 return status;
}


Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

crofter

HugoPT

I'm afraid you are mixing sketches. I see memory corruption when sending bytes containing numbers from 0 to 210.

I increased the receiving array size to see if there was a problem and it showed that maybe there is an issue with the RF24 read function or the way it is being used. In your analysis on the effect of increasing array size you ignored the line

Code: [Select]
uint8_t data_len = min(len,payload_size);
As payload_size is 32 I am reading 32 bytes into an array which will have some blanks at the end .. not that much of a crime.

Go Up