Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ESB to sync clocks

I am building a product where a central device communicates with peripheral devices in a star topology. The main purpose of the communication is for the central device to know a delta time between an event on the central device and an event on the peripheral devices. I am trying to determine the best way to do this to achieve a low (few ms) error in the measured time. I do not need to use BLE for this, I was considering ESB. The central device is however also using BLE to communicate with an App, so I have already set up timeslot requests.

My idea is to send 'start' signals repeatedly to all peripherals to start a clock, and when all peripherals respond to a given signal then the central knows all peripherals have started their clocks and will also start its clock. Then peripherals record the timestamps that events occur and send them back to the central when possible.

The issue with using ESB for this is being able to communicate with several nodes at the same time to start the clocks. To be able to decide when a packet is sent, the central must be in PTX mode. But this would only give it the ability to communicate with one PRX node.

Do you have any suggestions for how this could be achieved? Is ESB a good protocol choice?

  • Thanks for the suggestion. I guess I would need to modify the ESB library to be able to respond with the current timestamp in the ack? As the library only allows you to queue responses in advance.

    4 peripherals to one central.

    I did think that they could switch roles e.g. peripherals become PRX for sync, then switch to PTX, but it could become quite complicated. This is currently at prototype stage so I want it to work well and not take too long to build even if it is imperfect.

  • Hi 

    nrbrook said:
    Thanks for the suggestion. I guess I would need to modify the ESB library to be able to respond with the current timestamp in the ack? As the library only allows you to queue responses in advance.

    That is correct. The easiest way is probably to update this information just after (or before) the call to NRF_RADIO->TASKS_TXEN  = 1; at the end of the start_tx_transaction() function. 

    The triggering of the task and update of the payload should be wrapped in a critical section to avoid the case where an interrupt happens somewhere in the middle. 

    Please note that this method will not support retransmits. If you want to support this you will need to continuously update the value for each retransmitted packet, in order to make sure the timestamp is always up to date. 

    nrbrook said:
    I did think that they could switch roles e.g. peripherals become PRX for sync, then switch to PTX, but it could become quite complicated. This is currently at prototype stage so I want it to work well and not take too long to build even if it is imperfect.

    Yes, switching roles is possible, but in general I won't recommend it as it does complicate things quite a bit. 

    The more conceptually simple you can keep the implementation, the more likely it will work reliably in the field Slight smile

    Best regards
    Torbjørn

  • Thanks, I am just implementing this now.

    The easiest way is probably to update this information just after (or before) the call to NRF_RADIO->TASKS_TXEN  = 1; at the end of the start_tx_transaction() function. 

    Is this the correct place to update the buffer for both PTX and PRX modes? I can't see where the start_tx_transaction() function would be called in PRX mode.

    In addition, for PRX I want to automatically respond with a packet if another packet is received. I.e. if received packet byte 0 == 1, ack with a packet containing the current timestamp. Where should I put this? I think it should be in on_radio_disabled_rx in the if (ack) part, however looking at the code I can only see where the next packet is prepared if the protocol is ESP_DPL...

  • Hi

    nrbrook said:
    Is this the correct place to update the buffer for both PTX and PRX modes? I can't see where the start_tx_transaction() function would be called in PRX mode.

    The start_tx_transaction() function is not used in PRX mode. Instead the ACK payload is prepared in the on_radio_disabled_rx() function, line 863:

    if(mp_current_payload != 0)
    {
        p_pipe_info->ack_payload = true;
        update_rf_payload_format(mp_current_payload->length);
        m_tx_payload_buffer[0] = mp_current_payload->length;
        memcpy(&m_tx_payload_buffer[2],
               mp_current_payload->data,
               mp_current_payload->length);
    }

    nrbrook said:
    In addition, for PRX I want to automatically respond with a packet if another packet is received. I.e. if received packet byte 0 == 1, ack with a packet containing the current timestamp. Where should I put this? I think it should be in on_radio_disabled_rx in the if (ack) part, however looking at the code I can only see where the next packet is prepared if the protocol is ESP_DPL...

    You should be able to do this in the on_radio_disabled_rx() function, modifying the code I attached above. Just keep in mind that this happens some time before the packet is actually sent, since the radio needs to ramp up first. 

    The data you just received should be available in the m_rx_payload_buffer array, so you can check this if you want to change the behavior depending on the received packet content. 

    The ESB_DPL protocol is the only one that supports including data in the ACK payload (for historical reasons), which is why this is the only place where the ACK payload data is changed based on what is in the TX FIFO. 

    Best regards
    Torbjørn

  • Thanks, is there any way to set the timestamp to the buffer and send in a critical section as with PTX modification? I can't see where the PRX payload send is initiated.

Related