Programming nRF2401a with PIC

Hi everyone,

I am a beginner in programming wireless module thus I have some basic question in mind.

I am doing a project on wireless signal transmission which 2 nRD2401 transceiver and also dsPIC30F3013.

After reading through the datasheet of nRF2401a, I am not sure about the mode shown on page 11 of the datasheet.

There is the part which shows:

nRF2401A ShockBurst™ Transmit:

MCU interface pins: CE, CLK1, DATA

  1. When the application MCU has data to send, set CE high. This activates

nRF2401A on-board data processing. (This should be easy, i’ll just have to connect it to 1 of the MCU IO and set it to high)

  1. The address of the receiving node (RX address) and payload data is
    clocked into the nRF2401A. The application protocol or MCU sets the
    speed <1Mbps (ex: 10kbps).
    (This is the part which I am confuse about… Where do I find the adress of RX and payload data. And how do i exactly set the speed through my MCU?)

  2. MCU sets CE low; this activates an nRF2401A ShockBurst™

transmission.

  1. nRF2401A ShockBurst™:

• RF front end is powered up

• RF package is completed (preamble added, CRC calculated)

• Data is transmitted at high speed (250 kbps or 1 Mbps configured

by user).

Hope someone pass by soon and guide me along!

Thanks.

Hello!

I am currently working with the same modules on a project, although I am using direct mode. You must send the devices configuration bytes by setting both CE and CS high, and then sending the data (one bit at a time) to the nRF2401A. This is done on the Data and Clock lines. I would recommend using the PIC chips SPI module for communication between the microcontroller and the RF module, as it makes sending and receiving data much easier. The address of channels 1 and 2 can be set in bits 103-24. There is more on this in the datasheet, near page 19. As far as setting the data rate, I don’t believe you need to. It just needs to conform to all of the timing requirements, as shown on page 24 through 30 of the datasheet. I’d recommend looking the entire datasheet over, there’s a ton of helpful information in there.

Hey thanks for the reply.

I have read through and get the example code from http://www.sparkfun.com/products/152#.

I have studied the example code and used it as reference to program my modules.

An extract of the transmit part of my code is listed below

#define TX_CE      PIN_B0
#define TX_CS      PIN_B1
#define TX_CLK1    PIN_B2
#define TX_DATA    PIN_B3

void main()
{
   output_high(TX_CE);   // CE=1; Activate data processing
   

   unsigned int elapsed_time;

    counter = 0;

    while(1)
    {
      delay_ms(1000);
        counter++;
        
        data_array[0] = 0x12;
        data_array[1] = 0x34;
        data_array[2] = 0xAB;
        data_array[3] = counter;

        printf("\n\rSending data...\n\r");
        transmit_data();
   }
}

Firstly i had set the CE to high so as to activate data-processing as shown in pg 11 of the datasheet. After that i sent a series of array addresses (which i grabbed from the example code from sparkfun) then i go into transmit_data function.

my transmit data function code

void transmit_data(void){
   
unsigned int i, j, temp, rf_address, h, r;


    //Clock in address
    rf_address = 0b11100111; //Power-on Default for all units (on page 11)

   set_tris_B(0b00001111);

    for(i = 0 ; i < 8 ; i++)
    {
      rf_address = TX_DATA;
        output_high(TX_CLK1);   // TX_CLK1 = 1;
        output_low(TX_CLK1);   // TX_CLK1 = 0;
        
        rf_address <<= 1;
    }
    
    //Clock in the data_array
    for(i = 0 ; i < 4 ; i++) //4 bytes
    {
        temp = data_array[i];
        
        for(j = 0 ; j < 8 ; j++) //One bit at a time
        {
            temp = TX_DATA;
            output_high(TX_CLK1);   // TX_CLK1 = 1;
           output_low(TX_CLK1);   // TX_CLK1 = 0;
            
            temp <<= 1;
        }
    }

    output_low(TX_CE);   // CE=0; deActivate data processing 
}

But at the receiving end, I can’t seems to get the transmitter side to communicate with the receiver side… is there any problem with my codes stated above? :?:

I am very weak in programming but I would like someone to guide me along so I can learn through the process…

Thanks for the reply!

You should be using the nRF24L01+, the nRF2401A is obsolete. The former is much easier to use, and you will find much more software for it. Very cheap modules are available on Ebay.

leon_heller:
You should be using the nRF24L01+, the nRF2401A is obsolete. The former is much easier to use, and you will find much more software for it. Very cheap modules are available on Ebay.

Yes, I found lots of example of nRF24L01+ as you mentioned.

But I had already bought nRF2401a and I have already got it. =( Too late to regret now, only way is to work on whatever resources I have now…

Do u happen to have any knowledge to guide me through my project? thanks.

I got a couple of the original nRF2401A modules (I’ve still got them somewhere). I got them working with the SFE code example, IIRC, using the PIC16F88.

leon_heller:
I got a couple of the original nRF2401A modules (I’ve still got them somewhere). I got them working with the SFE code example, IIRC, using the PIC16F88.

Well, I’m kind of halfway done through it.

I have grabbed the example from SFE and editted some part of it… And all looks well to me but the transmitter and receiver doesn’t seems to communication to each other…

Hey guys, I have update and edited my codes to the following one, with full comments on it.

But I still cannot get the wireless module to work. Anyone with the knowledge of nRF2401a can take off some time to look at my code???

And this is the result I have gotten from the UART of the MCU.

http://imageshack.us/photo/my-images/507/fghw.png/

I will be glad to provide any information you ask for. Thanks.

#include  <30F3013.h>      //Include header file of dsPIC30F3013

#include <stdlib.h>
#include <stdio.h>

#use delay(clock = 20MHz,CRYSTAL = 20MHz)                  
// Oscillation freq. 20MHz
#use rs232(baud=38400,parity=N,UART1A,bits=8,stream=HOST)      
//XMIT=PIN_C13,RCV=PIN_C14


#define TX_CE      PIN_B0
#define TX_CS      PIN_B1
#define TX_CLK1    PIN_B2
#define TX_DATA    PIN_B3

#define RX_CE       PIN_B4
#define RX_CS       PIN_B5
#define RX_CLK1     PIN_B6
#define RX_DATA     PIN_B7
#define RX_DR       PIN_B8

unsigned int data_array[4];
unsigned int counter;

void boot_up(void);
void configure_receiver(void);
void configure_transmitter(void);
void transmit_data(void);
void receive_data(void);

void main()
{
    counter = 0;
    
    boot_up();

    while(1)
    {
        counter++;
        
        data_array[0] = 0x12;
        data_array[1] = 0x34;
        data_array[2] = 0xAB;
        data_array[3] = counter;

        printf("\n\rSending data...\n\r");
        transmit_data();
    
    
        if(input(RX_DR))       //if(RX_DR == 1) //We have data!
            receive_data();
        else
            printf("No data found!\n\r");
        
        delay_ms(1000); //Have a second between transmissions just for evaluation
    
    }
        
}

void boot_up(void)
{

    set_tris_B(0b0110000000);  //0 = Output, 1 = Input (RX_DR is on RB8)

    printf("\n\rRF-24G Testing:\n\r");
    
    delay_ms(100);

    configure_transmitter();
    configure_receiver();

}

//This will clock out the current payload into the data_array
void receive_data(void)
{
    unsigned int i, j, temp;

    output_low(RX_CE);  //RX_CE = 0;//Power down RF Front end

    //Erase the current data array so that we know we are looking at actual received data
    data_array[0] = 0x00;
    data_array[1] = 0x00;
    data_array[2] = 0x00;
    data_array[3] = 0x00;

    //Clock in data, we are setup for 32-bit payloads
    for(i = 0 ; i < 4 ; i++) //4 bytes
    {
        for(j = 0 ; j < 8 ; j++) //8 bits each
        {
            temp <<= 1;
            output_high(RX_DATA);
            
            if (input(RX_DATA))
            {
               temp |= 0b00000001;
            }

            output_high(RX_CLK1); //RX_CLK1 = 1;
            output_low(RX_CLK1); //RX_CLK1 = 0;
        }

        data_array[i] = temp; //Store this byte
    }
    
    if(!(input(RX_DR))) //Once the data is clocked completely, the receiver should make DR go low
        printf("DR went low\n\r");
    
    printf("\n\rData Received:\n\r");
    printf("[0] : %x\n\r", data_array[0]);
    printf("[1] : %x\n\r", data_array[1]);
    printf("[2] : %x\n\r", data_array[2]);
    printf("[3] : %x\n\r", data_array[3]);

    output_high(RX_CE);  //RX_CE = 1; //Power up RF Front end
}

//This sends out the data stored in the data_array
//data_array must be setup before calling this function
void transmit_data(void)
{
    unsigned int i, j, temp, rf_address;

    output_high(TX_CE); //TX_CE = 1;

    //Clock in address
    //rf_address = 0b01110011; //Power-on Default for all units (on page 22-23)
	rf_address = 0b00000101;

    for(i = 0 ; i < 8 ; i++)
    {
        if((rf_address^7) == 1)
        {
            output_high(TX_DATA);   //TX_DATA = 1; Set Data high
        }
        else
        {
            output_low(TX_DATA);   //TX_DATA = 0; Set Data low
            rf_address <<= 1;
        }
        //TX_DATA = rf_address.7;
        output_high(TX_CLK1); //TX_CLK1 = 1;
        output_low(TX_CLK1);  //TX_CLK1 = 0;
        

    }
    
    //Clock in the data_array
    for(i = 0 ; i < 4 ; i++) //4 bytes
    {
        temp = data_array[i];
        
        for(j = 0 ; j < 8 ; j++) //One bit at a time
        {
            if (input(TX_DATA))
            {
               temp |= 0b10000000;
            }
            else
            {  
               output_high(TX_DATA);   //TX_DATA = 1;
            }
            //TX_DATA = temp.7;
            output_high(TX_CLK1);   //TX_CLK1 = 1;
            output_low(TX_CLK1); //TX_CLK1 = 0;
            
            temp <<= 1;
        }
    }
    
    output_low(TX_CE);  //TX_CE = 0; //Start transmission   
}

//2.4G Configuration - Receiver
//This setups up a RF-24G for receiving at 1mbps
void configure_receiver(void)
{
    unsigned int i;
    unsigned int config_setup;

    //During configuration of the receiver, we need RX_DATA as an output
    //PORTA = 0b.0000.0000;  
    set_tris_B(0b0000000001);  //0 = Output, 1 = Input (RX_DR is on RB8) (RX_DATA is on RB7)

    //Config Mode
    output_low(RX_CE);  //RX_CE = 0; 
    output_high(RX_CS); //RX_CS = 1;
    
    //Delay of 5us from CS to Data (page 25) is taken care of by the for loop
    
    //Setup configuration word
    config_setup = 0b001000110110111000000101; 
    //Look at pages 18-23 for more bit info
    //Bit 0: CRC generation/checking enabled; To check if system is RX or TX (1=enable, 0=disable)
    //Bit 1: 8 bit CRC (1=16bit, 0=8bit)
    //Bit 2-7: ADDR_W address width of the channel (00001 = 0x01)
    //Bit 8-23: ADDR1; Up to 5 byte address for RX channel 1 (0x236D)
   
    for(i = 0 ; i < 24 ; i++)
    {
        if((config_setup^23) == 1)
        {
           output_high(RX_DATA);
        }
        //RX_DATA = config_setup.23;
        output_high(RX_CLK1); //RX_CLK1 = 1;
        output_low(RX_CLK1);  //RX_CLK1 = 0;
        
        config_setup <<= 1;
    }
    
    //Configuration is active on falling edge of CS (page 25)
    output_low(RX_CE);  //RX_CE = 0; 
    output_low(RX_CS);  //RX_CS = 0;

    //After configuration of the receiver, we need RX_DATA as an input
    set_tris_B(0b0000000011); //0 = Output, 1 = Input (RX_DR is on RB8) (RX_DATA is on RB7)

    //Start monitoring the air
    output_high(RX_CE); //RX_CE = 1; 
    output_low(RX_CS);  //RX_CS = 0;

    printf("RX Configuration finished...\n\r");

}    

//2.4G Configuration - Transmitter
//This sets up one RF-24G for shockburst transmission
void configure_transmitter(void)
{
    unsigned int i;
    unsigned int config_setup;

    //Config Mode
    output_low(TX_CE);  //TX_CE = 0; 
    output_high(TX_CS); //TX_CS = 1;
    
    //Delay of 5us from CS to Data (page 30) is taken care of by the for loop
    
    //Setup configuration word
    config_setup = 0b001000110110111000000100; 
    //Look at pages 18-23 for more bit info
    //Bit 0: CRC generation/checking disabled; To check if system is RX or TX (1=enable, 0=disable)
    //Bit 1: 8 bit CRC (1=16bit, 0=8bit)
    //Bit 2-7: ADDR_W address width of the channel (00001 = 0x01)
    //Bit 8-23: ADDR1; Up to 5 byte address for RX channel 1 (0x236D)

    for(i = 0 ; i < 24 ; i++)
    {    
        if((config_setup^23) == 1)
        {
           output_high(TX_DATA);
        }
        //TX_DATA = config_setup.23;
        output_high(TX_CLK1); //TX_CLK1 = 1;
        output_low(TX_CLK1);  //TX_CLK1 = 0;
        
        config_setup <<= 1;
    }
    
    //Configuration is actived on falling edge of CS (page 10)
    output_low(TX_CE);  //TX_CE = 0; 
    output_low(TX_CS);  //TX_CS = 0;

    printf("TX Configuration finished...\n\r");
}

BUMP! anyone~

Alright… after much struggling, I have got the wireless module to work.

For those who are interested, here is the code.

Once again, I’m using CCS S compiler with dsPIC micro-controller for nRF2401a.

Here is the RX code:

#include  <30F3013.h>      //Include header file of dsPIC30F3013

#include <stdlib.h>
#include <stdio.h>

#use delay(clock = 20MHz,CRYSTAL = 20MHz)                  
// Oscillation freq. 20MHz
#use rs232(baud=38400,parity=N,UART1A,bits=8,stream=HOST)      
//XMIT=PIN_C13,RCV=PIN_C14

#define RX_CE       PIN_B4
#define RX_CS       PIN_B5
#define RX_CLK1     PIN_B6
#define RX_DATA     PIN_B7
#define RX_DR       PIN_B8

unsigned int8 data_array[4];


void boot_up(void);
void configure_receiver(void);
void receive_data(void);


void main()
{
    
    boot_up();

   while(1)
   {
    if(input(RX_DR))       //if(RX_DR == 1) //We have data!
        receive_data();
    else
        printf("No data found!\n\r");
    
    delay_ms(1000); //Have a second between transmissions just for evaluation 
    }   
}


void boot_up(void)
{

    set_tris_B(0b0100000000);  //0 = Output, 1 = Input (RX_DR is on RB8)
    
    printf("\n\rRF-24G Testing:\n\r");
    
    delay_ms(100);

    configure_receiver();

}


//2.4G Configuration - Receiver
//This setups up a RF-24G for receiving at 1mbps
void configure_receiver(void)
{
   unsigned int8 i;
   long config_setup, tempRX;
   
   //During configuration of the receiver, we need RX_DATA as an output
   set_tris_B(0b0100000000);  //0 = Output, 1 = Input (RX_DR is on RB8) (RX_DATA is on RB1)
   
   //Config Mode
   output_low(RX_CE);  //RX_CE = 0; 
   output_high(RX_CS); //RX_CS = 1;
   
   //Delay of 5us from CS to Data (page 25) is taken care of by the for loop
   delay_us(5);
   
   //Setup configuration word
   config_setup = 0b001000110110111100000011;             
   //Look at pages 18-23 for more bit info
   //Bit 0: CRC generation/checking enabled; To check if system is RX or TX (1=enable, 0=disable)
   //Bit 1: 8 bit CRC (1=16bit, 0=8bit)
   //Bit 2-7: ADDR_W address width of the channel (00001 = 0x01)
   //Bit 8-23: ADDR1; Up to 5 byte address for RX channel 1 (0x236D)

    
    for(i = 0 ; i < 24 ; i++)   //8 bit per hexa, per byte
    {    

      tempRX = 0x000000;
      if( ((tempRX|config_setup)&(0x800000)) == 0x800000)
      {
          output_high(RX_DATA);
      }
      else
      {
          output_low(RX_DATA);
      }
      
       //TX_DATA = config_setup.23;
      
      
      config_setup = config_setup << 1;
      delay_us(1/2);   //page 28 figure 15
      output_high(RX_CLK1); //TX_CLK1 = 1;
      delay_us(1/2);   //page 28 figure 15
      output_low(RX_CLK1);  //TX_CLK1 = 0;
      delay_us(1/2);   //page 28 figure 15
      output_low(RX_DATA);
    }
    
   //Configuration is active on falling edge of CS (page 27)
   output_low(RX_CE);  //RX_CE = 0; 
   output_low(RX_CS);  //RX_CS = 0;
   delay_us(1);   

   //After configuration of the receiver, we need RX_DATA as an input
   set_tris_B(0b0110000000); //TRISA = 0b.0000.0011;  //0 = Output, 1 = Input (RX_DR is on RB8) (RX_DATA is on RB7)
   
   //Start monitoring the air
   output_high(RX_CE); //RX_CE = 1; 
   output_low(RX_CS);  //RX_CS = 0;
   delay_us(5);
   
   printf("RX Configuration finished...\n\r");

}    


//This will clock out the current payload into the data_array
void receive_data(void)
{
    unsigned int8 i, j, tempRX;
   
    output_low(RX_CE);  //RX_CE = 0;//Power down RF Front end
   //delay_us(203);

    //Erase the current data array so that we know we are looking at actual received data
    data_array[0] = 0x00;
    data_array[1] = 0x00;
    data_array[2] = 0x00;
    data_array[3] = 0x00;

    tempRX = 0x00;

    //Clock in data, we are setup for 32-bit payloads
    for(i = 0 ; i < 4 ; i++) //4 bytes
    {
        for(j = 0 ; j < 8 ; j++) //8 bits each
        {
            tempRX = tempRX << 1;
          delay_us(1/2);   //page 28 figure 15
            output_high(RX_CLK1);   //RX_CLK1 = 1
               
          //output_high(RX_DATA);
            if(input(RX_DATA))
            {
                tempRX |= 0x01;
            }

             delay_us(1/2);   //page 28 figure 15
                output_low(RX_CLK1);   //RX_CLK1 = 0         
             delay_us(1/2);   //page 28 figure 15
             
        }

       // tempRX = data_array[i]; //Store this byte
        data_array[i] = tempRX;
    }
    
    if(!(input(RX_DR))) //Once the data is clocked completely, the receiver should make DR go low
        printf("DR went low\n\r");
    
    printf("\n\rData Received:\n\r");
    printf("[0] : %x\n\r", data_array[0]);
    printf("[1] : %x\n\r", data_array[1]);
    printf("[2] : %x\n\r", data_array[2]);
    printf("[3] : %x\n\r", data_array[3]);

    output_high(RX_CE);  //RX_CE = 1; //Power up RF Front end
}

TX:

#include  <30F3013.h>      //Include header file of dsPIC30F3013

#include <stdlib.h>
#include <stdio.h>

#use delay(clock = 20MHz,CRYSTAL = 20MHz)                  
// Oscillation freq. 20MHz
#use rs232(baud=38400,parity=N,UART1A,bits=8,stream=HOST)      
//XMIT=PIN_C13,RCV=PIN_C14


#define TX_CE      PIN_B0
#define TX_CS      PIN_B1
#define TX_CLK1    PIN_B2
#define TX_DATA    PIN_B3

void boot_up(void);
void configure_transmitter(void);
void transmit_data(void);

unsigned int8 data_array[4];
int counter;

void main()
{  
    boot_up();
   counter = 0;   

   while(1)
   {
   delay_ms(1000);
   data_array[0] = 0x10;
   data_array[1] = 0x20;
   data_array[2] = 0x30;
   data_array[3] = counter++;   
   
   transmit_data();
   }
}

void boot_up(void)
{
   
    printf("\n\rRF-24G Testing:\n\r");
    
    delay_ms(100);

    configure_transmitter();

}

//2.4G Configuration - Transmitter
//This sets up one RF-24G for shockburst transmission
void configure_transmitter(void)
{
    unsigned int8 i;
    long config_setup, tempTX;
   
   delay_us(1/10);   //page 25 figure 12

    //Config Mode
    output_low(TX_CE);  //TX_CE = 0; 
    output_high(TX_CS); //TX_CS = 1;
    
    //Delay of 5us from CS to Data (page 30) is taken care of by the for loop
    delay_us(5);

    //Setup configuration word
      config_setup = 0b001000110110111100000010; 
    //Look at pages 18-23 for more bit info
    //Bit 0: CRC generation/checking disabled; To check if system is RX or TX (1=enable, 0=disable)
    //Bit 1: 8 bit CRC (1=16bit, 0=8bit)
    //Bit 2-7: ADDR_W address width of the channel
    //Bit 8-23: ADDR1; Up to 5 byte address for RX channel 1



    for(i = 0 ; i < 24 ; i++)   //8 bit per hexa, per byte
    {    

         tempTX = 0x000000;
           if( ((tempTX|config_setup)&(0x800000)) == 0x800000)
         //if(input(TX_CS))
           {
               output_high(TX_DATA);
           }
         else
         {
            output_low(TX_DATA);
         }
   
           //TX_DATA = config_setup.23;
           
           //tempTX = tempTX << 1;
         config_setup = config_setup << 1;
   
         delay_us(1/2);   //page 27 figure 14
         output_high(TX_CLK1); //TX_CLK1 = 1;
         delay_us(1/2);   //page 27 figure 14
         output_low(TX_CLK1);  //TX_CLK1 = 0;
         delay_us(1/2);   //page 27 figure 14
         output_low(TX_DATA);
    }
           
      //standby mode
       output_low(TX_CE);  //TX_CE = 0; 
       output_low(TX_CS);  //TX_CS = 0;   //Configuration is actived on falling edge of CS (page 17)
       delay_us(1);
       output_low(TX_DATA);
   
       printf("TX Configuration finished...\n\r");
}


void transmit_data(void)
{
    unsigned int8 i, j, k, tempTX, ADDR1;
   
    delay_us(1/20);      //page 28 figure 15
    output_high(TX_CE); //TX_CE = 1;
    output_low(TX_CS);  //TX_CS = 0;

    //Delay of 5us from CS to Data (page 30) is taken care of by the for loop
    delay_us(5);

    //Clock in address
    ADDR1 = 0b11100111; //Power-on Default for all units (on page 19)
   
   for(k = 0 ; k < 8 ; k++)
   {

       if( (ADDR1 & 0x80) == 0x80 )
           {
               output_high(TX_DATA);   //TX_DATA = 1; Set Data high
           }
           else
           {
               output_low(TX_DATA);   //TX_DATA = 0; Set Data low
           }
         
         delay_us(1/2);   //page 28 figure 15
         output_high(TX_CLK1); //TX_CLK1 = 1;
         delay_us(1/2);   //page 28 figure 15
         output_low(TX_CLK1);  //TX_CLK1 = 0;
         delay_us(1/2);   //page 28 figure 15
         output_low(TX_DATA);   //TX_DATA = 0; Set Data low

         ADDR1 = ADDR1 << 1;   //Left Shift to get next bit 
   }

    //Clock in the data_array
    for(i = 0 ; i < 4 ; i++)
    {
      tempTX = data_array[i];

      for(j = 0 ; j < 8 ; j++) //One bit at a time
       {
                       
           if( ((tempTX)&(0x80)) == 0x80)
           {
               output_high(TX_DATA);   //TX_DATA = 1; Set Data high
           }
           else
           {
               output_low(TX_DATA);   //TX_DATA = 0; Set Data low
           }
           //TX_DATA = rf_address.7;

         delay_us(1/2);   //page 28 figure 15
           output_high(TX_CLK1); //TX_CLK1 = 1;
         delay_us(1/2);   //page 28 figure 15
           output_low(TX_CLK1);  //TX_CLK1 = 0;
         delay_us(1/2);   //page 28 figure 15
         output_low(TX_DATA);   //TX_DATA = 0; Set Data low

           tempTX = tempTX << 1;   //Left Shift to get next bit 
      }
    
   }   
         //standby mode
         output_low(TX_CE);  //TX_CE = 0; 
         output_low(TX_CS);  //TX_CS = 0;
         delay_us(1);
         output_low(TX_DATA);
   
}

Feel free to ask me any question. I will help with the best of my knowledge!

P.S. some of the comments are wrong. So please do read with care. Always have the datasheet on hand!