nRF24L01 clone tester

I have a number of nRF24L01 that look like clones. When set to rx mode, they continuously say data is available on pipe3. Here is a sketch that should enable one to quickly detect if you have one of these devices. (Please note: I have not checked it with a genuine part as I do not have any yet).

/*
*   Check nRF24L01 to see if it is a modified clone
*
*   Tested using library "RF24 by TMRh20" Version 1.4.1
*   On Arduino IDE V 2.0.0-beta.10
*   Code running on Arduino Pro Mini
*
*   Change CE, CSN defined pin values to match your setup
*   Set your Arduino IDE serial monitor Baud rate to 9600
*
*   Interpret "modified" as meaning the part does not appear
*   to support the original Nordic Semiconductor datasheet:
*   https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf
*/

#include <RF24.h>

#define CE  9
#define CSN 10

RF24 radio(CE, CSN);
const byte address[6] = "TEST1";
long counter = 0;
uint8_t pipeNum;
char text[32] = "";

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("<<< nRF24L01 clone tester >>>");
  if (!radio.begin()) {
    Serial.println("Failed to connect to radio");
    while (1);
  }
  radio.openReadingPipe(1, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  for (int i=0; i<1000; i++) {
    if (radio.available(&pipeNum)) {
      radio.read(&text, sizeof(text));
      if (pipeNum == 3) {
        counter += 1;
      }
    }
  }
  if (counter > 100) {
    Serial.println("Part is a modified nRF24L01 clone");
  } else {
    Serial.println("Part may be a valid nRF24L01");
  }
}

void loop() {
}

So all clones don't work? Hard to believe.
Maybe there is a different content of the pipe registers on reset,
that make your "TEST1" address illegal.

Could you please post a register dump or a printDetails output?

I started to work on NRF diagnostic code, maybe you like to play with the rudimentary start.
(It contains the reset values of the genuine chips)

#include <SPI.h>

const byte CMD_R_REGISTER = 0x00; // mask for SPI command
const byte CMD_W_REGISTER = 0x20; // mask for SPI command

const byte resetValues[44] PROGMEM = {
  0x08, 0x3F, 0x03, 0x03, 0x03, 0x02, 0x0F, 0x0E, 0x00, 0x00, 0xE7,
  0xE7, 0xE7, 0xE7, 0xE7, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC4,
  0xC5, 0xC6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00
};

const byte csnPin = 10;

void pHexByte(uint8_t val, bool blankAfter = true);
void printRegisters(bool printTitle = true, bool printFirstSPI = false);

uint8_t regValues[44];
uint8_t firstVals[44];

void setup() {
  Serial.begin(115200);
  pinMode(csnPin, OUTPUT);
  Serial.println(F("\nNRF24L01 register dump\n"));
  SPI.begin();
  readRegisters();
}

void loop() {
  static uint32_t lastDump = (uint32_t)(-5000);
  if (millis() - lastDump >= 5000) {
    readRegisters();
    printRegisters();
    if (!memcmp_P(regValues, resetValues, 44)) {
      Serial.println(F(" -> matches reset values"));
    }
    Serial.println();
    lastDump = millis();
  }
}
void readRegisters() {
  for (uint8_t cIndex = 0, tIndex = 0; cIndex < 0x20; cIndex++, tIndex++) {
    digitalWrite(csnPin, LOW);
    firstVals[tIndex] = SPI.transfer(CMD_R_REGISTER | cIndex);
    if (cIndex == 10 || cIndex == 11 || cIndex == 16) {
      SPI.transfer(regValues + tIndex, 5);
      tIndex += 4;
    } else {
      regValues[tIndex] = SPI.transfer(0xff);
    }
    digitalWrite(csnPin, HIGH);
  }
}

void printRegisters(bool printTitle, bool printFirstSPI) {
  if (printTitle) {
    Serial.print(F("# 00 01 02 03 04 05 06 07 08 09 0A __ __ __ __ 0B __ __ __ __ 0C 0D 0E 0F"
                   " 10 __ __ __ __ 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"));
  }
  if (printFirstSPI) {
    Serial.print(F("\n- "));
    for (uint8_t i = 0; i < 44; i++) {
      pHexByte(firstVals[i]);
    }
  }
  Serial.print(F("\nV "));
  for (uint8_t i = 0; i < 44; i++) {
    pHexByte(regValues[i]);
  }
  Serial.println();
}

void pHexByte(uint8_t val, bool blankAfter) {
  if (val < 0x10) {
    Serial.write('0');
  }
  Serial.print(val, HEX);
  if (blankAfter) {
    Serial.write(' ');
  }
}

Have a look at this please.

Also, could you see what my tester code does with a genuine nRF24L01 please.

How does someone know if they have a genuine nRF24L01 ?

Output from your NRF diagnostic code:

NRF24L01 register dump

# 00 01 02 03 04 05 06 07 08 09 0A __ __ __ __ 0B __ __ __ __ 0C 0D 0E 0F 10 __ __ __ __ 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
V 0E 3F 03 03 5F 78 01 0E 5F 00 30 30 30 30 31 C2 C2 C2 C2 C2 C3 C4 C5 C6 30 30 30 30 31 20 20 20 20 20 20 11 00 00 00 00 00 00 6D 00 

As expected it prints:

12:34:10.247 -> <<< nRF24L01 clone tester >>>
12:34:10.281 -> Part is probably a genuine nRF24L01

Looks like those registers are not the reset state, but some relic of a previous sketch.
Please run the sketch again after a power cyclce of the NRF.

Hi @Whandall, thanks for your input, can you please supply a link to documentation that supports your statement "When set to rx mode, they continuously say data is available on pipe3." I have not seen reference to this anywhere else.

By the way, even after being powered off overnight, my parts still exhibit the same "clone" behaviour. Do you have any code that will reset registers to the "correct" startup state?

That was your claim, and it is what your program tests for, you see me confused.

My code just reads out the registers, but the NRF needs a power cycle to reset,
so please post the output directly after a power up.

My code contains the standard reset setup,
you can just write those to the corresponding registers, I doubt it will help.

Sorry about the confusion, my comment was simply a statement of the behaviour of the modules I have which is not what I expected. It means they are almost unusable as one has to stay in a tight loop reading pipe 3 before being able to read anything from another pipe. I have since seen Protocol decoder:nrf24l01 - sigrok so it seems there are many clones. My code will probably only detect this nasty variant.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.