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?

  • Hi 

    I definitely think ESB is a good protocol for this application, yes, since you have good control over packet timing, and you can even make some changes to the ESB implementation if needed in order to include an accurate time stamp in the packet. 

    In order to send a packet to multiple receivers at the same time you simply have to disable the ACK packet, by setting the no_ack field in the payload to 1. 

    For this to work it is important that the dynamic_ack feature is enabled when you initialize ESB. 

    A common way to do this is to have a running timestamp on the 'central' side, and include this timestamp in a packet that you send to all the devices. Then you just need to figure out how much delay you have between sending and receiving the packet, and add this to the local timestamp on the receiver side. 

    In order to mitigate the issue of packet loss it is a good idea to send time synchronization packets repeatedly, always with an updated timestamp, so that a receiver that misses out on one packet should receive another one shortly thereafter. 

    Best regards
    Torbjørn

  • Thanks for the response. So in this scenario, the central would be PTX and the nodes PRX? How can the central then know that all nodes are live and have the timestamp if they can’t ack? And how could I figure out the delay between sending and receiving the packet?

  • Hi

    nrbrook said:
    So in this scenario, the central would be PTX and the nodes PRX?

    That was the idea, yes. 

    nrbrook said:
    How can the central then know that all nodes are live and have the timestamp if they can’t ack?

    Good question. To answer this it would be good to know how you plan to handle the regular communication between nodes.
    Do you intend to switch the PTX/PRX relationship after you have achieved sync, so that the nodes can send data to the central whenever they want, or do you plan to leave the central node PTX?

    Having the central node remain in PTX mode should work fine, but it requires it to manually poll the different nodes for information since a PRX node can't send anything without first receiving a packet from the PTX. 

    nrbrook said:
    And how could I figure out the delay between sending and receiving the packet?

    A practical way to do this is to set a pin on the PTX side when the timestamp is written into the payload, and then set a pin on the PRX side when the timestamp is received and updated locally. If you measure the two pins on a scope you can then see the delay between reading out the timestamp on one side and writing it on the other.  

    You should also run this operation repeatedly over time, and see if there is a lot of jitter in the delay. Some jitter should be expected, but if there is a lot it will affect how good accuracy you can achieve. 

    Best regards
    Torbjørn

  • Do you intend to switch the PTX/PRX relationship after you have achieved sync, so that the nodes can send data to the central whenever they want, or do you plan to leave the central node PTX?

    I could do, whatever would work best. To outline my requirements:

    • Ideally I would like to keep power consumption to a minimum on the peripherals, but this is a secondary consideration
    • The central will not be available 100% of the time due to time slots
    • This period of synchronisation will typically only need to last a few minutes at most, after which the system could fall into a lower power state with infrequent communication and no synchronisation, as long as the central can kick off the synchronisation process again at any time
    • The time to achieve synchronisation is not important
    • The time to get timestamps back to the central is not critical, i.e. <1s is fine

    So you are suggesting keeping the central as PTX but without noack in order to get confirmation of synchronisation? Wouldn't all the PRX nodes try to ack at the same time in that case?

    A practical way to do this is to set a pin on the PTX side when the timestamp is written into the payload, and then set a pin on the PRX side when the timestamp is received and updated locally.

    Ok, measure the delay and then hardcode that in the firmware to offset received timestamps? That should be fine. The application is measuring physical performance in humans, so a few ms error is acceptable.

  • Hi

    Thanks for clarifying your requirements. If low power on the peripheral side is more important than on the central side then it might be better to put the peripherals in PTX mode and the central in PRX mode. 

    The reason for this is that in general the PRX will have much higher current drain than the PTX, since it needs to keep the receiver running most of the time in order to pick up the packets from the PTX. 

    You can get around this issue by having the PRX synchronize to the packet interval of the PTX, but this is more challenging to implement, especially when you have multiple PTX's. 

    This means you won't be able to use the trick of sending a single packet from the central to all the peripherals, but you would instead require the PTX's to send a poll packet to the PRX at certain intervals in order to get a timestamp in return. Only one PTX can talk to the PRX at the time, but as long as you always send the current state of the timer on the central side this shouldn't be an issue. 

    Another advantage of this method is that it makes it easy for the peripherals to control when they receive a timestamp, and they can use this to only request a new timestamp when the old one expires (depending on the accuracy of the local timer, and your accuracy requirements, the peripherals need to get an updated timestamp from the central once in a while). 

    What is the maximum number of peripheral devices you expect to connect to a single central?

    Best regards
    Torbjørn

Related