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

Accessing nRF51 Radio packet data outwith payload

Hello,

We are developing a system using a receiver nRF unit, and multiple transmitter nRF units. The transmitters use the proprietary radio protocol (not bluetooth LE) to broadcast data periodically, which the receiver listens to.

We are using the nRF51 series reference manual 2.1, specifically section 16.1.2 and the proceeding pages. I understand that a radio packet on this protocol carries an ADDRESS sequence, with BASE and PREFIX data concatenated.

I also understand that "in memory", the packet structure only contains S0, LENGTH, S1, and PAYLOAD, since the PREAMBLE, ADDRESS, and CRC fields are "added dynamically when the packet is sent".

Using the NRF_RADIO struct, I can access data like NRF_RADIO->PREFIX0 and NRF_RADIO->BASE1

We're using example projects as reference extensively, since most of us are more familiar with software APIs than electronics manuals.

In the nRF51 SDK, there is a project called radio_example. Both the receiver and the transmitter for this program include radio_config.h (!)

In other words, both entry points have pre-configured the NRF_RADIO->PREFIXn and NRF_RADIO->BASEn values (along with all other values like NRF_RADIO->TXADDRESS and NRF_RADIO->RXADDRESSES)

Due to this, it's unclear which fields need to be matching on both entry points, which fields are used by which entry points, and which fields are updated dynamically by receive/transmit calls. Ideally, I would like to have each transmitter in my system preconfigured with a unique ADDRESS, so that my receiver can read ADDRESS fields from each received packet. Is this possible? And if so, how?

We have considered encoding the address info in the payload, but this is not ideal. Also note that our environment has many other nRF radio devices (due to other teams in the course), and some of them are using Bluetooth LE. We need address checking to distinguish our packets from garbage.

Kind Regards,

Parents
  • Lets see if we are able to summarize this and answer your questions.

    If I start with the addressing PREFIX and BASE. For my own part it is easier to understand these two by looking at the Enhanced Shockburst engine Nordic has in their legacy products. There's a good reason for having both PREFIX and BASE. So please have a look in chapter 7, and specifically chapter 7.6 of the nRF24L01+ product specification. As you see there, there's a feature called Multiceiver that's able to listen for multiple address matches (pipes) at the same time. These addresses are arranged so that for pipe0 all five bytes of the address if unique compare to pipe1-pipe5. Pipe1 to pipe5 however share the 4 MSB and have unique LSB. So PREFIX on the nRF51 is to be able to have the unique LSB on the pipes for backwards compatibility and BASE would be the shared 4 MSB in pipe1 to pipe5. On the nRF24L01+ this was all done by a HW implemented state machine, but for the nRF51 this is done in SW and hence more flexible. So for your setup, lets say you have one PTX (primary transmitter) sending to one specific PRX (primary receiver) these two units will have to match the PTX TX address to the PRX RX address, both BASE and PREFIX would have to be the same. Then if you have auto-ACK, the PRX will use the address on the receive pipe for transmitting the ACK back and hence the PTX will have to listen for the ACK coming in on the same address as used for the TX it just sent.

    If you scale this up and have one PRX configured with two pipes, so that it is listening for two different addresses RX_ADDRESS0 (made from BASE0 and PREFIX0) and RX_ADDRESS1 (made from BASE1 and PREFIX1), the two PTX can be configured to communicate with the PRX through their own separate addresses. The PRX will then send the ACK to the specific PTX that it received from.

    The addresses are configured by you by writing to the BASE0, BASE1, PREFIX0 and PREFIX1 and the selecting the pipe/TXADDRESS/RXADDRESSES. Once you have configure a pipe to use a specific RXADDRESS and set it to use auto-ACK, it will handle the transmission of the ACK on it's own.

    With regard to the S0, Length and S1 these are field used to be backwards compatible as well and or define your own packet structure. Also here you might have some benefit from reading the history from nRF24L01+. Please see chapter 7.3 and specifically 7.3.3. You'll see that the S0, Length and S1 can be used to have the same structure as the "Packet control field" in Enhanced Shockburst. So these fields will be updated when you write to the nrf_esb_add_packet_to_tx_fifo() with the needed S0, Length and S1 size and content.

    This became a long answer, but hopefully it gave you some more context. Basically these fields are based on the fact that we want to be backwards compatible and it might be easier to understand them by reading the Enhanced Shockburst example in the nRF24L01+ product specification. Please let us know if you still have further questions.

    edit to answer questions in comments:

    1. How can I enable auto-ACK?

    • You do this by using the Enhanced Shockburst library in the nRF51 SDK. Please see documentation here devzone.nordicsemi.com/.../a00852.html and specifically the function named: nrf_esb_enable_dyn_ack().

    2. What happens if a tx fails to receive an ACK? Does it automatically re-transmit?

    • If you have enabled auto-ACK and are using the nrf_esb_add_packet_to_tx_fifo() to send the payload the re-transmit will be handled as you have configured it through the nrf_esb_set_retransmit_delay and nrf_esb_set_max_number_of_tx_attempts

    3. How can I make rx::NRF_RADIO->RXADDRESSES accept pipes from, for example, all of BASEn | PREFIXn for n on [0..4]?

    • See the functions related to this one: nrf_esb_set_base_address_0 there are functions for BASEn, PREFIXn and setting which pipes to use.

    4. When rx receives a packet and automatically ACKs it, how can I programmatically check which n from [0..4] was received?

    • nrf_esb_fetch_packet_from_rx_fifo will give you the pipe number the specific payload was receive on.

    5. • I understand that having a larger payload size (PACKET_PAYLOAD_MAXZIZE) will increase the likelihood of failed transmission, and also increase power consumption. Where in the specification can I find approximate likelihood and consumption values for different PACKET_PAYLOAD_MAXSIZE values?

    • We don’t have an overview over this as there are parameters outside our control that would affect this as well. You could have good and bad designs making it easier/worse to send packages, antenna design and placement, environment and noise would all affect this experiment. It would be a lot of assumption doing such a test that wouldn’t be realistic for any other setup and could in worst case give customers false expectations due to ideal scenario.
Reply
  • Lets see if we are able to summarize this and answer your questions.

    If I start with the addressing PREFIX and BASE. For my own part it is easier to understand these two by looking at the Enhanced Shockburst engine Nordic has in their legacy products. There's a good reason for having both PREFIX and BASE. So please have a look in chapter 7, and specifically chapter 7.6 of the nRF24L01+ product specification. As you see there, there's a feature called Multiceiver that's able to listen for multiple address matches (pipes) at the same time. These addresses are arranged so that for pipe0 all five bytes of the address if unique compare to pipe1-pipe5. Pipe1 to pipe5 however share the 4 MSB and have unique LSB. So PREFIX on the nRF51 is to be able to have the unique LSB on the pipes for backwards compatibility and BASE would be the shared 4 MSB in pipe1 to pipe5. On the nRF24L01+ this was all done by a HW implemented state machine, but for the nRF51 this is done in SW and hence more flexible. So for your setup, lets say you have one PTX (primary transmitter) sending to one specific PRX (primary receiver) these two units will have to match the PTX TX address to the PRX RX address, both BASE and PREFIX would have to be the same. Then if you have auto-ACK, the PRX will use the address on the receive pipe for transmitting the ACK back and hence the PTX will have to listen for the ACK coming in on the same address as used for the TX it just sent.

    If you scale this up and have one PRX configured with two pipes, so that it is listening for two different addresses RX_ADDRESS0 (made from BASE0 and PREFIX0) and RX_ADDRESS1 (made from BASE1 and PREFIX1), the two PTX can be configured to communicate with the PRX through their own separate addresses. The PRX will then send the ACK to the specific PTX that it received from.

    The addresses are configured by you by writing to the BASE0, BASE1, PREFIX0 and PREFIX1 and the selecting the pipe/TXADDRESS/RXADDRESSES. Once you have configure a pipe to use a specific RXADDRESS and set it to use auto-ACK, it will handle the transmission of the ACK on it's own.

    With regard to the S0, Length and S1 these are field used to be backwards compatible as well and or define your own packet structure. Also here you might have some benefit from reading the history from nRF24L01+. Please see chapter 7.3 and specifically 7.3.3. You'll see that the S0, Length and S1 can be used to have the same structure as the "Packet control field" in Enhanced Shockburst. So these fields will be updated when you write to the nrf_esb_add_packet_to_tx_fifo() with the needed S0, Length and S1 size and content.

    This became a long answer, but hopefully it gave you some more context. Basically these fields are based on the fact that we want to be backwards compatible and it might be easier to understand them by reading the Enhanced Shockburst example in the nRF24L01+ product specification. Please let us know if you still have further questions.

    edit to answer questions in comments:

    1. How can I enable auto-ACK?

    • You do this by using the Enhanced Shockburst library in the nRF51 SDK. Please see documentation here devzone.nordicsemi.com/.../a00852.html and specifically the function named: nrf_esb_enable_dyn_ack().

    2. What happens if a tx fails to receive an ACK? Does it automatically re-transmit?

    • If you have enabled auto-ACK and are using the nrf_esb_add_packet_to_tx_fifo() to send the payload the re-transmit will be handled as you have configured it through the nrf_esb_set_retransmit_delay and nrf_esb_set_max_number_of_tx_attempts

    3. How can I make rx::NRF_RADIO->RXADDRESSES accept pipes from, for example, all of BASEn | PREFIXn for n on [0..4]?

    • See the functions related to this one: nrf_esb_set_base_address_0 there are functions for BASEn, PREFIXn and setting which pipes to use.

    4. When rx receives a packet and automatically ACKs it, how can I programmatically check which n from [0..4] was received?

    • nrf_esb_fetch_packet_from_rx_fifo will give you the pipe number the specific payload was receive on.

    5. • I understand that having a larger payload size (PACKET_PAYLOAD_MAXZIZE) will increase the likelihood of failed transmission, and also increase power consumption. Where in the specification can I find approximate likelihood and consumption values for different PACKET_PAYLOAD_MAXSIZE values?

    • We don’t have an overview over this as there are parameters outside our control that would affect this as well. You could have good and bad designs making it easier/worse to send packages, antenna design and placement, environment and noise would all affect this experiment. It would be a lot of assumption doing such a test that wouldn’t be realistic for any other setup and could in worst case give customers false expectations due to ideal scenario.
Children
  • Hello,

    Thank you for the response. As I understand, the structure of the address fields are split into BASEn and PREFIXn to facilitate backwards compatibiltiy with an older nordic radio device. I also understand that since the nRF51822 is not hardware limited, I can have unique values such that BASE0 != BASE1, since the shared values are only necessary for the nRF24L01P.

    Further, I understand that both the receiver and transmitters need to have equivalent BASE and PREFIX values such that rx::BASE0 == tx::BASE0. Lastly, if I want to have auto-ack working, I need each tx, tx-n to have its tx address, tx-n::NRF_RADIO->TXADDRESS to equal the value of the base/prefix I want to use, i.e. to use BASE0 | PREFIX0, I need to set tx-0::NRF_RADIO->TXADDRESS = 0. I also need the rx' receive addresses to reference all tx-n::NRF_RADIO->TXADDRESS values.

    Please correct me if any of these statements are wrong.

    Next, I have a couple questions related to these:

    • How can I enable auto-ACK?
    • What happens if a tx fails to receive an ACK? Does it automatically re-transmit?
    • How can I make rx::NRF_RADIO->RXADDRESSES accept pipes from, for example, all of BASEn | PREFIXn for n on [0..4]?
    • When rx receives a packet and automatically ACKs it, how can I programmatically check which n from [0..4] was received?
    • I understand that having a larger payload size (PACKET_PAYLOAD_MAXZIZE) will increase the likelihood of failed transmission, and also increase power consumption. Where in the specification can I find approximate likelihood and consumption values for different PACKET_PAYLOAD_MAXSIZE values?

    Thanks again,

Related