My application has two 580, a master and a slave
I want the two to have time synchronization ,and the time accuracy is 0.01s, better to be 0.001s.
Assuming that the synchronisation requirement applies only to a connected state, you should be able to rely on the timing of connection events ending (this event can be detected in rwble.c - look for the BLE_EVT_END in that file).
I studied your advice these days, I suppose the master and slave BLE_EVT_END happens synchronously, I can get the time immediately after BLE_EVT_END happens from both sides, then I can have the time synchronized.
while BLE_EVT_END happens so frequently, I can't find the corresponding events from the two sides, how to solve this problem?
Thanks a lot.
The BLE_EVT_END events on BLE master and slave should be as close to syncronous as you can get. If you want to limit when the synchronization takes place, you can implement a GATT characterisitic that you write to which then drives the logic to synchronize on the end of the following event. You can add your synchronization code in the rwble.c right after the event has been recorded (this line records the event: arch_rwble_last_event = BLE_EVT_END; - note that you will find this line twice in rwble.c. Which one of them that actually is executed depends on your power optimization setting). There may be a fixed time delay between the event triggering on the central and the event triggering on the peripheral, but it will be small, constant, and could therefore be compensated for.
One of the advantages of using the BLE_EVT_END is that you will have a lot of time available to manage the synchronization algorithm. No high priority IRQs will need processing until the next connection event.
You can use the function uint32_t lld_evt_time_get(void) to get the current time in increments of 625us. If you need better timing than that, you will have to disable sleep and use the systick timer which could provide as low as 1us accuracy.
Please let us know if you manage to implement the suggested solution. I imagine that this synchronization scheme would be really powerful in conjunction with ultra-sound in a ranging/distance application. Properly implemented, you could likely get to inch or even centimeter type precision.
Thanks a lot for you quick response.
My question centers around how to 'recognize' the corresponding BLE_EVT_END of the same connection from master and slave,because the event comes one after another very quickly,I can't distinguish different BLE_EVT_END events.
The application is distance application, but not ultra-sound ranging.
0.01s time synchronization accuracy can meet my application requirement,better synchronization is preferred as I don't need to reset the synchronization due to time drift for short time use,I will implement the suggested solution, but now I focus on how to 'recognize' the corresponding BLE_EVT_END from two sides.
Writing to a characteristic and knowing the connection interval should allow you to tag a connection. Transmission of the data will happen on the following connection event and so will reception on the server side (again, there could be an offset, but this offset should be constant). The client will receive a confirmation when the data has been transmitted, the server will receive an indication that data has arrived.
我的问题是两个580主从时间同步的问题，如何才能确定主从的BLE_EVT_END为相对应的Event呢？ 因为 BLE_EVT_END 是在不停快速地重复出现，我不知道如何确定主从对应的Event。
Thanks a lot for you answer.
To be frank, I'm a new hand in this field and though I feel your answer may be the right one to my question, after a lot study, still don't know how to do.
1.What is the confirmation and indication? BLE_EVT_END? or other event?
2.Still I don't know how to tag the connection, there should be some thing different to distinguish it, I think.
Hope you will not be impatient about my questions.
Let me start by saying that what you have set out to do is not simple :o)
But here is how I would try to implement the core of it. First, on both the central and the peripheral, use the app_on_connection event to reset a global counter. Then, in rwble.c, find the two places that refer to BLE_EVT_END (there are two implementations of this event. Which one runs depends on your use of "USE_POWER_OPTIMIZATIONS"). Both implementations have a line like this:
arch_rwble_last_event = BLE_EVT_END;
After this line, on both central and peripheral, you can increment the global counter that you reset in the app_on_connection event as described above. The two counters, one on the central/Master and one on the peripheral/Slave will run synchronously because BLE events on both sides end at "nearly exactly" the same time (microseconds apart) - as long as you do not start implementing slave latency. The counter will be your coarse time. This will give you a synchronized master and slave, but the granularity depends on the connection intervals (7.5ms minimum). To implement a finer granularity you could implement a fine timer based on the SysTick timer (see the reference manaual for details). This timer should be reset at every BLE_EVT_END and would allow you to decrease the granularity to a few microseconds. Note that the SysTick timer will only work when the device is awake, so the fine timer is only valid while you are awake.
I hope that helps. Let us all know how it works out.
I just implemented the concept described above and the result is promising. I used the CodeLess project as a starting point and changed rwble.c to toggle a GPIO high on the BLE_EVT_END. I then load this modified CodeLess hexfile onto two development kits and establish a connection between them via AT commands (see the CodeLess documentation). I use a logic analyser to monitot the two GPIOs and I see them being separated by a 3us offset with a deviation of +/- 500ns. In a ranging application using sound, the 500ns amounts to sound traveling less than 0.2mm.
There will be times where the slave will miss the transmission from the master (That's the "beauty" of RF), so you would need to do some dead-reckoning of the timer between the events to filter out those instances. But they should be easy to detect.
I'm testing the method you gave me,generally speaking,it's a good approach and can meet my needs. I plan to have more test as there is problem, seeing you have more information here, I put my test result here first.
The problem I met is that there are about 1% cases the BLE_EVT_END is not happend synchronously,either from the master side or from the salve side, in the most serious case,the asynchronization is 0.5ms,while the other 99% cases, the synchronization is very good.
For my application, 0.5ms asynchronization is acceptable,actually,I can find out the asychronization if I want.
I'm having more test to find out if it's real asynchronization or it's due to other reasons.
You mentioned "slave will miss the transmission from the master" Do you mean BLE_EVT_END will not happened in pairs? I had worried about this, but acc. to my test, this never happened. If this can theoritically happen or enen actually happened as you've found, I can manage to avoid it's effect.
Again thank you Mikael.
Good to hear that you are seing results already. In the world of RF, you will occasionally come across a channel that is blocked by other traffic and this leads to "miissing" connection events. The slave may miss the TX from the master and will attempt to keep its receiver open a little longer. The slave does not consider the event to be over until it times out and this leads to the BLE_EVT_END to trigger a little later seen from the point of view of the slave. The event still happens - but you are not actually in sync with the master. This is likely what you are observing. 0.5ms sounds about right.
Thanks a lot for you quick response.
Still for "slave will miss the transmission from the master" ,it sounds the content may miss sometimes, while the events(BLE_EVT_END
) will never miss(though occasionally there might be some delay), in other words, BLE_EVT_END always happens in pairs at host and slave.
This is very important,if I suppose the event happens in pairs,while sometimes there is missing event in single side(either host or slave),there could be big problem.
I need a confirmation.
If in theory, there will not be any missing events or miss on both sides , I will be at ease.
or in theory, there will be possibly missing events in single side, I need to consider this in my function.
I can confirm that there will always be the same amount of events on both sides. The slave may not "hear" from the central, but the event will still end - though the timing will miss by something in the order of half a millisecond. In other words there will be some outliers as far as timing, but the event count on the master side will always match that of the slave. In your case, where 1ms accuracy is good enough, you really do not have to filter anything out.
Hi MHv_Dialog ,
I will use the function uint32_t lld_evt_time_get(void) to get the current time as you recommended, I found it will be very convenient for me to be able to reset this timer,is there any function available for me to do so?
No such function available, unfortunately.