NRF24 modules behaving differently on different arduinos

The setup:

  1. NRF24L01 module connected to Arduino Uno, on SPI plus pins 9,10
  2. Another NRF24L01 module connected on an arduino micro (ATMEGA32U4) based, stand alone system on SPI bus via voltage level shifters (BSS138 based) plus also pins 9,10. This system has the micro bootloader burned and behaves just like an arduino micro.
    Results:
    When the Arduino UNO is programmed as receiver and the micro as a transmitter everything works fine. An array of 20 bytes is sent and received perfectly on the other side.
    However, when the roles are swapped and now the Micro is the receiver and the Uno the transmitter (exactly the same sketches are used as before) the received data appears corrupt. Testing indicates that there is a certain pattern in the way the data is received corrupt:
    All data with bytes of value from 0 to 127 are received correct.
    All data of where the bytes are higher than 127 values are received corrupt and it appears as if a bit has been flipped! See output below.

If anyone can think of any reason why this is happening, it would be great help!
Thanks for your support!

// RECEIVER


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



  #define RFCE 9                // Pin connected to CE of nRF24 module 
  #define CSN 10                // Pin connected to CSN (Chip Select In) of nRF24 Module                 


byte IncPacket[79];             // Array to store incoming Data Packet
byte OutPacket[79];             // Array to store outgoing Data Packet




  RF24 radio(RFCE, CSN);                                   // Create a Radio
  uint64_t addresses[] = {0xABABABABABLL, 0xC3C3C3C3C3LL}; // Define the transmit/ receive pipes
  boolean sender = 1;                                    // Change this from 0 to 1 to switch between sending or receiving sketch



void setup() {


 Serial.begin(9600);                 // Initialise serial port for USB to PC
 Wire.begin();
 radio.begin();
 

  radio.setDataRate (RF24_250KBPS);
  radio.setPayloadSize(20);
  radio.openWritingPipe(addresses[0]);        // Both radios listen on the same pipes by default, but opposite addresses
  radio.openReadingPipe(1,addresses[1]);      // Open a reading pipe on address 0, pipe 1
  radio.startListening();

  

 
}

//    **************** MAIN LOOP  *********************
//    *************************************************

void loop() {

 
  if (( CheckIncDataRadio()==true)) // Check if valid Data available 
  { 
    Serial.println ();
    Serial.print (" Incoming Radio Data: ");
    for (int x=0; x<20; x++) {Serial.print (IncPacket[x]); Serial.print (" "); }
  
  
   
    
    Serial.println ("------------------------------------------------");
   }


}


//  CHECK INCOMING DATA RADIO

byte CheckIncDataRadio() {

 radio.startListening();
 
 
  if (!radio.available()) {return false;}
  
  Serial.println("Data Received");
  
  radio.read(&IncPacket, 20);   
  delay (10);
    
 
  Serial.println("Packet Complete!");
     
  return true;
  
}
// Transmitter


 #include <Wire.h>
 #include <OneWire.h>

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



  #define RFCE 9                // Pin connected to CE of nRF24 module 
  #define CSN 10                // Pin connected to CSN (Chip Select In) of nRF24 Module                 


byte IncPacket[79];             // Array to store incoming Data Packet
byte OutPacket[79];             // Array to store outgoing Data Packet


  RF24 radio(RFCE, CSN);                                   // Create a Radio
  uint64_t addresses[] = {0xABABABABABLL, 0xC3C3C3C3C3LL}; // Define the transmit/ receive pipes
                               


void setup() {


 Serial.begin(9600);                 // Initialise serial port for USB to PC


 
  Wire.begin();
  radio.begin();
 

  radio.setDataRate (RF24_250KBPS);
  radio.setPayloadSize(20);
  radio.openWritingPipe(addresses[1]);        // Both radios listen on the same pipes by default, but opposite addresses
  radio.openReadingPipe(1,addresses[0]);     
  radio.startListening();
 
  
 
 
}

//    **************** MAIN LOOP  *********************
//    *************************************************

void loop() {

 
 
 SendFeedback();
 Serial.println("Sent!");
 delay (200);
  


}



void SendFeedback()
{

  Serial.println ();
 
      
  radio.stopListening(); 


 
 
 for (int x=0; x<20; x++){ OutPacket[x]=120+x;}
  
 
  if (!radio.write( &OutPacket, 20)) {Serial.print(F("Sending failed!"));}
  else {   Serial.print(F("Sent packet:"));}
 
  
   
   
    radio.startListening();
    delay (400);
    
      Serial.print (" Output Data: ");
      for (int x=0; x<20; x++) {
        Serial.print (OutPacket[x]);
        Serial.print(" "); }
   
  }

Output :

At Tx:

Sent packet: Output Data: 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139! 

At RX when the Micro is the receiver:

 Incoming Radio Data: 120 121 122 123 126 127 127 127 192 193 194 195 196 197 198 199 200 201 202 203 
Data Received
Packet Complete! 


At RX when the UNO is the receiver :

Incoming Radio Data: 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 
Data Received
Packet Complete!

circuit.png

I assume that the default CRC16 setting is used, correct me if I'm wrong.

Because the chip presents the packet, it survived the transmission undamaged. It seems that the level-shifter is corrupting your packet. (NRF24L01 -> micro)

I never used a level-shifter, because the NRF24L01 pins are 5V tolerant.

If you are using ManiacBug's RF24 library I suggest you switch to the newer version by TMRh20.

The pair of programs in this link work on all of my Arduinos (Mega, Uno, Leonardo, Sparkfun ProMicro and 8MHz breadboard Atmega 328) in any combination.

How are you powering the nRF24s? Have you a 10µF capacitor across Vcc and GND close to the nRF24?

...R

@whandall: the level shifters was also my first suspect. However this isnt a case of random data corruption since there is a pattern as explained earlier. Why doesn't something similar happen when the micro is used as a transmitter? I used default crc settings.

Robin2 : same happens with both libraries. Yes i have caps connected. The micro arduino system has a dedicated 3.3v regulator near the nrf24 module. I could never get leonardo to work without level shifters before at all...

Remove the shifters, or just bypass them for a test, I bet they screw up your data or timing.

You could try to run the SPI slower.

My Leonardo runs without problems without shifters.

Watcher: However, when the roles are swapped and now the Micro is the receiver and the Uno the transmitter the received data appears corrupt.

Watcher: Why doesn't something similar happen when the micro is used as a receiver?

This is contradictory.

This is contradictory.

Sorry, my mistake! Original post edited.

Remove the shifters, or just bypass them for a test, ...

Although not easy on a dense SMD PCB, I will give it a try...

Watcher: Although not easy on a dense SMD PCB, I will give it a try...

Before mucking about with your PCB have you tried a different program just in case the problem is in your software?

Trying a different program should only take a few minutes.

...R

@Robin2: Actually i havent! However if this was a program issue, wouldn't it not work on both arduinos? How come it works on one and it doesnt work on the other?

Still... i ll give it a try! Any particular suggestions for something simple known to work well?

Watcher: Any particular suggestions

Reply #2 ?

...R

The data gets only transferred by SPI, regardless of the driver (at least all I have seen). Any driver will run into trouble if reading from the SPI changes bits.

The corruption has to occur on the way from the NRF24L01 to the Arduino, the chip trusts in the correct CRC16, or it would have discarded the packet.

So there seems to be some disturbance while using the 3.3 to 5 direction.

@whandall: thanks! Very ineresting deduction. Could you also guess which of the three signals is most likely to couse the disturbance? Clk, miso, mosi?

Arduino is master, data is comming in, so it should be miso for the data. Master In Slave Out. Clk controls all, so it could be part of the problem, but it should impact both directions.

I'm by no way a SPI specialist, just a user with some background, so beware. ;)

I would try to connect miso directly and retest.

Thanks..will try that. The reason am asking is because when measuring voltage on the 3.3v side of the clk level shifter i get always close to zero in contrast to the other two signals where i get 3.3v as expected. I will stick a scope there and see what i get..

Before mucking about with your PCB have you tried a different program just in case the problem is in your software?

Trying a different program should only take a few minutes.

Update: I ve tried the programs as suggested and I was able to replicate the problem as before: With the UNO as a receiver and the micro as a transmitter everything is fine. When the roles are reversed data bytes higher than 127 get corrupted. 128 is received as 192, 129 as 193 etc...

Watcher: Update: I ve tried the programs as suggested and I was able to replicate the problem as before: With the UNO as a receiver and the micro as a transmitter everything is fine. When the roles are reversed data bytes higher than 127 get corrupted. 128 is received as 192, 129 as 193 etc...

That is useful to demonstrate it is not a software problem.

It seems strange that there should be a consistent error - setting bit 6 high when it should be low, and (presumably) only doing so when bit 7 is high.

What happens when the value 64 is transmitted? What happens when the value 192 is transmitted?

...R

I would try to connect miso directly and retest.

Update2 : I couldn't just remove / bypass one of the level shifters because am using 4x10k array SMD resistors., So I had to remove all three of them. Result: IT WORKED!!

Thanks for your help.

Still, I don't understand why this particular type of data corruption happened with a specific pattern!

On the other hand, is it really wise not to use level shifters in terms of system reliability and safe design practices? The chip might be 5v tolerant but the voltage logic levels dont exactly coincide between 5v and 3.3v logic...

What happens when the value 64 is transmitted? What happens when the value 192 is transmitted?

64 was received correctly, being less than 127 192 was received wrong but i dont have a record of it now..

Watcher: On the other hand, is it really wise not to use level shifters in terms of system reliability and safe design practices? The chip might be 5v tolerant but the voltage logic levels dont exactly coincide between 5v and 3.3v logic...

What does the product datasheet have to say ?

...R

The datasheet claims '5V tolerant inputs'.

I doubt that using resistors as level-shifter works for raising levels, I would use active level-shifters (for the 3.3V -> 5V at least).

I doubt that using resistors as level-shifter works for raising level

Thats why i used the circuit posted with my first post...not just resistors!

Watcher: I couldn't just remove / bypass one of the level shifters because am using 4x10k array SMD resistors.

Then I can see no sense in the above.