This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

switch between RX and TX mode in nRF24L01+

Hej,

I'm working with the nRF24L01+ and the ATmega328p programmed in c. The goal is to have both TX and RX mode in the same device, mainly work as RX but in certain conditions work as TX. There seems to be a problem in the set registers, because it mostly works once until it switches to the TX mode, and then doesn't switch back properly. I can't find much about the necessary presets in the registers without ESB. I read somewhere in another thread (which i can't find anymore) that the rx addresses have to remain untouched for rx mode. I guess, I need to reset them back to that "untouched" state, but i can't find any information what that would be. I attached the setup function i wrote to switch between RX and TX mode.

Thank you very much in advance! Nito

#define TX_POWERUP  nrf24_writeRegister(CONFIG, (1 << EN_CRC)|(0<<CRCO)|(0 << PRIM_RX)|(1 << PWR_UP));
#define RX_POWERUP  nrf24_writeRegister(CONFIG, (1 << EN_CRC)|(0<<CRCO)|(1 << PRIM_RX)|(1 << PWR_UP));

uint8_t nrf24_startAs(uint8_t mode){
  nrf24_writeRegister(RF_CH, 2);
  nrf24_writeRegister(RX_PW_P0, PAYLOAD_LENGTH); //length of payload in 1-32 byte, p60
  nrf24_writeRegister(RF_SETUP, RF_SETUP_RF_DR_250 | RF_SETUP_RF_PWR_0);
  nrf24_writeRegister(CONFIG, (1 << EN_CRC)|(0<<CRCO)|(0 << PRIM_RX));

  if (mode == RX_MODE) {
    nrf24_csn_set(0);
    spi_transfer(FLUSH_RX);
    nrf24_csn_set(1);
    nrf24_configRegister(EN_RXADDR,(1<<ERX_P0)|(1<<ERX_P1)|(0<<ERX_P2)|(0<<ERX_P3)|(0<<ERX_P4)|(0<<ERX_P5));
    RX_POWERUP;
    nrf24_ce_set(1);
    UART_Transmit("booted in RX_MODE\n");
    return 0;
  }
  else if (mode == TX_MODE) {
    nrf24_csn_set(0);
    spi_transfer(FLUSH_TX);
    nrf24_csn_set(1);
    nrf24_writeRegister(SETUP_RETR,(SETUP_RETR_ARD_750 | SETUP_RETR_ARC_15));
    tx_addr[0] = tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P0_B0_DEFAULT_VAL;
    nrf24_tx_address(tx_addr);
    nrf24_rx_address(tx_addr);
    UART_Transmit("booted in TX_MODE\n");
    return 0;
  }
  else {
    UART_Transmit("something in startAs went wrong\n");
    return -1;
  }
}
  • Hi Nito

    Quick follow up question: Do you have any changing bytes in the payload, or is the payload static? A known issue when resetting the radio between each transmitted packet is the fact that the 2 bit sequence counter (PID) will be reset, and the second packet will be discarded as a retransmission in the RX. By including a rolling counter in the payload you will avoid the problem.

    Can you confirm whether or not this is the issue?

  • Hej Torbjørn! The issue was something else, I found out that i have to reset the RX-addr actively to a specific value and when I set the TX-addr I need to have the RX-addr equal to that. It works fine afterwards. (sorry for taking so long to answer)

  • Here is the function how I made it work:

    uint8_t nrf24_startAs(uint8_t mode){
      tx_addr[0] = tx_addr[1] = tx_addr[2] = tx_addr[3] = tx_addr[4] = RX_ADDR_P0_B0_DEFAULT_VAL;
    
      if (prevMODE = TX_MODE && mode == RX_MODE) {
        nRF24L01_reset();
        POWERDOWN;
        _delay_ms(10);
        // UART_Transmit("TX->RX\n");
      }
    
      nrf24_writeRegister(RF_CH, 2);
      nrf24_writeRegister(RF_SETUP, RF_SETUP_RF_DR_250 | RF_SETUP_RF_PWR_0);
      nrf24_writeRegister(CONFIG, (1 << EN_CRC)|(0<<CRCO)|(0 << PRIM_RX));
    
      // Set length of incoming payload in 1-32 byte, p60
      nrf24_configRegister(RX_PW_P0, 0x00); // Auto-ACK pipe ...
      nrf24_configRegister(RX_PW_P1, PAYLOAD_LENGTH); // Data payload pipe
      nrf24_configRegister(RX_PW_P2, 0x00); // Pipe not used
      nrf24_configRegister(RX_PW_P3, 0x00); // Pipe not used
      nrf24_configRegister(RX_PW_P4, 0x00); // Pipe not used
      nrf24_configRegister(RX_PW_P5, 0x00); // Pipe not used
    
    
      if (mode == RX_MODE) {
        CLEAR_BIT(PORTD, PD7);
        // Auto Acknowledgment
        nrf24_configRegister(EN_AA,(1<<ENAA_P0)|(1<<ENAA_P1)|(0<<ENAA_P2)|(0<<ENAA_P3)|(0<<ENAA_P4)|(0<<ENAA_P5));
        // Enable RX addresses
        nrf24_configRegister(EN_RXADDR,(1<<ERX_P0)|(1<<ERX_P1)|(0<<ERX_P2)|(0<<ERX_P3)|(0<<ERX_P4)|(0<<ERX_P5));
    
        nrf24_rx_address(tx_addr);
        PTX = 0;
        RX_POWERUP;
        nrf24_ce_set(1);
        UART_Transmit("booted in RX_MODE\n");
        return 0;
      }
      else if (mode == TX_MODE) {
        SET_BIT(PORTD, PD7);
        nrf24_writeRegister(SETUP_RETR,(SETUP_RETR_ARD_750 | SETUP_RETR_ARC_15));
    		nrf24_tx_address(tx_addr);
        UART_Transmit("booted in TX_MODE\n");
        return 0;
      }
      else {
        UART_Transmit("something in startAs went wrong\n");
        return -1;
      }
      prevMODE = mode;
    }
    
  • Hi

    Thanks for adding the working code :)

    It is true that on the PTX side the TX and RX needs to be set to the same value. Otherwise the ACK will not be received (since the ACK uses the same address as the TX packet).

    Best regards
    Torbjørn

Related