Migration from nRF24 to nRF5x

We have a product on the market that uses the nRF24 and a PIC, chosen primarily for it's cost and rapid development time. We are now looking into using a nRF52 to replace both the nRF24 and the PIC. I think I understand how ESB works on the nRF52, but I am confused about a couple of things:

#1:  nrf_esb_set_prefixes & nrf_esb_set_base_address_1 – currently we are using a 3 byte Tx/Rx address: uint8_t RX_ADDR1[3] = {0x20, 0x23, 0x23};  I can’t tell if nrf_esb_set_prefixes is required on the nrf52, or can it be safely ignored and just use a 3 byte “esb_set_base_address_1”?

#2: nRF52 doesn’t seem to allow: “NRF_ESB_BITRATE_250KBPS”, which is ok. We can adjust, if necessary, on the Transmitter side.

#3: I am using “C:\nRF5_SDK_17.1.0_ddde560\examples\proprietary_rf\esb_prx”. Cortex/nRF52 is very new to me. I am more familiar with Microchip PIC C & Arduino C++ so if there are other things that would be helpful to be aware of please don’t hesitate to point them out to me.

#4 I have a “Nordic Semiconductor nRF52840-DK” to prototype with, but I am open to suggestions on low power, low cost nRF5x options for a simple application: ESB and some simple programming to control a couple of gpio pins. (no BLE, etc...)

my current PIC nRF24_Setup() 

const uint8_t R_REG = 0x00;

const uint8_t W_REG = 0x20;

const uint8_t RX_PAYLOAD = 0x61;

const uint8_t TX_PAYLOAD = 0xA0;

const uint8_t FLUSH_TX = 0xE1;

const uint8_t FLUSH_RX = 0xE2;

const uint8_t ACTIVATE = 0x50;

const uint8_t R_STATUS = 0xFF;

 

//Registers

const uint8_t NRF_CONFIG = 0x00;

const uint8_t EN_AA = 0x01;

const uint8_t EN_RXADDR = 0x02;

const uint8_t SETUP_AW = 0x03;

const uint8_t SETUP_RETR = 0x04;

const uint8_t RF_CH = 0x05;

const uint8_t RF_SETUP = 0x06;

const uint8_t NRF_STATUS = 0x07;

const uint8_t OBSERVE_TX = 0x08;

const uint8_t CD = 0x09;

const uint8_t RX_ADDR_P0 = 0x0A;

const uint8_t RX_ADDR_P1 = 0x0B;

const uint8_t RX_ADDR_P2 = 0x0C;

const uint8_t RX_ADDR_P3 = 0x0D;

const uint8_t RX_ADDR_P4 = 0x0E;

const uint8_t RX_ADDR_P5 = 0x0F;

const uint8_t TX_ADDR = 0x10;

const uint8_t RX_PW_P0 = 0x11;

const uint8_t RX_PW_P1 = 0x12;

const uint8_t RX_PW_P2 = 0x13;

const uint8_t RX_PW_P3 = 0x14;

const uint8_t RX_PW_P4 = 0x15;

const uint8_t RX_PW_P5 = 0x16;

const uint8_t FIFO_STATUS = 0x17;

const uint8_t DYNPD = 0x1C;

const uint8_t FEATURE = 0x1D;

 

uint8_t TX_ADDR0[3] = {0x21, 0x23, 0x23}; //address actually = 0x23,0x23,0x21

uint8_t RX_ADDR1[3] = {0x20, 0x23, 0x23}; //address actually = 0x23,0x23,0x20

uint8_t rfCardPresent = 0x00; //False

 

//enums

enum nrfChannel{

    channel_2402 = 0x02,

    channel_2440 = 0x28,

    channel_2480 = 0x50,

} channel;

 

enum nrfPower{

    powerMinus_0 = 0x26,  //250kbps, 0dBm

    powerMinus_6 = 0x24,  //250kbps, -6dBm

    powerMinus_12 = 0x22, //250kbps, -12dBm

    powerMinus_18 = 0x20, //250kbps, -18dBm

} power;

 

 

void nRF24_Setup(uint8_t _channel, uint8_t _power)

{

  WriteRegister(NRF_CONFIG, 0x0B);     //1 uint8_t CRC, POWER UP, PRX

  WriteRegister(EN_AA, 0x00);          //Disable auto ack

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

  WriteRegister(SETUP_AW, 0x01);       //3 uint8_t address

  WriteRegister(SETUP_RETR, 0x00);     //Retransmit disabled

  WriteRegister(RF_CH, 0x01);          //Randomly chosen RF channel

  WriteRegister(RX_PW_P0, received_CCU_Payload_Length);       //RX payload

 

  WriteAddress(RX_ADDR_P0, 3, RX_ADDR1);

  WriteAddress(TX_ADDR, 3, TX_ADDR0);

  WriteRegister(RF_CH, _channel);          //channel 2440

  WriteRegister(RF_SETUP, _power);       //250kbps, 0dBm

 

  if ((ReadRegister(NRF_CONFIG) & 0x08) != 0)

      rfCardPresent = 0x01;//True

}

 

and my proposed nRF52 esb_init( void ).

 

uint32_t esb_init( void )

{

    uint32_t err_code;

    uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};

    uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};

    uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };

    nrf_esb_config_t nrf_esb_config         = NRF_ESB_DEFAULT_CONFIG;

 

    //  Override  - NRF_ESB_DEFAULT_CONFIG

    nrf_esb_config.protocol                 = NRF_ESB_PROTOCOL_ESB;

    nrf_esb_config.mode                     = NRF_ESB_MODE_PRX;

    nrf_esb_config.event_handler            = nrf_esb_event_handler;

    nrf_esb_config.bitrate                  = NRF_ESB_BITRATE_1MBPS;

    nrf_esb_config.crc                      = NRF_ESB_CRC_OFF;

    nrf_esb_config.tx_output_power          = NRF_ESB_TX_POWER_4DBM;

    nrf_esb_config.payload_length           = 32;

    nrf_esb_config.selective_auto_ack       = false;

 

    err_code = nrf_esb_init(&nrf_esb_config);

    VERIFY_SUCCESS(err_code);

 

    err_code = nrf_esb_set_base_address_0(base_addr_0);

    VERIFY_SUCCESS(err_code);

 

    err_code = nrf_esb_set_base_address_1(base_addr_1);

    VERIFY_SUCCESS(err_code);

 

    err_code = nrf_esb_set_prefixes(addr_prefix, 8);

    VERIFY_SUCCESS(err_code);

 

    return err_code;

}

Parents
  • Hello,

    1. The prefix is always required yes, see: 
    https://infocenter.nordicsemi.com/topic/ps_nrf52840/radio.html#concept_mdy_kcj_4r 

    2. Correct, 250kbps not supported.

    3. For all new development you should use the nRF Connect SDK (NCS), see:
    nRF Connect SDK and nRF5 SDK statement  

    To get started with NCS check out:
    https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/ 

    The nRF Connect SDK is using the zephyr RTOS. ESB is also supported in NCS:
    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_esb.html# 

    4. You can find an overview of the different nRF52-variants here:
    https://infocenter.nordicsemi.com/topic/struct_nrf52/struct/nrf52.html 

    Typically there is no problem to use the nRF52840-DK for development, and later to swap to a different nRF52 variant if you find that you don't use all the ram, flash and features that is available in the nRF52840 in specific. The only thing you need to do is then to update the possible gpios you are using and build for the target nRF52-variant you intend to use.

    Kenneth

  • Thanks Kenneth, I think I am getting a handle on this. Can you elaborate more on the base addresses and the prefix. I had read the documentation, but it still leaves me with questions. I could probably experiment and get it to work, but I would like to understand it better.

    1. Does it mean that 1 byte is taken from the addr_prefix[8] array, but the particular byte to be appended is determined by the Pipe(0-7) that is being initialized?  

      uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
      uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
      uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };

      Therefore
      pipe0's address = {0xE7, 0xE7, 0xE7, 0xE7,0xE7};
      pipe1's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC2};
      pipe2's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC3};
      ...
      pipe7's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC8};

    2. In the example I can't find a line which sets the address length. Am I missing something or is there a default assumed that I can’t find? I expected to see something like this in the example: 

      err_code = nrf_esb_set_address_length(5);

    3. Regarding the nRF Connect SDK (NCS). I thought I was using that already. Is that general advice moving forward or do you see something in my question that leads you to believe I'm not using the right thing ?(which is very possible)

    4. Channel. I also don't see nrf_esb_set_rf_channel() in the example code. It isn't clear to me what values are acceptable. Is it the full channel (2440) or just the 40 or something else?

    Here is my transmitter (ESP32/Arduino IDE) setup:

    /************************************************************************
    18:10:18.093 -> SPI Frequency = 10 Mhz
    18:10:18.093 -> Channel = 40 (~ 2440 MHz)
    18:10:18.093 -> RF Data Rate = 1 MBPS
    18:10:18.093 -> RF Power Amplifier = PA_LOW
    18:10:18.093 -> RF Low Noise Amplifier = Enabled
    18:10:18.127 -> CRC Length = 8 bits
    18:10:18.127 -> Address Length = 5 bytes
    18:10:18.127 -> Static Payload Length = 32 bytes
    18:10:18.127 -> Auto Retry Delay = 1500 microseconds
    18:10:18.127 -> Auto Retry Attempts = 15 maximum
    18:10:18.127 -> Packets lost on
    18:10:18.127 -> current channel = 0
    18:10:18.127 -> Retry attempts made for
    18:10:18.127 -> last transmission = 15
    18:10:18.127 -> Multicast = Disabled
    18:10:18.127 -> Custom ACK Payload = Disabled
    18:10:18.127 -> Dynamic Payloads = Disabled
    18:10:18.127 -> Auto Acknowledgment = Disabled
    18:10:18.127 -> Primary Mode = TX
    18:10:18.160 -> TX address = 0xc2c2c2c2c2
    18:10:18.160 -> pipe 0 ( open ) bound = 0xc2c2c2c2c2
    18:10:18.160 -> pipe 1 ( open ) bound = 0xe7e7e7e7e7
    18:10:18.160 -> pipe 2 (closed) bound = 0xc3
    18:10:18.160 -> pipe 3 (closed) bound = 0xc4
    18:10:18.160 -> pipe 4 (closed) bound = 0xc5
    18:10:18.160 -> pipe 5 (closed) bound = 0xc6
    *************************************************************************/

    ---

    Hello,

    1. The prefix is always required yes, see: 
      https://infocenter.nordicsemi.com/topic/ps_nrf52840/radio.html#concept_mdy_kcj_4r

     

    1. For all new development you should use the nRF Connect SDK (NCS), see:
      nRF Connect SDK and nRF5 SDK statement

    To get started with NCS check out:
    https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/ 

    The nRF Connect SDK is using the zephyr RTOS. ESB is also supported in NCS:
    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_esb.html# 

    Kenneth

  • mej7000 said:
    Therefore
    pipe0's address = {0xE7, 0xE7, 0xE7, 0xE7,0xE7};
    pipe1's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC2};
    pipe2's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC3};
    ...
    pipe7's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC8};

    Correct.

    mej7000 said:
    In the example I can't find a line which sets the address length. Am I missing something or is there a default assumed that I can’t find?

    It can be controlled by calling esb_set_address_length(), I can see default values are in esb.c:

    /* Default address configuration for ESB.
     * Roughly equal to the nRF24Lxx defaults, except for the number of pipes,
     * because more pipes are supported.
     */
    __ALIGN(4)
    static struct esb_address esb_addr = {
        .base_addr_p0 = {0xE7, 0xE7, 0xE7, 0xE7},
        .base_addr_p1 = {0xC2, 0xC2, 0xC2, 0xC2},
        .pipe_prefixes = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8},
        .addr_length = 5,
        .num_pipes = CONFIG_ESB_PIPE_COUNT,
        .rf_channel = 2,
        .rx_pipes_enabled = 0xFF
    };
    mej7000 said:
    Is that general advice moving forward

    nRF Connect SDK (NCS) is the recommended SDK moving forward yes, I can see you have initially chosen to download the nRF5 SDK which is no longer recommended for new designs. Unfortunately our web page is not fully up to date, so it's easy mistake to download the old nRF5 SDK for development.

    mej7000 said:
    Channel. I also don't see nrf_esb_set_rf_channel() in the example code. It isn't clear to me what values are acceptable. Is it the full channel (2440) or just the 40 or something else?

    See the following struct for a description of the rc_channel:

    /* Enhanced ShockBurst address.
     *
     * Enhanced ShockBurst addresses consist of a base address and a prefix
     * that is unique for each pipe. See @ref esb_addressing in the ESB user
     * guide for more information.
     */
    struct esb_address {
        uint8_t base_addr_p0[4];    /* Base address for pipe 0, in big endian. */
        uint8_t base_addr_p1[4];   /* Base address for pipe 1-7, in big endian. */
        uint8_t pipe_prefixes[8];   /* Address prefix for pipe 0 to 7. */
        uint8_t num_pipes;      /* Number of pipes available. */
        uint8_t addr_length;    /* Length of the address plus the prefix. */
        uint8_t rx_pipes_enabled;   /* Bitfield for enabled pipes. */
        uint8_t rf_channel;        /* Channel to use (between 0 and 100). */
    };
    The radio support 0 to 100, however radio regulations limit the channels to 2 to 81.
    Kenneth

Reply
  • mej7000 said:
    Therefore
    pipe0's address = {0xE7, 0xE7, 0xE7, 0xE7,0xE7};
    pipe1's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC2};
    pipe2's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC3};
    ...
    pipe7's address: = {0xC2, 0xC2, 0xC2, 0xC2,0xC8};

    Correct.

    mej7000 said:
    In the example I can't find a line which sets the address length. Am I missing something or is there a default assumed that I can’t find?

    It can be controlled by calling esb_set_address_length(), I can see default values are in esb.c:

    /* Default address configuration for ESB.
     * Roughly equal to the nRF24Lxx defaults, except for the number of pipes,
     * because more pipes are supported.
     */
    __ALIGN(4)
    static struct esb_address esb_addr = {
        .base_addr_p0 = {0xE7, 0xE7, 0xE7, 0xE7},
        .base_addr_p1 = {0xC2, 0xC2, 0xC2, 0xC2},
        .pipe_prefixes = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8},
        .addr_length = 5,
        .num_pipes = CONFIG_ESB_PIPE_COUNT,
        .rf_channel = 2,
        .rx_pipes_enabled = 0xFF
    };
    mej7000 said:
    Is that general advice moving forward

    nRF Connect SDK (NCS) is the recommended SDK moving forward yes, I can see you have initially chosen to download the nRF5 SDK which is no longer recommended for new designs. Unfortunately our web page is not fully up to date, so it's easy mistake to download the old nRF5 SDK for development.

    mej7000 said:
    Channel. I also don't see nrf_esb_set_rf_channel() in the example code. It isn't clear to me what values are acceptable. Is it the full channel (2440) or just the 40 or something else?

    See the following struct for a description of the rc_channel:

    /* Enhanced ShockBurst address.
     *
     * Enhanced ShockBurst addresses consist of a base address and a prefix
     * that is unique for each pipe. See @ref esb_addressing in the ESB user
     * guide for more information.
     */
    struct esb_address {
        uint8_t base_addr_p0[4];    /* Base address for pipe 0, in big endian. */
        uint8_t base_addr_p1[4];   /* Base address for pipe 1-7, in big endian. */
        uint8_t pipe_prefixes[8];   /* Address prefix for pipe 0 to 7. */
        uint8_t num_pipes;      /* Number of pipes available. */
        uint8_t addr_length;    /* Length of the address plus the prefix. */
        uint8_t rx_pipes_enabled;   /* Bitfield for enabled pipes. */
        uint8_t rf_channel;        /* Channel to use (between 0 and 100). */
    };
    The radio support 0 to 100, however radio regulations limit the channels to 2 to 81.
    Kenneth

Children
No Data
Related