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

"synchronize" two devices

I have two nrf51822 devices, one running s110, the other s120. The s110 device reads ADC values every 20ms, and if they changed from the last reading it sends a notification with the values to the s120 device. My connection interval is 7.5ms, so this works fine. (packet is only 9 bytes). However, I also wish to know roughly how "old" the ADC readings are when received on the s120 device. I used the ble_app_multilink example in the SDK as a basis for the project, and tried the following:

I modified it so that when the s120 enables notifications on the s110 it also starts RTC1 with a 64 prescaler. When the s110 receives this it also starts its RTC1 with the same prescaler. The idea is that the real-time clocks on the two devices are now roughly in sync, disregarding the time it takes to send and process the packet. This difference will in any case only add a constant offset. Every time the s110 sends a message to the s120 it will timestamp the message, and the s120 will check how late it is. Since the packets are timestamped, then queued, i expected the difference to be maximum one connection interval, but the values seem to be completely random, anywhere from 2 ticks, to about 35 ticks. (~4ms to ~70ms). The s120 device makes use of the ble_radio_notification to know when exactly to start the RTC, so i'm guessing it should be fairly accurate.

So, I have two questions:

  1. Why do i see such large variation in the received packets?

  2. Is there a better way to know how "old" the received packet is?

    1. I think the variation of 70ms is larger than what to expect with a 7.5ms connection interval. The delay could be a little larger than 7.5ms as a result of processing delays in the protocol stacks on both ends, but I guess you should not be seeing much more than 10ms delay if you are only sending one packet per connection interval. The softdevice will block the CPU while processing a radio event, so that would worst case add 1ms delay on each end when sending one packet per connection interval.

    Is your connection interval really 7.5ms? Have you verified that? Do you see that on air?

    Also, are you using 32kHz RC internal oscillator as a clock source for the RTC or an external crystal? If you are using crystal, what is the accuracy? If you are using the RC, you must synchronize it periodically in order it for being usable for this purpose.

    Since this is a wireless packet transmission, retransmissions are perhaps evident, specifically if you have other 2.4GHz devices in the area, e.g. other Bluetooth devices, or WIFI devices. Also if the range between the devices is relatively long for the chosen radio TX power.

    1. I think your method is good in synchronizing the peripheral and central. If you use the radio notification event that is triggered at the end of the radio event, that should not be more than 1ms later than the actual packet transmission to the peripheral, so I think there should not be more than 1ms difference between the RTC timers on the central and peripheral. I can however not rule out that there might be some undetermined latency in lower layers of the stack when enabling notfications, by writing to the CCCD on the peripheral.

    The best synchronization option however would be to connect a GPIO pins together on the two devices. I am guessing this is not a valid method for you in practice but perhaps it is good for verification purposes, if you have any doubt about the actual accuracy of the over-the-air synchronization method that you are using. For this purpose, you could start a timer on the peripheral and at the same time set the GPIO pin. On the central device, receive the signal with GPIOTE event and connect the GPIOTE event with a TIMER->START task, using a PPI channel, which will start the TIMER with no latency.

    To minimize the delay from ADC sampling to receive measurement in the central application, you could use radio notification on the peripheral to measure and send the packet just before the radio event. Then you will minimize the delay as result of the connection interval, you will have perhaps 1ms max delay instead of the 7.5ms.

    Update 17.10.2014 From the fact that your S120 code is based on the ble_app_multilink_example and that you are not receiving packets for about 60ms, I now highly suspect that the S120 is scanning for other devices after it has connected with your S110 device. The default scanning window in the example is 50ms. When the S120 is scanning for new devices, it is not able to receive packets for an existing connection at the same time.

    When the S120 gets a connection confirmation from the S110 device it will throw an event to the application which is captured in the device_manager_event_handler. If you change the value of MAX_PEER_COUNT to 1 (is default 8), the S120 will not scan for additional devices after it has connected with your S110 device.

  • I'm pretty sure the connection interval is 7.5 ms. I'm reading the conn_params in the BLE_GAP_EVT_CONNECTED event, and both min and max are 6 (6x1.25=7.5). I also tried using the sniffer, and I'm seeing some weird results: wireshark capture To start off with, it seems like there is about 7.5ms between every event, but on every 7th event, it waits ~62ms until the next one. Coincidentally, this is the max delay i saw earlier, plus a connection interval (62+7.5). Retransmissions was also my first thought, but I've tried in two different environments, one with little activity, and I'm still seeing the same results. The distance between the devices is about 2 meters. Also, I'm using the RC oscillator, and I realized I'm not actually calibrating it, so this might be a large error-source.

  • Aaaah! I completely forgot it keeps scanning.. Never considered that might be the problem, thanks a lot :) The delay is now dead-constant at about 3.5 ms, but some of this might be because the RTC's dont start at the exact same time.. i'll try synchronizing them using GPIO as you suggested at a later time to check this, but for now this is good enough.

Related