nordic-auko / nrf5-ble-timesync-demo Goto Github PK
View Code? Open in Web Editor NEWnRF52 clock synchronization demo code
nRF52 clock synchronization demo code
I'm new to nrf products and nrf5 sdk, so these questions might come off as " just rtfm" material, but I'm asking them because I ran into various issues when trying to answer these myself.
Thanks!
I'm trying to adapt this example for a different application and would like to use the debug compare event (pin 0.24) to trigger an SAADC measurement.
For now I'm trying to adjust the toggle frequency of the debug pin. Using the peripheral example in this repo, P0.24 toggles with a period of 5 ms. This toggle frequency corresponds to the value set in the CC[0] register (40,000) and not the vale in the CC[4] register (20,000) as configured in the PPI endpoint. If the CC[4] compare is toggling the pin the period should be 2.5 ms.
Can you provide some guidance on how to adjust the pin toggle frequency? I see that there is a CC[0] clear shortcut configured for this timer but I believe that should only occur when the timer reaches a count of 40,000. It seems like the pin is currently toggling when the timer reaches CC[0] and not when it reaches CC[4].
nrf_ppi_channel_endpoint_setup(
NRF_PPI_CHANNEL0,
(uint32_t) nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE4),
nrf_gpiote_task_addr_get(NRF_GPIOTE_TASKS_OUT_3));
nrf_ppi_channel_enable(NRF_PPI_CHANNEL0);
static void sync_timer_start(void)
{
// m_params.high_freq_timer[0] (NRF_TIMER) is the always-running sync timer
// The timing master never adjusts this timer
// The timing slave(s) adjusts this timer whenever a sync packet is received and the logic determines that there is
m_params.high_freq_timer[0]->TASKS_STOP = 1;
m_params.high_freq_timer[0]->TASKS_CLEAR = 1;
m_params.high_freq_timer[0]->PRESCALER = SYNC_TIMER_PRESCALER;
m_params.high_freq_timer[0]->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
m_params.high_freq_timer[0]->CC[0] = TIME_SYNC_TIMER_MAX_VAL;
m_params.high_freq_timer[0]->CC[1] = 0xFFFFFFFF;
m_params.high_freq_timer[0]->CC[2] = 0xFFFFFFFF;
m_params.high_freq_timer[0]->CC[3] = 0xFFFFFFFF;
if (m_params.high_freq_timer[0] == NRF_TIMER3 || m_params.high_freq_timer[0] == NRF_TIMER4)
{
// TIMERS 0,1, and 2 only have 4 compare registers
m_params.high_freq_timer[0]->CC[4] = TIME_SYNC_TIMER_MAX_VAL / 2; // Only used for debugging purposes such as pin toggling
}
m_params.high_freq_timer[0]->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;
m_params.high_freq_timer[0]->TASKS_START = 1;
}
Thanks!
Hello,
I am running this on 2 different boards and experiencing the same issue on boath
I am very interested in the NCS implementation of this app, and I have downloaded and got it to build with NCS version 2.3.0. I did not run into any major issues in this porting process. I am curious if you have seen the following issue - when I build and flash to the NRF52 DK (nrf52832), and then press button 1, I see:
I also downloaded this and ported it to work with the nrf5340 DK. This was quite the process but I also got some help in a private ticket on DevZone with Sigurd Olav Nevstad in private case ID #293529 (in case you can see this). When flashing to the nrf5340 DK, I also see the issue of MPLS TIMESLOT BLOCKED.
I have not been able to overcome this and I did not see anyone else having this issue. How can I overcome this, or how can I share this code with you to see if you or others have the same issue?
Thanks,
Hi, first of all thank you for the great work that has been done here. Unfortunately I don't posses a nRF52840-DK.I was considering porting the project to the NRF52DK, would it be easy? Wouldn't it take too long?
Thank you in advance!
I cannot break at main. Every time code is loaded, I'm immediately thrown into nrf_log_frontend.c:112 and it hard faults. I've tried using make flash, but this does the same thing. My main method of pushing code is using openocd and arm-none-eabi-gdb for debugging. I've tried enabling logging in the config file, and I've also tried disabling logging in the config file. Both give me the same result. I've also tried using the toolchain from arm (10.3.1) and the version from my package manager (12.1.1). All give me the same result.
When trying to place a breakpoint at main, gdb thinks main is at nrf_log_frontend.c:112
I'm new to nrf and its sdk so this could just be something I'm doing wrong, but I figured this demo was more plug and play than anything else.
hi,
I do have a question regarding the new features you added. I am using a much simpler version of your sync example Where I just want to send the current timer from a master to slaves without adjusting the timer value but storing the distance from the current timer to the master timer. Therefore I skiped the entire EGU stuff because I think I do not need it.
But now in your new version I see, that you are using it for the realing handling. Could you explain it a bit more how this mechanism is supposed to work?
Kind regards,
C.W
Hi,
when I run the example in the examples/ble_peripheral/ble_app_uart/pca10056/s140/armgcc folder I am getting:
undefined reference to `nrfx_ppi_channel_alloc'
I guess this has to be added to the nrfx /src folder.
Kind regards,
Is there a particular reason for it? How many devices can be synchronized?
Okay tested it right now. And it seems to work with just two peripherals. Very nicely done.
Hi all!
I'm full time working to update my code with the new branch (count_revamp).
I download the branch, flashed my boards and press the button to start the syncronization.
After some seconds, this is the situation:
So I reset the boards and I repeat the procedure.
After some seconds, this is the situation:
Are you sure this is a completely tested branch? It seems to be veeeery bugged (at least respect to master branch).
Moreover, if you just download the branch and build it with SES, it fails. I needed to make these changes to build the project:
Is it supposed to be normal?
I think I will need a lot of support in the following weeks.
Thanks for the help
Hi,
when I try to connect with the board configured as peripheral I cannot connect to the board and the JLINK console tells me a fatal error.
Hi Audun,
Have a good day.
I tested this timesync-demo under SDK-16.0 and found that sometimes the device couldn't receive any sync packet sent from master(More specifically time sync stopped itself, a system reset could resume). However the BLE activity works well when the time sync is stopped.
Is there any methods to debug this issue? I tried to re-init the time-sync functions but failed.
If this issue occur how could we to resume the time-sync without system reset or SOFTDEVICE reset?
Appreciate your quick response.
Kindest Regards,
Randy
Software: basic this example, s140_nrf52_7.2.0_softdevice
When using this method for ble central (nrf52840), disconnect very quickly after connected,reason:0x3E. Repeat 10 or more times before establishing a connection。
If i not used "ts_enable()" function ,Everything is working very well。
how to fix it ,Looking forward to your reply very much ,thanks very much
The current code base is not effective for multiple islands of synchronised systems in broadcast proximity.
An option here maybe to use the rxaddress white list in the RADIO. To make this possible the timesync master address must be sent to timesync slaves. This can be managed out-of-band of this timesync protocol.
In time_sync.c, case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0 has no break and no comment why.
Hi,
I'm trying to synchronize an event on multiple nRF52 boards. This code is a really nice starting point, however I had a little bit of trouble with the counter synchronization.
This is my setup:
I'm using the m_params.high_freq_timer[1] to synchronize the blinking of an LED. The master will toggle the LED every 100 counter ticks (250ms). Now I want multiple synchronized slaves that toggle their LED at exactly the same moment.
After modifying the code, I ran into a few strange behaviors / problems:
This should be:
m_master_counter = mp_curr_adj_pkt->counter_val + 1
Because the timer will be reset during the synchronization and the whole reset will take one additional overflow in the master, the counter value needs be increased by 1 for every synchronization.
This one was pretty hard to find and I'm not sure if I my workaround is the best way to resolve it...
If the timer_offset is very small (let's assume timer_offset = 1
), it looks like the timer reset does not work reliable.
What I would expect:
m_params.high_freq_timer[0]->CC[2] = 39999
TIME_SYNC_TIMER_MAX_VAL > 39999
What actually happens:
I suspect that this has something to do with a delay in the PPI tasks and the timer itself.
I found this information in the infocenter:
After the TIMER is started, the CLEAR task, COUNT task and the STOP task will guarantee to take effect within one clock cycle of the PCLK16M.
This means that if the timer_offset
is too small (which happens quite often), the counter value (m_params.high_freq_timer[1]) in the slave is not reset to 0, but to 1 (because CC[0] increases the timer value during reset).
My workaround looks like this:
if (timer_offset < 5) { return false; }
If this value is already greater than TIME_SYNC_TIMER_MAX_VAL
or the time it takes from this line of code to actually setting the CC[2] and activating the PPI group will cause it to become greater than TIME_SYNC_TIMER_MAX_VAL
, the counter in the master will be increased and this is no longer valid:
Once again, the result will be a wrong m_master_counter
in the slave.
In order to prevent this I added the following workaround:
if (peer_timer > (TIME_SYNC_TIMER_MAX_VAL - 10000)) { return false; }
This means that quite a few incoming synchronization requests will be ignored, but because I'm not sure how much time it will take until the following line is called, I tried to add a relativly large "safety" margin.
Because the synchronization itself and the trigger for the LED toggle event are completly asynchronous, the synchronization between master and slave looked completly random. Sometimes the slave would trigger one counter tick too early, sometimes one tick too late, or sometimes it was correct.
After fixing (workaround) all three issues, I tested with an oscilloscope and the synchronization seemed to work perfectly.
Is there any more insight you can give me on these issues? Are there any proposals for better solutions than my workarounds?
I tested all of this with an oscilloscope, however, I forgot to take some screenshots. I you like, I can reproduce the described issues and upload the screenshots.
Thank you in advance!
Hi all,
thanks for the amazing work, I'm using this syncro architecture to sample difference sensors at the same time.
I found some issues regarding syncro frequency.
This plot shows the time between two consecutive syncro packets from transmitter.
I take the data each 2ms (sampling at 500Hz) and the syncro frequency is the standard one (30hz). So, doing some maths, it makes sense for me having values of 16-17 units between each syncro packet. Indeed, each packet is sent every 1/30 = 33ms, I sample each 2ms, I'm expecting to have 16-17 samples between each syncro packet and the next one.
But, as you see, I don't know why every 6 packets, there is a longer interval (66), that is the time used to send 4 packets (16.5*4 = 66).
Do you have an explanation? I was expecting to have always 16-17 samples between each syncro packet.
I want also to highlight that every time I have a 66-samples packet, the receiver misses that packet (I noticed this introducing a counter_packet variable inside the syncro packet).
Thanks for the help,
David
We tried today to modify the example to use BLE LR 500 or 250kbits
We are using NRF52833 (Laird BL653) with SDK 16 and s140
NRF_RADIO->MODE = RADIO_MODE_MODE_Nrf_2Mbit << RADIO_MODE_MODE_Pos;
we tried:
BLE 1MBit worked
NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos;
neither 500 or 125Kbit worked
NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit << RADIO_MODE_MODE_Pos;
NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit << RADIO_MODE_MODE_Pos;
we also tried to increase timeslot length and extension
#define TS_LEN_US (20000UL)
#define TX_LEN_EXTENSION_US (20000UL)
we also tried to to reduce the frequency from 30Hz to 5Hz
It seems that the Sender is sending (its toggling the output) but the receiver is not entering the IRQ Handler (nor toggling).
Maybe you have an idea?
I've test the power consumption both in receiving and sending mode on the nrf52832 minimum system board.
In receiving mode, the average current is about 13mA. But after switched to sending mode, the average current reduced to 1mA.
Which means that the "receiving" (something like scan) costs about 12mA. So is it possible to reduce power consumption in "receiving" mode?
PPI is not enabled within:
nRF5_SDK_16.0.0_98a08e2/examples/ble_peripheral/ble_app_uart/pca10056/s140/config/sdk_config.h
Hi all,
I am working to merge this tool into my project.
I noticed something weird with the TIME_SYNC_TIMER_MAX_VAL parameter, probably I am missing some details.
If I set TIME_SYNC_TIMER_MAX_VAL = 20000, since the main clock is 16MHz, I am expected to see a debug toggling every 1.25ms but I see a synchronous toggling with 2.5ms of period. It is the double of what should be and I can't get why.
Moreover, if I set TIME_SYNC_TIMER_MAX_VAL = 16000, the debug toggling starts correctly but then the two boards start toggling asynchronously and then crash. I made some tests and it seems that if I set TIME_SYNC_TIMER_MAX_VAL smaller than 20000 the platform can't work in stable way for long time.
Any ideas about that?
Thanks,
Alessio
I have read #12 and enabled NRFX_PPI_ENABLED
as shown in the screen, but the IDE still consider it as error.
Hi
I downloaded your code and tryied to build it in Segger Embedded Studio. But there the error comes:
"conflicting types of '__putchar()'
(1) you declare it in stdio.h as follow:
int __putchar(int, __printf_tag_ptr);
(2) then in rectarget.c it is defined as following:
int __putchar(int ch, FILE * p_file)
{
UNUSED_PARAMETER(p_file);
UNUSED_VARIABLE(app_uart_put((uint8_t)ch));
return ch;
}
Can you help me?
Is is ok if I just uncomment the (2) declaration? Will it still run? I'm very very pleased for any help since my thesis will highly depend on it... : (
Dear author.
I want to porting this code to the old version SDK for nRF51822. Can I ask you for an old version of this project?
I tried to compile this example for my nrf52840-DK but I'm running into errors. I switched the examples/ble_central/ble_app_uart_c/main.c from the original SDK 14.2.0 with the ble_central/ble_app_uart_c/main.c. I also copied the time_sync files into the example folder.
Is it even possible to port this example "easily" to the nrf52840-DK?
I'm looking forward to your answers.
Hi,
I was successfully able to incorporate this example code into a project which requires time sync between Nordic devices.
The issue I'm having is that in my implementation the whole sync mechanism to be dependent upon an external clock input (PWM, roughly 10Hz)
What would be the best approach to implement this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.