Need some help at nRF24L01 communication problem

Hi there~ :slight_smile:

A strange thing happens when using nRF24L01 to communicate, I wonder if anyone who can give some advices for me.

Here is the situation:

Both board A and board B (they’re the same) have a ATmega32L and a nRF24L01 module.

Step1: At first, A as transmitter and B as receiver, A sends a package to B until B receives it successfully.

Step2: Then A swtich to receive mode, B switch to transmit mode. B sends data to A constantly.

If it’s the first communication after “Board Power Up”, Step1 and Step2 succeed. But after I push the RESET button at each board and want to do the second time, Step1 succeeds and Step2 fails~ I’ve tried many times that I got a conclusion: If I want both Step1 and Step2 succeed, I have to " Cut the Power on Board A and Re-Power Up Board A ". The re-booting on Board A seems have no effect at receving data…

I’m quite sure that the program is correct~ Is there anything I mis-noticed :?: Hope to hear the advices~

Thank U guys!! :wink:

Do you have some sort of time-out in your code if A never receives the data back from B? If not, there’s a possibility that both A and B could both get stuck as receivers if you do the reset sequence at the right times. If you can time out and assume the packet was dropped, then A could then change to a TX, transmit to B again, and B would be reset and would respond.

Let me say it in this way~

A as TX, B as RX, A sends a package to B. When B receives the package, it sends ACK signal to A. This is Step1, and it will succeed.

Then B switch to Tx, A switch to Rx, B sends packages to A constantly.

This is Step2~ and it will only succeed when it’s the first time Board A power on. It fails after I reset Board A.

Will it be a hardware problem?

So if you reset A but not B during step 2, then you’re leaving B as TX, but A is also going to boot up as TX. B then has no way to know that A is now a TX and A has no way to know that B is a TX, so they will both stay TX forever. Unless I’m still not understanding you, while in TX mode, both A and B, need to be able to know whether or not the other module is receiving packets. Otherwise, you could very easily end up in the state that you mentioned. This is the purpose of Enhanced Shockburst, because the 24L01 does it in hardware for you.

Umm~ What I mean “Reset” is that boot Both A and B~

That’s after the first time I tried Step1 and Step2, I boot A and B, let them do Step1 and Step2 once again. Then Step1 passed, Step2 failed… :cry:

Not sure what your problem is, then. You should probably print out your 24L01’s register settings once you fail Step 2, as this will give you some insight into what’s actually going on.

But how can it explains that the first time Board A and Board B power up, Step1 and Step2 both work?

Sounds like a problem within your software. If you post the code, someone may spot the problem. Otherwise its just a guessing game.

Which part of the software should I post?

The parts that are relative to interfacing to your 24L01.

//Configuration words initialize
//------------------------------------------------------------------------------

void nRF24L01_Tx_Config_Words(void)

{

CE_Low;

CSN_High;

SCK_Low;

CE_Low;

nRF24L01_FLUSH_Tx(); // Clear Tx buffer

nRF24L01_Write_Reg(CONFIG,0x0C); // Power down,2byte CRC

nRF24L01_Write_Reg(EN_AA,0x01); // Enable Auto ACK

nRF24L01_Write_Reg(EN_RXADDR,0x01); // Enable data pipe 0

nRF24L01_Write_Reg(SETUP_RETR,RE_TRANSMIT_TIME); // 336us*2

nRF24L01_Write_Reg(RX_PW_P0,PAYLOAD_LENGTH); // 2 bytes payload data

nRF24L01_Write_Reg(STATUS,0x70); // Clear all the interrupts

nRF24L01_Write_Reg(CONFIG,0x0E); // Power up

DelayXms(2);

nRF24L01_Write_TxAddr_P0();

nRF24L01_Write_RxAddr_P0();

}

void nRF24L01_Rx_Config_Words(void)

{

CE_Low;

CSN_High;

SCK_Low;

CE_Low;

nRF24L01_FLUSH_Tx(); // Clear Tx buffer

nRF24L01_FLUSH_Rx(); // Clear Rx buffer

nRF24L01_Write_Reg(CONFIG,0x0D); // Power down

nRF24L01_Write_Reg(EN_AA,0x01); // Enable AutoAck

nRF24L01_Write_Reg(EN_RXADDR,0x01); // Enable data pipe 0

nRF24L01_Write_Reg(SETUP_RETR,RE_TRANSMIT_TIME); // 336us*2

nRF24L01_Write_Reg(RX_PW_P0,PAYLOAD_LENGTH); // 2 bytes payload data

nRF24L01_Write_Reg(STATUS,0x70); // Clear all the interrupts

nRF24L01_Write_Reg(CONFIG,0x0F); // Power up

DelayXms(2);

nRF24L01_Write_TxAddr_P0();

nRF24L01_Write_RxAddr_P0();

}

//Actions
//------------------------------------------------------------------------------

void nRF24L01_Tx_Payload(void)

{

nRF24L01_FLUSH_Tx();

nRF24L01_Write_Payload(); // Write payload data

CE_High;

DelayXus(20);

CE_Low;

while( PINB&(1<<IRQ) ); // Wait for Tx or Max interrupt

nrf24l01_status = nRF24L01_Read_Reg(STATUS); // Read the STATUS

switch( nrf24l01_status & 0xF0 )

{

case 0x20: LED_G_Flash; // Transmit sign

nRF24L01_Write_Reg(STATUS,0x20); // Clear TX_DS

nrf24l01_status = PACKAGE_SENT; // Store status

break;

case 0x10: LED_R_On; // Package lost

nRF24L01_Write_Reg(STATUS,0x10); // Clear MAX_RT

nrf24l01_status = PACKAGE_LOST; // Store status break;

}

nRF24L01_FLUSH_Tx();

}

void nRF24L01_Rx_Payload(void)

{

CE_High;

while( PINB&(1<<IRQ) ); // Wait for Rx interrupt

nRF24L01_Read_Payload();

nrf24l01_status = nRF24L01_Read_Reg(STATUS); // Read the STATUS

switch( nrf24l01_status & 0xF0 )

{

case 0x60: //LED_G_Flash;

nRF24L01_Write_Reg(STATUS,0x60); // Clear RX_DR

nrf24l01_status = PACKAGE_RECEIVED; // Store status

break;

}

nRF24L01_FLUSH_Rx();

}

//Partial operation
//------------------------------------------------------------------------------

// R/W byte

u08 nRF24L01_RW_Byte(u08 data)

{

SPDR=data;

while( !(SPSR&(1<<SPIF)) );

SPSR|=(1<<SPIF);

return SPDR;

}

// Read Register

u08 nRF24L01_Read_Reg(u08 reg)

{

u08 status_buffer=0;

CSN_Low;

status_buffer = nRF24L01_RW_Byte(reg);

status_buffer = nRF24L01_RW_Byte(NO_OP);

CSN_High;

return status_buffer;

}

// Write Register

void nRF24L01_Write_Reg(u08 reg,u08 value)

{

CSN_Low;

nRF24L01_RW_Byte(0x20+reg);

nRF24L01_RW_Byte(value);

CSN_High;

}

// Read Payload

void nRF24L01_Read_Payload(void)

{

u08 counter=0;

CSN_Low;

nRF24L01_RW_Byte(R_RX_PAYLOAD);

for(counter=0;counter<PAYLOAD_LENGTH;counter++)

{ nrf24l01_rx_buffer[counter] = nRF24L01_RW_Byte(NO_OP); }

CSN_High;

}

// Write Payload

void nRF24L01_Write_Payload(void)

{

u08 counter=0;

CSN_Low;

nRF24L01_RW_Byte(W_TX_PAYLOAD);

for(counter=0;counter<PAYLOAD_LENGTH;counter++)

{ nRF24L01_RW_Byte( nrf24l01_tx_buffer[counter] ); }

CSN_High;

}

// Write Tx address P0

void nRF24L01_Write_TxAddr_P0(void)

{

CSN_Low;

nRF24L01_RW_Byte(0x20+TX_ADDR);

nRF24L01_RW_Byte(0xCC);

nRF24L01_RW_Byte(0x3C);

nRF24L01_RW_Byte(0xC3);

nRF24L01_RW_Byte(0x3C);

nRF24L01_RW_Byte(0xCC);

CSN_High;

}

// Write Rx address P0

void nRF24L01_Write_RxAddr_P0(void)

{

CSN_Low;

nRF24L01_RW_Byte(0x20+RX_ADDR_P0);

nRF24L01_RW_Byte(0xCC);

nRF24L01_RW_Byte(0x3C);

nRF24L01_RW_Byte(0xC3);

nRF24L01_RW_Byte(0x3C);

nRF24L01_RW_Byte(0xCC);

CSN_High;

}

// Clear Tx buffer

void nRF24L01_FLUSH_Tx(void)

{

CSN_Low;

nRF24L01_RW_Byte(0xE1);

CSN_High;

}

// Clear Rx buffer

void nRF24L01_FLUSH_Rx(void)

{

CSN_Low;

nRF24L01_RW_Byte(0xE3);

CSN_High;

}

//Constant Define
//------------------------------------------------------------------------------

//nRF24L01 SPI Commands

#define READ_REG 0x00

#define WRITE_REG 0x20

#define R_RX_PAYLOAD 0x61

#define W_TX_PAYLOAD 0xA0

#define CLR_TX 0xE1

#define CLR_RX 0xE2

#define REUSE_TX_PL 0xE3

#define NO_OP 0xFF

//nRF24L01 Register_Status value

#define PACKAGE_SENT 0x01

#define PACKAGE_LOST 0x02

#define PACKAGE_RECEIVED 0x03

//nRF24L01 Constant

#define PAYLOAD_LENGTH 0x02

#define RE_TRANSMIT_TIME 0x02

//nRF24L01 SPI Registers address

//Config retister

#define CONFIG 0x00

//Enable ACK

#define EN_AA 0x01

//Enable address receive

#define EN_RXADDR 0x02

//Set address width

#define SETUP_AW 0x03

//Enable auto re-transmit

#define SETUP_RETR 0x04

//RF channel

#define RF_CH 0x05

//RF register

#define RF_SETUP 0x06

//RF status

#define STATUS 0x07

//Transmit observer

#define OBSERVE_TX 0x08

//Carrier detect

#define CD 0x09

//Pipe 0-5 receive address

#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

//Transmit address

#define TX_ADDR 0x10

//Receive payload width,pipe 0-5

#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

//FIFO status

#define FIFO_STATUS 0x17

//Register default value

#define CONFIG_BIT0 0x5B

#define CONFIG_BIT1 0x01

#define CONFIG_BIT2 0x01

#define CONFIG_BIT3 0x02

#define CONFIG_BIT4 0x0A

#define CONFIG_BIT5 0x00

#define CONFIG_BIT6 0x0F

Do you have a way to print out your register values such that you could show them here? If so, initialize your 24L01, and before doing anything else, print out all of the 24L01 registers (preferrably with addresses and values both in hex). Showing that here would make debugging simpler than plowing through code (at least for me).

OK~I’ll see if I can do so~ Thanks a lot!! :smiley: :slight_smile:

Maybe it’ll take some time…

Do the follow 3 things whenever TX/RX done, then you can do other RX/TX.

  1. Clear TX FIFO.

  2. Clear RX FIFO.

  3. Clear IRQ.

How?

  1. SPI_WriteReg(0xE1); // FLUSH_TX

  2. SPI_WriteReg(0xE2); // FLUSH_RX

  3. SPI_WriteRegValue(0x27,0x70); // Clear IRQ

After that, the STATUS(0x07) register will be 0x0E, then OK, you can do other TX/RX

DavidLu:
Do the follow 3 things whenever TX/RX done, then you can do other RX/TX.

  1. Clear TX FIFO.

  2. Clear RX FIFO.

  3. Clear IRQ.

I wouldn’t recommend manually clearing your FIFO unless you really need to (just in case one were to sneak in before you notice). Bringing CE low at the RX and then reading the FIFO will clear packets that are read out automatically, as will transmitting the packets loaded in the FIFO on a TX. You do indeed have to manually clear the IRQs at both the RX and TX, though.