ESB vs. Gazelle Max Polling Rate

Hi all,

I have an application that is pretty simple. One master that needs to stream small payloads (sub 32 byte) to a receiving device. The payload is a fixed size and all I care about is achieving the maximum polling rate/update rate possible. I do not even care about the client acknowledging data or attempting to retry and transmission. Just send the most current data as fast as possible (I think of a UDP stream in a away).

I started with standard BLE but realized that if I need maximum update rates possible, I needed to turn to proprietary protocols. I am now looking at ESB and Gazelle.

In order to avoid having to implement and tweak both protocols, I was wondering if someone would know beforehand what protocol is built best for my needs. ESB seems attractive as you can turn off ACK packets from the client and turn off re-transmissions. It seems like you would get a decent gain in packets per second that you could send eliminating this overhead.

Gazelle seems like it does not give you some of that flexibility (maybe it does and I didnt find it) like turning off ACK responses. However I saw with 2 NRF52840 devices, the Gazelle time slot can be reduced to 600us. So maybe it can still hold its own against ESB.

Is there any benchmarking or experience you may have to know which protocol is best suited towards the type of application I described. My gut tells me ESB, but I would appreciate any insight.

Thanks

Parents
  • Hi,

     

    Gazell is ESB-based, and requires the use of ACKing, so I agree with your statement here:

    ESB seems attractive as you can turn off ACK packets from the client and turn off re-transmissions. It seems like you would get a decent gain in packets per second that you could send eliminating this overhead.

    Gazell has a slot based setup, as you mention here:

    Gazelle seems like it does not give you some of that flexibility (maybe it does and I didnt find it) like turning off ACK responses. However I saw with 2 NRF52840 devices, the Gazelle time slot can be reduced to 600us. So maybe it can still hold its own against ESB.

    However, it will use one slot for sending and one for receiving, so the maximum payload throughput will be 1 / (2 * timeslot) = 1 / 1.2 ms = 833.3 packets per second.

      

    What you "get for free" with gazell is channel hopping in case of your environment being a bit noisy, but this is also something that you can implement in your own ESB-based application, as you have full control over the radio when using ESB. ESB is open source while gazell is delivered as a static compiled library.

    That being said, if you only want to stream data one way, it sounds like ESB (with noack) is something that you should look into.

    With ESB, you can achieve close to 80-90% link utilization with larger payload sizes, as well as quite a low latency (<500 us) and can be used for sync'ing devices over-the-air, as shown in this blog post:

     Wireless timer synchronization among nRF5 devices 

       

    Kind regards,

    Håkon

  • Thank you for the response. I had a feeling ESB was the better route if just concerned about update rate. That was also a very interesting article that shows the low latency and capabilities.

    Similar to my original question, I am now interested in what ESB configuration results in the most packets per second sent over the air. Like I said, my packet size is under 32 bytes so nothing crazy.

    I have currently slightly modified the ESB transmitter and receiver sample codes and have them running on 2 NRF52840DKs that are sitting next to each other.

    I modified my transmitter to have this configuration.

    My receiver has this configuration:

    My transmit code looks like:

    To my knowledge, my configuration is using the 2M PHY, requires no acknowledgements, and attempts no retries, and is sending a static 8 byte payload.

    My transmit code is essentially just a while loop that adds the packet to the Tx buffer and then sends it out. To me this all seems like the absolute fastest configuration I can have. When doing some statistics, I am getting roughly 475 packets per second on the receiving end. To me this seems......low? Maybe not, I have no context as to what should be reasonably expected.

    Are there any benchmarks for ESB on what update rates are possible? Is there any knowledge on what the fastest configuration should be? Any ideas on what tweaks could be made to increase update rates? It seems like I am running the fastest ESB configuration possible and am getting roughly half of what the theoretical max of Gazelle is.

    Any insights or ideas would be greatly appreciated.

  • Hi,

     

    coder123 said:
    To my knowledge, my configuration is using the 2M PHY, requires no acknowledgements, and attempts no retries, and is sending a static 8 byte payload.

    All PHY modes can be configured with .noack=true. 2MBit will be the fastest.

     

    coder123 said:
    My transmit code is essentially just a while loop that adds the packet to the Tx buffer and then sends it out. To me this all seems like the absolute fastest configuration I can have. When doing some statistics, I am getting roughly 475 packets per second on the receiving end. To me this seems......low? Maybe not, I have no context as to what should be reasonably expected.

    This seems low. Try disabling or limiting logging, and setup a 1 second k_timer to count/print the amount of packets received and the packets sent on the PTX side.

    I did a quick test with no receiver (since its noack=true), and I'm getting around 4000 payloads sent per second.

    Here's the .diff based on ncs v2.6.1:

    diff --git a/samples/esb/esb_ptx/prj.conf b/samples/esb/esb_ptx/prj.conf
    index 621266d17..d8e9e282d 100644
    --- a/samples/esb/esb_ptx/prj.conf
    +++ b/samples/esb/esb_ptx/prj.conf
    @@ -5,3 +5,4 @@
     #
     CONFIG_NCS_SAMPLES_DEFAULTS=y
     CONFIG_ESB=y
    +CONFIG_LOG_MODE_IMMEDIATE=y
    diff --git a/samples/esb/esb_ptx/src/main.c b/samples/esb/esb_ptx/src/main.c
    index b64950ab7..f5ff7f4b2 100644
    --- a/samples/esb/esb_ptx/src/main.c
    +++ b/samples/esb/esb_ptx/src/main.c
    @@ -24,6 +24,9 @@ static const struct gpio_dt_spec leds[] = {
            GPIO_DT_SPEC_GET(DT_ALIAS(led3), gpios),
     };
     
    +
    +volatile uint32_t packet_count;
    +
     BUILD_ASSERT(DT_SAME_NODE(DT_GPIO_CTLR(DT_ALIAS(led0), gpios),
                              DT_GPIO_CTLR(DT_ALIAS(led1), gpios)) &&
                 DT_SAME_NODE(DT_GPIO_CTLR(DT_ALIAS(led0), gpios),
    @@ -48,7 +51,8 @@ void event_handler(struct esb_evt const *event)
     
            switch (event->evt_id) {
            case ESB_EVENT_TX_SUCCESS:
    -               LOG_DBG("TX SUCCESS EVENT");
    +               //LOG_DBG("TX SUCCESS EVENT");
    +               packet_count++;
                    break;
            case ESB_EVENT_TX_FAILED:
                    LOG_DBG("TX FAILED EVENT");
    @@ -181,6 +185,15 @@ static void leds_update(uint8_t value)
            (void)gpio_port_set_masked_raw(leds[0].port, mask, val);
     }
     
    +void my_timer_handler(struct k_timer *dummy)
    +{
    +       static uint32_t last_packet_count;
    +       printk("Packet count per sec: %d\n", packet_count-last_packet_count);
    +       last_packet_count = packet_count;
    +}
    +
    +K_TIMER_DEFINE(my_status_timer, my_timer_handler, NULL);
    +
     int main(void)
     {
            int err;
    @@ -205,8 +218,8 @@ int main(void)
     
            LOG_INF("Initialization complete");
            LOG_INF("Sending test packet");
    -
    -       tx_payload.noack = false;
    +       k_timer_start(&my_status_timer, K_SECONDS(1), K_SECONDS(1));
    +       tx_payload.noack = true;
            while (1) {
                    if (ready) {
                            ready = false;
    @@ -219,6 +232,6 @@ int main(void)
                            }
                            tx_payload.data[1]++;
                    }
    -               k_sleep(K_MSEC(100));
    +               k_cpu_idle();
            }
     }
    

     

    With fast ramp-up, you should see even more.

     

    Kind regards,

    Håkon

  • Just to follow up on this, I was able to replicate what you showed.If anyone is curious, the logging in the event callbacks was the problem.

    Thank you very much for the help.

Reply Children
Related