0

How to detect RFM12B or NRF24L01 device presence in your code

I’m using day by day a custom board to debug and test my Arduino code. My board exposes an NRF24L01 connector that I’m using also to connect lot of devices (RFM12B, RFM69, MAX18355, SD, FLASH, …) mounted on a breakboard such as this one for example. Some time during test I’m switching from one board to another, it is quite useful to be able to check that the device is here and is responding.

How to do that ?

Well, as usual, reading data sheet of the device can help a lot. but I’ve already done this and the code is already written. Just read below on how to achieve this.

RFM12B Module

RFM12 datasheet has the ability to detect low voltage, we will be using this function to detect the device. For this example I’m using LowPowerLab rfm12b library written by Felix and tweaked from excellent one written by jcw from jeelabs, but you can use another one the same way.

The Low voltage threshold can be setup from 3.75V to 2.25V. So until you’re powering the RFM12B device from let’s say 2.4V to 3.6V (which is juste the datasheet recomendation) you will be able to detect the device. The trick is done in two phases.

  • Set threshold voltage to 3.75V, and check we’re under voltage.
  • then set threshold voltage to 2.25V and check we’re above under voltage

That’s it, simple and efficient not ?

NRF24L01 Module

NRF24L01 datasheet has the ability to set configuration parameters and read them back. We will be using this function to detect the device. For this example I’m using RF24 Arduino library from Stanley and tweaked from excellent one written by maniacbug, but you can use another one the same way, just check library functions and methods.

We will setup number of retries and read them back and also we will trie to set the module RF speed. Then read back the number of retries and check that speed command has been done successfully. The trick is done in three phases.

  • Set number of retries
  • Read back number of retries and compare with the value we set
  • Set the speed (baud rate) and check if it has been done correctly

Example code

The example code below is a function that return if the device detected is an RFM12B or NRF24L01 module. Of course two radios modules need to be declared and instancied for this, but if you use only one, juste instantiate the one you use and remove code from the unneeded module in the function.

....

// The various RF Modules supported 
typedef enum 
{ 
  module_unknown = 0, 
  module_nrf24 , 
  module_rfm12b
} module_e;

// Instantiate Radio Modules
RF24    radio_rf24(RF_CE,RF_CSN);    /* NRF24L01 */
RFM12B  radio_rfm12b;                /* RFM12B */

module_e module; // RF module used

/* ======================================================================
Function: detectDevice
Purpose : try to detect device connected to SPI bus (NRF24 or RFM12B)
Input   : -
Output  : return device type 
Comments: - 
====================================================================== */
uint8_t detectDevice() 
{
  module_e module = module_unknown;
  uint16_t status;

  // Init NRF24L01 Module
  radio_rf24.begin();
  
  // Try to set retries to check later
  radio_rf24.setRetries(0x0A, 0x05);
  
  // NRF24L01 easy to detect, because setDataRate write and read again to see if the same
  // So if it is okay this mean that there is a NRF24L01 device
  if (  radio_rf24.getRetries()==0xA5 && radio_rf24.setDataRate(RF24_1MBPS) ) 
  {
    // We are sure, this is a NRF24
    module = module_nrf24; 
  }
  else
  {
    // Init RFM12B module
    // whatever values here, the real init will be done later
    // We just need to init the device
    radio_rfm12b.Initialize(0, RF12_433MHZ);

    // Clock output (1.66MHz), Low Voltage threshold (3.75V)
    // we will change the Low Voltage threshold to the highest 
    // value we can, as the module is powered by 3.3V the bit
    // indicating low voltage should now be set because at 3.3V
    // we are under 3.75V
    radio_rfm12b.Control(0xC04F); 
    
    // Wait the voltage comparison to settle ?
    // I do not know, but it can't hurt
    delay(10);

    // Check if module is low battery ?
    if ( radio_rfm12b.LowBattery() )
    {
      // Here we can have false detection in case of NRF24 plugged
      // since we just check SPI return on one bit (LowVoltage)
      // Clock output (1.66MHz), Low Voltage threshold (2.25V)
      // So set voltage detection to test inverted bit
      radio_rfm12b.Control(0xC040); 

      delay(10);
      
      // Check if module is no more low battery ?
      // this time sounds we got a RFM12B module
      if ( !radio_rfm12b.LowBattery() )
        module = module_rfm12b;
    }
  }
  return module;
}

void setup()
{
  // Do serial init stuff
  // blah blah

  module = (module_e) detectDevice();
    
  // Check Module
  if ( module == module_unknown )
    Serial.println("No module detected..");
   else
     Serial.print(module==module_nrf24?"NRF24L01":"RFM12B");
}

Have fun detection, I will add detection for RF69 as soon as I will need it and read the datasheet.

Charles

Charles

Charles