NRF24L01 Slow Data Rate

IbrahimOladepo

New member
Background:
I am working on an electrophysiology data acquisition system with the following specs:
- I am using an Intan RHD2132 as the amplifier and ADC (running 32 amplifier channels at 30 kSamples/s, equivalent to 1.05MSamples/s).
- The Intan RHD2132 directly interfaces with a Teensy 4.0 via SPI, and I am running the Teensy 4.0 at 600 MHz.
- Then I intend to send the data wirelessly via two NRF24L01 modules (transmitter and receiver, using 2MBPs data rate), and the receiver module is connected to the PC via another Teensy 4.0.


My Questions and Issues:
- Presently, I cannot get the SPI speed above 16MHz without some messed-up clock signal on the clock pin (and the data becoming invalid) [Image Attached]. Is there a way I can increase the SPI speed above 16MHz?

- I am unable to get the NRF24L01 to actually operate at 2MBPs (using the RF24 library). I tried to just send 32 bytes for a period of 10 seconds to calculate how high I could get the data rate. The maximum data rate I got was about 57 KBPs. Is there something I am doing wrong that is not making me get the highest data rate? [I have attached the codes for the transmission and reception below.]

- Also, the data transfer from the Intan to the PC via Serial seems much slower than the data acquisition. I think this is because of the 250000 baud rate. Is there a way I can achieve a very high data transfer speed from Teensy 4.0 (Up to 3 MB/s) to the PC?

- I am beginning to think a high data rate Bluetooth module would be sufficient for my wireless data transmission since I am not concerned about long-range. Any suggestions on a Bluetooth module that would fit my application?


Code and Images:

Teensy 4.0 SPI at 24 MHz
SPI at 24MHz.jpg

NRF24L01 Transmit Data Code
Code:
//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 10);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

elapsedMillis sinceStart;

// Max size of this struct is 32 bytes - NRF24L01 buffer limit
// Some properties of the unsigned short int data type are: Being an unsigned data type, 
// it can store only positive values. Takes a size of 16 bits. A maximum integer value that can be 
// stored in an unsigned short int data type is typically 65535, around 216 – 1(but is compiler dependent)
struct Data_Package {
  unsigned short a = 0;
  unsigned short b = 8;
  unsigned short c = 16;
  unsigned short d = 32;
  unsigned short e = 64;
  unsigned short f = 128;
  unsigned short g = 256;
  unsigned short h = 512;
  unsigned short i = 1024;
  unsigned short j = 2048;
  unsigned short k = 4096;
  unsigned short l = 8192;
  unsigned short m = 16384;
  unsigned short n = 32768;
  unsigned short o = sinceStart;    // timer variable
  unsigned short p = 1;    // p is goinig to change every loop to monitor speed
};

Data_Package data; // Create a variable with the above structure

void setup(){
  Serial.begin(115200);

  pinMode(2, OUTPUT);
  
  radio.begin();
  
  //set the address
  radio.openWritingPipe(address);

  // Set transmission power
  // radio.setPALevel( RF24_PA_MIN ); // -18dBm
  // radio.setPALevel( RF24_PA_LOW ); // -12dBm
  radio.setPALevel( RF24_PA_HIGH ); // -6dBm
  // radio.setPALevel( RF24_PA_MAX ); // 0dBm

  // changer the transfer rate as needed
  // radio.setDataRate( RF24_250KBPS ); // pour portée maximum
  // radio.setDataRate( RF24_1MBPS );
  radio.setDataRate( RF24_2MBPS );

  // Change the channel (transmit-receive frequency) as needed
  // channel = 0 to 125 correspond to the range 2,400GHz to 2,500GHz
  // NOTE: if DataRate is set to 2MBPS, the bandwidth
  // is 2 MHz and we must therefore skip every other channel 
  // to avoid overlaps
  radio.setChannel( 90 );

  radio.printDetails();
  
  //Set module as transmitter
  radio.stopListening();

  Serial.println( "*****************" );
  Serial.println( "Trasmitter is Ready" );

  sinceStart = 0;
  digitalWriteFast(2, LOW);
}

void loop()
{
//  Serial.print("Since Start: ");
//  Serial.println(sinceStart);
  
  if (sinceStart < 10000){
    digitalWriteFast(2, HIGH);
    
    // Send the whole data from the structure to the receiver
    radio.write(&data, sizeof(Data_Package));

    // digitalWriteFast(2, LOW);
  
    data.p = data.p + 1;
    data.o = sinceStart;

    digitalWriteFast(2, LOW);

    delayMicroseconds(1);

    // Serial.println("I am here!");
  }

}

NRF24L01 Receive Data Code
Code:
//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 10); // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
  unsigned short a = 0;
  unsigned short b = 0;
  unsigned short c = 0;
  unsigned short d = 0;
  unsigned short e = 0;
  unsigned short f = 0;
  unsigned short g = 0;
  unsigned short h = 0;
  unsigned short i = 0;
  unsigned short j = 0;
  unsigned short k = 0;
  unsigned short l = 0;
  unsigned short m = 0;
  unsigned short n = 0;
  unsigned short o = 0;
  unsigned short p = 1;    // p is goinig to change every loop to monitor speed
};

Data_Package data; // Create a variable with the above structure

void setup() {
  Serial.begin(115200);
  
  radio.begin();

  //set the address
  radio.openReadingPipe(0, address);
  
  // régler puissance d'émission
  // radio.setPALevel( RF24_PA_MIN ); // -18dBm
  // radio.setPALevel( RF24_PA_LOW ); // -12dBm
  radio.setPALevel( RF24_PA_HIGH ); // -6dBm
  // radio.setPALevel( RF24_PA_MAX ); // 0dBm

  // changer the transfer rate as needed
  // radio.setDataRate( RF24_250KBPS ); // pour portée maximum
  // radio.setDataRate( RF24_1MBPS );
  radio.setDataRate( RF24_2MBPS );

  // Change the channel (transmit-receive frequency) as needed
  // channel = 0 to 125 correspond to the range 2,400GHz to 2,500GHz
  // NOTE: if DataRate is set to 2MBPS, the bandwidth
  // is 2 MHz and we must therefore skip every other channel 
  // to avoid overlaps
  radio.setChannel( 90 );

  radio.printDetails();

  //Set module as receiver
  radio.startListening();

  Serial.println( "*****************" );
  Serial.println( "Receiver is Ready" );
}

void loop() {
  
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure

    Serial.print(" counter: ");
    Serial.print(data.p);
    Serial.print(" , timer: ");
    Serial.println(data.o);
  }
  
}

Code For Getting ADC Data:
This code has multiple files, so I'd rather post a Github link: https://github.com/IbrahimOladepo/Scratch/tree/main/Teensy_Intan_FasterSPI_01


Thank you.
 
Hi Ibrahim,

Did you provide a "special" power supply for the NRF?
They are somewhat sensible to this point, and this could be a problem. There is some small power shield specially designed for this purpose.

Well, that's only a suggestion, I'm in no way a specialist of the NRF!!

Gerard.
 
Since the NRF24L01 operates on the 2.4GHz ISM band, you have to share that medium with all present WiFi traffic. That could be one of the issues for the low throughput.

Another factor could be the physical distance between the 2 RF24 modules; the higher distance, the lower the throughput [to the point where the connection breaks].

And thirdly: unfortunately there are a lot of fake NRF24L01 modules out there. I have been troubled by cheap inferior modules so I ended up buying modules of the brand RobotDyn. Google for "NRF24L01 fake" and you won't be happy to read...

Lastly: check out this page, no need to crank up the SPI clock above 10Mhz. In my NRF24L01 projects, I always used the standard SPI clock speed which is 4MHz if I'm not mistaken.

Paul
 
Hi Ibrahim,

Did you provide a "special" power supply for the NRF?
They are somewhat sensible to this point, and this could be a problem. There is some small power shield specially designed for this purpose.

Well, that's only a suggestion, I'm in no way a specialist of the NRF!!

Gerard.


Hello Gerad,

I did use an external power supply to power the NRFs at 3.3v. But there was no difference in the data rate.
 
Since the NRF24L01 operates on the 2.4GHz ISM band, you have to share that medium with all present WiFi traffic. That could be one of the issues for the low throughput.

Another factor could be the physical distance between the 2 RF24 modules; the higher distance, the lower the throughput [to the point where the connection breaks].

And thirdly: unfortunately there are a lot of fake NRF24L01 modules out there. I have been troubled by cheap inferior modules so I ended up buying modules of the brand RobotDyn. Google for "NRF24L01 fake" and you won't be happy to read...

Lastly: check out this page, no need to crank up the SPI clock above 10Mhz. In my NRF24L01 projects, I always used the standard SPI clock speed which is 4MHz if I'm not mistaken.

Paul

Hello Paul,

As for the distance between the two NRF modules, I actually placed them side by side to perform the speed tests I did. I don't think that is the problem in this case.

As for the originality of my NRF modules, I got them directly from Sparkfun and I believe these are genuine modules.

For the increased SPI speed, I was referring to the data acquisition from the Intan RHD ADC. For me to get that high data rate of 1 MBPs, I need to increase the SPI clock to about 24MHz.

Ibrahim.
 
Back
Top