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

[nRF52] ESB: one PTX, many PRX + frequency hopping. How to increase probability to of recived data?

In traditional approach to ESB communication we have many PTX device and one PRX device: image description

In my application, situation is inverted: I have only one PTX device and many PRX devices:

image description

Each PRX device have implemented Bluetooth and timeslot ESB.

Each PTX device has implemented only ESB protocol, and only transmit data – so the communication is only in one direction. So I did it, and it works very well, but i don't thing is the best way to do it.

PTX device sends payload with no ack:

payload->noack  = 1;

And later, send packed on 5 different channels: 4, 25, 42, 63 and 77 channel. For increase the probability of a chance of reaching the frame data to the PRX device I send each frame:

for ( i = 0 ; i < 10 ; i++ )
{	
  sendEsbDataOnChannelNr1();
  wait();
  sendEsbDataOnChannelNr2();
  wait();
  sendEsbDataOnChannelNr3();
  wait();
  sendEsbDataOnChannelNr4();
  wait();
  sendEsbDataOnChannelNr5();
  wait();
}

In the each PRX device I jumping through RX channel in interval 10ms:

nrf_esb_stop_rx();
nrf_esb_set_rf_channel( frequencyHopingTable[ channelIndex ] );
nrf_esb_start_rx();
channelIndex++;
if ( channelIndex > 4 ) channelIndex = 0;

So my question is:

  1. How to choose the best channel for frequency hopping?

  2. How to maximize probability to recive frame by PRX device? We have a few variable:

  • a total number of frequency hopping channel
  • number of burst transfer. Less is better - more energy efficiency. (one burst = transfer data ion each frequency hopping channel )
  • time and algorithm between how to jump between RX channel in PRX device? Random? What time between hop?

Mayby there are some books or article about this problems?

  • Hi Mateusz

    1. The main consideration when picking channels is that you spread them across the band, rather than clustering them together. Then you have a larger chance that some channels will be open, even if you have significant interference from other 2.4GHz sources such as WiFi and Bluetooth.
      The 5 channels you listed earlier seems to fit this requirement.

    2. The main point in a frequency jumping system such as this, where you don't synchronize the frequency hopping in the TX and RX, is that one side needs to stick to one channel for as long as it takes the other side to go through all it's channels.
      In Gazell we solve this by having the PTX retransmit on the same channel for the same amount of time it takes the PRX to cycle through all it's channels (5ms typically, with 5 channels and a 1ms 'Gazell period'). In your example it seems to be the opposite, and you have the PRX stick on a channel for a longer time while the PTX jumps around. There is no reason you can't do it this way, and the same rule applies (but in reverse). The PRX should stay on the same channel for at least enough time to allow the PTX to send the packet once on each channel. Then you have a very good chance that they will at least be on the same frequency for one of these packets. Not using the ACK is a bit of a drawback, since it means you have no idea if the packet was received or not, which means you have to retransmit each packet a certain number of times and hope for the best. It also means you have no way of synchronizing the PTX with the PRX (which would allow you to pick the right frequency quicker, and reduce the amount of retransmits).

    The number of channels used is typically between 3-5. Fewer channels reduce the amount of retransmits needed and as such reduced average current consumption and latency, but you have less flexibility when encountering heavy interference.

    I don't see any particular reason to go for a random hop sequence in the PRX, a sequential ordering should work equally well (and if you do implement synchronization it makes things easier).

    Best regards
    Torbjørn

  • Firstly thanks for the answer! Secondly, let me summarize:

    PTX DEVICE:

    for ( i = 0 ; i < 10 ; i ++ ) // for example - do this 10 times - less is better
    {
    	for ( j = 0; j < 5 ; j ++ ) // total time send in one channel is ~5ms
    	{
    		sendEsbDataOnChannelNr1();
    		wait1ms();
    	}
    	for ( j = 0; j < 5 ; j ++ )
    	{
    		sendEsbDataOnChannelNr2();
    		wait1ms();
    	}
    	for ( j = 0; j < 5 ; j ++ )
    	{
    		sendEsbDataOnChannelNr3();
    		wait1ms();
    	}
    	for ( j = 0; j < 5 ; j ++ )
    	{
    		sendEsbDataOnChannelNr4();
    		wait1ms();
    	}
    	for ( j = 0; j < 5 ; j ++ )
    	{
    		sendEsbDataOnChannelNr5();
    		wait1ms();
    	}
    }
    

    PRX DEVICE:

    in every 1ms:

    channelIndex++;
    if ( channelIndex > 4 ) channelIndex = 0;
    nrf_esb_stop_rx();
    nrf_esb_set_rf_channel( frequencyHopingTable[ channelIndex ] );
    nrf_esb_start_rx();
    

    so all frequency hop have 5ms period.

    Please, let me know is that ok?

    I can't use ACK because I have many PRX device which have the same address and I want to trasmit data to all of them. So I can't synchronize frequency between PRX and PTX - so I think the only way to do this - is "stupid" burst data throught all the channels in PTX device and hope that all PRX devices will recive data :)

  • Hi Mateusz

    Sending a packet every 1ms when the PRX stays on each channel for 1ms might not be quick enough, because you might send the packet at the exact moment the PRX is switching to a different channel (causing it to drop the data).
    It would be safer to send a packet every 500us. Then you know that if one packet is sent during the channel switch, the next packet will not be.

    In other words I would recommend sending the same packet every 500us, for a total of 5ms. If you want to try on all channels you should go through the list and do the same for each one.

    Best regards

  • Of course You right. In PTX device i send 20 times in each channel:

    for ( j = 0; j < 20 ; j ++ ) {
    	sendFrameOnChannel1();
    	wait500us();
    }
    for ( j = 0; j < 20 ; j ++ ) {
    	sendFrameOnChannel2();
    	wait500us();
    }
    for ( j = 0; j < 20 ; j ++ ) {
    	sendFrameOnChannel3();
    	wait500us();
    }
    for ( j = 0; j < 20 ; j ++ ) {
    	sendFrameOnChannel4();
    	wait500us();
    }
    for ( j = 0; j < 20 ; j ++ ) {
    	sendFrameOnChannel5();
    	wait500us();
    }
    

    Send data on one channel takes ~10ms.

    In PRX device I switch channel in every 2ms.

    And it works very well :) Thanks for help.

  • Hi Mateusz

    It's good to hear that you got it working :)

    In general I would recommend sending the packets in a non-blocking way, but that shouldn't affect packet loss ;)

    Best regards

Related