Problem with nrf24l01 ACK Comunication, can't make it to work

Hello, I need help with an issue I'm having in establishing a conversation between two NRF24L01 modules using ACK (Acknowledgement).
I'm using two Arduino Nano boards as MCUs (Microcontroller Units), and I'm employing NRF24L01+PA+LNA modules with the regulator of 3.3v incorporated.
When I conduct a test using the simple method of sending a message from a transmitter and receiving it on a receiver, it works correctly. However, when I try to incorporate the functionality of ACK, I cannot make it work.
I send the message from the transmitter, but the receiver doesn't receive anything. I know this because I use a logic analyzer to verify the operation of both modules.
I've read the datasheet several times, and I'm doing everything that I'm supposed to do, so it must be an issue that I can't resolve. That's why I'm seeking help from someone who might have more experience.
I'm not using any libraries as I'm doing this to learn. I decided to develop my own library responsible for configuration management, sending, receiving, etc.

NRF24_Init is called from both NRF24L01 modules to perform the initial configuration. Then, NRF24_TxMode is called from the transmitter, and NRF24_RxMode is called from the receiver.

NRF24_Transmit is the function responsible for sending the packet. In it, I check in a while loop if the ACK has been received by consulting the status register.

The ReadReg and WriteReg functions are functions I created to read from and write to the specified registers.

Ce_Disable and CE_Enable are used to enable and disable the NRF24L01. Select_Slave_SPI and Unselect_Slave_SPI are functions that do what their names suggest; they are for SPI communication.

If I understand correctly, from the transmitter, I have to enable data pipe 0, which will be where the ACK is received. In the receiver, I simply indicate the pipe I use for communication, and the sending and receiving of ACKs are managed automatically by the NRF24L01.

void NRF24_Init(void){
	CE_Disable();

	nrf24_WriteReg(CONFIG, 0x08); 	
	nrf24_WriteReg(EN_AA, 0x00);	
	nrf24_WriteReg(EN_RXADDR, 0x00);	
	nrf24_WriteReg(SETUP_AW, 0x03); 
	nrf24_WriteReg(SETUP_RETR, 0x15);	
	nrf24_WriteReg(RF_CH, 0);	
	nrf24_WriteReg(RF_SETUP, 0x03);	

    	CE_Enable();
}

void NRF24_TxMode(uint8_t *address, uint8_t channel){
	CE_Disable();
	nrf24_WriteReg(RF_CH, channel);

	nrf24_WriteRegMulti(TX_ADDR, address, 5);
	nrf24_WriteReg(EN_RXADDR, 0x01);
	nrf24_WriteReg(EN_AA, 0x01);
	nrf24_WriteRegMulti(RX_ADDR_P0, address, 5);

	uint8_t config = nrf24_ReadReg(CONFIG); 
	config = config | (1 << 1);	 
	nrf24_WriteReg(CONFIG, config);

	CE_Enable();
}

void NRF24_RxMode(uint8_t *address, uint8_t channel){
	CE_Disable();

	nrf24_WriteReg(RF_CH, channel);
	
	nrf24_WriteReg(EN_AA, 0x02);	
	nrf24_WriteRegMulti(RX_ADDR_P1, address, 5); 
	nrf24_WriteReg(RX_PW_P1, 0x05); 

	nrf24_WriteReg(EN_RXADDR, 0x02); 
	
	uint8_t config = nrf24_ReadReg(CONFIG);
	config = config | (1 << 1) | (1 << 0);
	nrf24_WriteReg(CONFIG, config);

	CE_Enable();
}

void NRF24_Transmit(uint8_t *data, uint8_t size){
   	 uint8_t cmdtosend = 0; // Variable para guardar un comando
   	 cmdtosend = W_TX_PAYLOAD;

	select_slave_SPI();
   	 SPI_Transmit(&cmdtosend, 1); 
   	 SPI_Transmit(data,size); 
	unselect_slave_SPI();
	_delay_us(700); // Delay for waiting to send the package


	uint8_t ack_flag;
	// Wait for the ack
	do{
		ack_flag = nrf24_ReadReg(STATUS);
		_delay_us(700); 
	}while(!(ack_flag & (1 << 5)) & (!(ack_flag & (1 << 4))));

	// Clean IRQ's
	uint8_t status = nrf24_ReadReg(STATUS);
	status |= (1 << 5) | (1 << 4);
	nrf24_WriteReg(STATUS, status);

	select_slave_SPI();
	cmdtosend = FLUSH_TX;
	SPI_Transmit(&cmdtosend, 1);
	unselect_slave_SPI();
}

Parents
  • Hello,

    If you simply power up the nRF24L01 chip, then by default the chip is configured to for instance use acknowledgement.

    The minimum configuration on the PRX after power up is to set the operation mode to RX and the rx payload width of pipe0 to specific length (e.g. 3), then write PWR_UP bit to 1 (wait ~2ms), and set CE to 1.

    The minimum configuration on the PTX after power up  is write PWR_UP bit to 1 (wait ~2ms), then write the TX payload with a specific length (e.g. 3), and toggle CE to start transmission.

    Best regards,
    Kenneth

  • As I understand it from the datasheet, what needs to be done to use the ACK is: In the TX:

    • Enable CRC
    • Set TX Address size and the TX Address itself
    • Set the number of retransmit retries for ACK
    • Enable data pipe 0 for receiving the ACK
    • Put the address of pipe 0 the same as the TX Address
    • Then the other configuration stuff like power, channel, data rate, TX Mode

    In the RX:

    • Enable CRC
    • Enable data pipe 1 (the one I'm using for communication)
    • Enable ACK on that pipe 1 (EN_AA)
    • Size of address
    • Set up the address of data pipe 1, the same as the TX
    • Payload size on data pipe 1
    • Other stuff like channel, power....
Reply
  • As I understand it from the datasheet, what needs to be done to use the ACK is: In the TX:

    • Enable CRC
    • Set TX Address size and the TX Address itself
    • Set the number of retransmit retries for ACK
    • Enable data pipe 0 for receiving the ACK
    • Put the address of pipe 0 the same as the TX Address
    • Then the other configuration stuff like power, channel, data rate, TX Mode

    In the RX:

    • Enable CRC
    • Enable data pipe 1 (the one I'm using for communication)
    • Enable ACK on that pipe 1 (EN_AA)
    • Size of address
    • Set up the address of data pipe 1, the same as the TX
    • Payload size on data pipe 1
    • Other stuff like channel, power....
Children
Related