NRF24L01+ Communication issue Tx & Rx

Discussion about wireless devices

NRF24L01+ Communication issue Tx & Rx

Postby asking » Tue Feb 11, 2014 10:43 am

Hi All,

I have been trying hard to setup Tx & Rx setup. I just want to on the led when some data from tx is send to receiver and on condition matching of received data LED should be turned on. I have written simple code for Tx & Rx just for functionality test setup as per nordic support. But i doubt that i am making some software programming issue related to array_data. So please review and check whats wrong ?

i am confused regarding the array_data[3] means there are 3 bytes of payload available (default configuration of NRF24L01+) i think i am making mistake in sending the data_array please help me with code..how to transmit payload of 3 bytes ? one by one ?

Thanks.




What's changed to NRF24L01+ Chip

1) only PRIM_RX is changed for transmitter and receiver.
2) payload data_array to be given to transmitter.

rest of the things are by default and ok for normal Tx & Rx test.





Transmitter Code
Code: Select all
#include <xc.h>
#include <htc.h>

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & CP_OFF);
#define   _XTAL_FREQ   20000000


#include "stdint.h"
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C

/* Bit Mnemonics */

/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0

/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0

/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0

/* setup of address width */
#define AW          0 /* 2 bits */

/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */

/* RF setup register */
#define PLL_LOCK    4
#define RF_DR_HIGH  3
#define RF_PWR      1 /* 2 bits */

/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0

/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */

/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0

/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5

/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define NOP1          0xFF

#define nrf24_CONFIG ((1 << MASK_RX_DR)|(1<<EN_CRC)|(0<<CRCO))

/// hardware spi pin defined
#define LED_PIN      PORTAbits.RA1 // led test
#define CS_Pin       PORTBbits.RB0//          //set port as output
#define CE_Pin       PORTBbits.RB4         //set port as output
#define SCK_Pin      PORTBbits.RB1        //set port as output
#define Mosi_Pin     PORTBbits.RB2         //set port as output
#define Miso_Pin     PORTBbits.RB3        //set port as input
#define HIGH         1
#define LOW          0



void nrf24_ce_digitalwrite(uint8_t state)
{
if (state)
{
CE_Pin = 1;
}
else
{
CE_Pin = 0;
}
}


void nrf24_csn_digitalwrite(uint8_t state)
{
if (state)
{
CS_Pin = 1;
}
else
{
CS_Pin = 0;
}
}


void nrf24_sck_digitalwrite(uint8_t state)
{
if (state)
{
SCK_Pin = 1;
}
else
{
SCK_Pin = 0;
}
}


void nrf24_mosi_digitalwrite( uint8_t state)
{
if (state)
{
Mosi_Pin = 1;
}
else
{
Mosi_Pin = 0;
}
}



/* software spi routine */
uint8_t spi_transfer(uint8_t tx)
{
     uint8_t i = 0;
     uint8_t rs = 0;

    nrf24_sck_digitalwrite(LOW);

    for(i=0;i<8;i++)
    {

        if(tx & 0x80) // msbit first spi standard
        {
            nrf24_mosi_digitalwrite(HIGH);
        }
        else
        {
            nrf24_mosi_digitalwrite(LOW);
        }

        nrf24_sck_digitalwrite(HIGH);

        tx = tx << 1;
        if(Miso_Pin == 1)
        {
            rs |= 0x01;
        }
        nrf24_sck_digitalwrite(LOW);
    }
    return rs;
}


/* send and receive multiple bytes over SPI */ // checked with mirf
void nrf24_transferSync(uint8_t  *dataout,uint8_t *datain,uint8_t len)
{
    uint8_t i;

    for(i=0;i<len;i++){
       datain[i] = spi_transfer(dataout[i]);
    }
}


//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len)
{
    uint8_t i;

    for(i=0;i<len;i++){
      spi_transfer(dataout[i]);
    }
}

void nrf24_configRegister(uint8_t reg, uint8_t value)
{
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    spi_transfer(value);
    nrf24_csn_digitalwrite(HIGH);
}

void nrf24_powerUpTx() // checked with mirf
{
   // PTX = 1;
   
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));

}

void nrf24_init()
{
   TRISB = 0b00001000;
   TRISA = 0b00000000;
    CMCON  |= 7;
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
}


void nrf24_send(uint8_t* value)   // check with mirf
{
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);

    /* Set to transmitter mode , Power up if needed */
    nrf24_powerUpTx();
   nrf24_csn_digitalwrite(LOW);
   spi_transfer(FLUSH_TX);
   nrf24_csn_digitalwrite(HIGH);
   

    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);

    /* Write cmd to write payload */
    spi_transfer(W_TX_PAYLOAD);

    /* Write payload */
    nrf24_transmitSync(value,3);

    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);

    /* Start the transmission */
    nrf24_ce_digitalwrite(HIGH);
__delay_us(50);
nrf24_ce_digitalwrite(LOW);

}

uint8_t data_array[3];

void main()
{

nrf24_init();
__delay_ms(50);
nrf24_powerUpTx();
__delay_ms(10);
nrf24_csn_digitalwrite(LOW);
spi_transfer(FLUSH_TX);
nrf24_csn_digitalwrite(HIGH);

__delay_ms(10);

data_array[0] = 0x6F;
data_array[1] = 0X12;
data_array[2] = 0x12;

while(1)
{

nrf24_send(data_array);
__delay_ms(15); // wait some time
}


}








Receiver code

Code: Select all
#include <xc.h>
#include <htc.h>

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & CP_OFF);
#define   _XTAL_FREQ   20000000


#include "stdint.h"
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C

/* Bit Mnemonics */

/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0

/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0

/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0

/* setup of address width */
#define AW          0 /* 2 bits */

/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */

/* RF setup register */
#define PLL_LOCK    4
#define RF_DR_HIGH  3
#define RF_PWR      1 /* 2 bits */

/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0

/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */

/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0

/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5

/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define NOP1          0xFF

#define nrf24_CONFIG ((1 << MASK_RX_DR)|(1<<EN_CRC)|(0<<CRCO))

/// hardware spi pin defined
#define LED_PIN      PORTAbits.RA1 // led test
#define CS_Pin       PORTBbits.RB0//          //set port as output
#define CE_Pin       PORTBbits.RB4         //set port as output
#define SCK_Pin      PORTBbits.RB1        //set port as output
#define Mosi_Pin     PORTBbits.RB2         //set port as output
#define Miso_Pin     PORTBbits.RB3        //set port as input
#define HIGH         1
#define LOW          0



void nrf24_ce_digitalwrite(uint8_t state)
{
if (state)
{
CE_Pin = 1;
}
else
{
CE_Pin = 0;
}
}


void nrf24_csn_digitalwrite(uint8_t state)
{
if (state)
{
CS_Pin = 1;
}
else
{
CS_Pin = 0;
}
}


void nrf24_sck_digitalwrite(uint8_t state)
{
if (state)
{
SCK_Pin = 1;
}
else
{
SCK_Pin = 0;
}
}


void nrf24_mosi_digitalwrite( uint8_t state)
{
if (state)
{
Mosi_Pin = 1;
}
else
{
Mosi_Pin = 0;
}
}



/* software spi routine */
uint8_t spi_transfer(uint8_t tx)
{
     uint8_t i = 0;
     uint8_t rs = 0;

    nrf24_sck_digitalwrite(LOW);

    for(i=0;i<8;i++)
    {

        if(tx & 0x80) // msbit first spi standard
        {
            nrf24_mosi_digitalwrite(HIGH);
        }
        else
        {
            nrf24_mosi_digitalwrite(LOW);
        }

        nrf24_sck_digitalwrite(HIGH);

        tx = tx << 1;
        if(Miso_Pin == 1)
        {
            rs |= 0x01;
        }
        nrf24_sck_digitalwrite(LOW);
    }
    return rs;
}




/* send and receive multiple bytes over SPI */ // checked with mirf
void nrf24_transferSync(uint8_t  *dataout,uint8_t *datain,uint8_t len)
{
    uint8_t i;

    for(i=0;i<len;i++){
       datain[i] = spi_transfer(dataout[i]);
    }
}


//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len)
{
    uint8_t i;

    for(i=0;i<len;i++){
      spi_transfer(dataout[i]);
    }
}

void nrf24_configRegister(uint8_t reg, uint8_t value)
{
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    spi_transfer(value);
    nrf24_csn_digitalwrite(HIGH);
}

void nrf24_powerUpTx() // checked with mirf
{
   // PTX = 1;

    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
   
}


void nrf24_powerUpRx() // checked with mirf
{
   // PTX = 0;
   
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));
   
}

void nrf24_init()
{
   TRISB = 0b00001000;
   TRISA = 0b00000000;
    CMCON  |= 7;
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
}


void nrf24_send(uint8_t* value)   // check with mirf
{
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);

    /* Set to transmitter mode , Power up if needed */
    nrf24_powerUpTx();
   nrf24_csn_digitalwrite(LOW);
   spi_transfer(FLUSH_TX);
   nrf24_csn_digitalwrite(HIGH);
   

    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);

    /* Write cmd to write payload */
    spi_transfer(W_TX_PAYLOAD);

    /* Write payload */
    nrf24_transmitSync(value,3);

    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);

    /* Start the transmission */
    nrf24_ce_digitalwrite(HIGH);

}

/* Read single register from nrf24 */
void nrf24_readRegister(uint8_t reg,uint8_t *value,uint8_t len) //checked with mirf
{
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
    nrf24_transferSync(value,value,len);
    nrf24_csn_digitalwrite(HIGH);
   }



uint8_t nrf24_getStatus()    // checked with mirf
{
    uint8_t rv;
    nrf24_readRegister(STATUS,&rv,1);
    return rv;
}


uint8_t nrf24_dataReady() // check with mirf
// checks if data is available for reading

{
    // See note in getData() function - just checking RX_DR isn't good enough
    uint8_t status = nrf24_getStatus();

 // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
   return status & (1 << RX_DR);
}


/* Reads payload bytes uint8_to data array */
uint8_t nrf24_getData(uint8_t *data1)  // check with mirf
{
    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);

    /* Send cmd to read rx payload */
    spi_transfer(R_RX_PAYLOAD);

    /* Read payload */
    nrf24_transferSync(data1,data1,3);

    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);

    /* Reset status register */
    nrf24_configRegister(STATUS,(1<<RX_DR));
}


/*
uint8_t wl_module_data_ready ( ) 
/ / checks if data is available for reading
{
    if  ( PTX )  return  0 ;
    uint8_t status ;
    / / Read wl_module status
    wl_module_CSN_lo ;                                 / / Pull down chip select
    status = spi_fast_shift ( NOP ) ;                / / Read status register
    wl_module_CSN_hi ;                                 / / Pull up chip select
    return status &  ( 1 << RX_DR ) ;
}

*/

uint8_t data_array[3];


void main()
{
//data_array[0] = 0x6F;
//data_array[1] = 0X12;
//data_array[2] = 0x12;
uint8_t temp; // return status
uint8_t count = 0;
nrf24_init();
__delay_ms(50);
nrf24_powerUpRx();

nrf24_csn_digitalwrite(LOW);
spi_transfer(FLUSH_RX);
nrf24_csn_digitalwrite(HIGH);

__delay_ms(10);



while(1)
{
while(nrf24_dataReady());
temp = nrf24_getData(data_array[0]);
count = data_array[0];

if(count == 0x6F)
{
LED_PIN = HIGH;
}
else
{
LED_PIN = LOW;
}
__delay_ms(10);
}
}

asking
 
Posts: 5
Joined: Tue Feb 11, 2014 7:33 am

Re: NRF24L01+ Communication issue Tx & Rx

Postby brennen » Wed Feb 12, 2014 1:40 pm

You definitely need to turn on the PWR_UP bit and set the payload width at the receiver to match the payload size you're sending at the TX. The RX should have the CE pin high whenever it's receiving data. The TX should pulse CE high after a payload is loaded into the radio. The first thing to do is make sure you get a TX_DS interrupt once you transmit a packet from your TX. *Only* after that can you try to receive a packet with your RX.
brennen
Site Admin
 
Posts: 395
Joined: Sun Aug 17, 2008 2:15 pm

Re: NRF24L01+ Communication issue Tx & Rx

Postby asking » Thu Feb 13, 2014 10:31 am

Hi Brennen,

i just refered the datasheet, if auto_ack is enabled then bit TX_DS is only valid when the receiver gets the data. So you mean to say that in order to make setup functionality test i should disabled the auto-ack on transmitter and then just trigger CE for more than 10us when TX Fifo is loaded with data then TX_DS will show the status regarding the transmission fired from tx side ? right ?
asking
 
Posts: 5
Joined: Tue Feb 11, 2014 7:33 am

Re: NRF24L01+ Communication issue Tx & Rx

Postby brennen » Thu Feb 13, 2014 3:26 pm

Yes, you're correct. So I would suggest starting out by turning off auto-acknowledge, so that way you can test one end of the link at a time.
brennen
Site Admin
 
Posts: 395
Joined: Sun Aug 17, 2008 2:15 pm

Re: NRF24L01+ Communication issue Tx & Rx

Postby asking » Thu Feb 13, 2014 5:47 pm

Hi

i have tried to disable the auto acknolwedgement but still TX_DS is not triggering. I have checked the VDD_PA and i get pulse around 95-100HZ means its transmitting data but TX_DS is not triggered. I have programmed LED to be on if TX_DS is 1. any other thing to check ?
asking
 
Posts: 5
Joined: Tue Feb 11, 2014 7:33 am

Re: NRF24L01+ Communication issue Tx & Rx

Postby brennen » Fri Feb 14, 2014 1:07 pm

Did you clear the PRIM_RX bit for the TX? Are you pulsing CE high after you upload the packet to the TX? If so, how are you determining that you're not getting the TX_DS interrupt? Are you looking at the IRQ line and waiting for it to go low? Or are you just polling the STATUS register value?
brennen
Site Admin
 
Posts: 395
Joined: Sun Aug 17, 2008 2:15 pm

Re: NRF24L01+ Communication issue Tx & Rx

Postby asking » Sat Feb 15, 2014 1:17 am

Hi,

Actually i have cleared the bit PRIM_RX. and as per datasheet VDD_PA i am getting high pulses too

Image
Image
Image

but i think there's some noise. it should be flat top. Means my data is transmitted on every high on VDD_PA and then low. But i don't understand why TX_FULL is always getting to be 1. whatever i do. So for example i just removed all other commands for sending, then also status when i read from TX_FULL was giving output LED ON. i have checked with Proteus Software for SPI Debugger and i can see values which needed to be transmitted. Then i looked at oscilloscope in proteus and check all SPI Signals they seems to be fine. So now i have decided to make another Test Setup.

Code: Select all
uint8_t status;

csn_low;
spi_transfer(NOP);
csn_high;

if (status & (1<<TX_FULL))
{
LED = ON;
}

else
{
LED = OFF;
}
asking
 
Posts: 5
Joined: Tue Feb 11, 2014 7:33 am

Re: NRF24L01+ Communication issue Tx & Rx

Postby brennen » Sun Feb 16, 2014 1:47 am

So are you getting the TX_DS interrupt or not? That is the only way you can tell in software, at least, that you have successfully transmitted the packet (this is strictly with auto-acknowledge/auto-retry turned off).
brennen
Site Admin
 
Posts: 395
Joined: Sun Aug 17, 2008 2:15 pm


Return to Wireless

Who is online

Users browsing this forum: No registered users and 1 guest

cron