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

Nordic Calendar example (https://github.com/NordicPlayground/nrf5-calendar-example) related issue

I wanted to implement a time sync feature on nRF-52840 DK. I took a reference from this example, but there were certain things unclear to me.

Can somebody explain to me what is calibrated and uncalibrated time here? and what exactly are we doing here in this example?

Parents
  • In this example, a calendar is periodically synced with an outside time-stamp. It does not cover how you obtain the outside time-stamp, just how you can use it to update the calendar. 

    As the calendar uses the RTC as it's base clock, it will experience a fair amount of drift, +/- 10-20ppm at best, and will need to be periodically calibrated/synced. 

    I believe the uncalibrated time is the current time of the calendar, and the calibrated time is the provided synchronization time-stamp.

  • I flashed this example on an nRF52840 DK and I got this output on serial

     when I use the get function(option g) to get the time, I get this as the output where the calibrated and the uncalibrated time is the same.

     next, when I use the run continuous-time updates (option r), I get a time difference of 4 seconds every time and I just don't get it that why is there such a big difference.

    Later I set time to current time and then tried to run continuous-time updates (option r) and still there is a time difference of 4 seconds.

    can you please explain this behavior?

  • Hi

    The RTC timer doesn't have the accuracy to count milliseconds, since it is running off of a 32.768kHz clock. 

    If you modify the calendar example to use a TIMER module instead of the RTC then you can count milliseconds also, but this requires a fair bit of changes to the example.

    This will also increase the sleep current significantly, so if power consumption is important to you it might not be the best solution.  

    Best regards
    Torbjørn

  • ya power consumption is important to me. so what is the best solution to get YY:MM:DD hh:mm:ss:ms like this using rtc? any other example should i use

  • Hi

    On second thought you should get decent millisecond accuracy using the RTC. For some reason I thought about microseconds, not milliseconds, when I replied to you earlier...

    If you change the prescaler to 0 in the calendar example the RTC will run at the full 32.768kHz clock speed, and if you divide the RTC counter value by 32.768 you should get the current time in milliseconds. 

    The important factor is that you need to update all references to the CAL_RTC->COUNTER register, since this value will now be much higher (rather than increase by 8 every second it will increase by 32768 every second). 

    Also, the maximum time the RTC can run without being cleared will be much shorter, since the 24-bit RTC counter will overflow in 512 seconds when the prescaler is 0. 

    Best regards
    Torbjørn

  • omg i learned so much about rtc from you guys thanks and sorry for keep bugging you i grasped everything about that nrf calender except one thing why are  you using this function and what is the purpose of this function

    void nrf_cal_set_callback(void (*callback)(void), uint32_t interval)
    {
    // Set the calendar callback, and set the callback interval in seconds
    cal_event_callback = callback;
    m_rtc_increment = interval;
    m_time += CAL_RTC->COUNTER / 8;
    CAL_RTC->TASKS_CLEAR = 1;
    CAL_RTC->CC[0] = interval * 8;
    },

    and also how can i print something like this int count =CAL_RTC->COUNTER / 32.768;

    printf("%d",count);;is this correct.I want to see the values myselfs before sending it over ble

    and also what happens when overflow occurs and how can i rectify that

    REGARDS

    MANIKANDAN V

  • Hi Manikandan

    I am happy I could be of help Slight smile

    The purpose of this function is to provide a callback function to the library that will be called at a regular interval, which is useful if for instance you want to log the time regularly in your code, or if you want to display the time somewhere at regular intervals. 

    If you want to schedule some activity at a certain time in the future you can also use this callback to check the current time once in a while, and perform some activity once you reach a certain point in time. 

    As an example, if you create a void(void) function in your code and forward it to this function with the interval set to 60, your function will be called once every minute:

    void do_something(void)
    {
        // This code will run once every minute
    }
    
    .
    .
    
    nrf_cal_set_callback(do_something, 60);

     

    manikandan said:

    and also how can i print something like this int count =CAL_RTC->COUNTER / 32.768;

    printf("%d",count);;is this correct.I want to see the values myselfs before sending it over ble

    In order to divide the value by 32.768 you would have to convert the COUNTER value to float first, like this for instance:

    int count_ms = (int)((float)CAL_RTC->COUNTER / 32.768f);

    It is also possible to rewrite the formula and perform it all in integers:

    int count_ms = (CAL_RTC->COUNTER * 250 + 125) / 8192;

    Please note I haven't tested any of these code snippets, so take them with a grain of salt ;) 

    manikandan said:
    and also what happens when overflow occurs and how can i rectify that

    When an overflow occurs the RTC COUNTER value will be reset back to 0, and since the code is not set up to handle this it will lead to incorrect time updates. 

    To avoid this simply call the nrf_cal_set_callback(..) function with an interval lower than 512 seconds.

    Then the  RTC IRQ handler will be called before the overflow happens, and you should not have any issues. 

    Best regards
    Torbjørn 

Reply
  • Hi Manikandan

    I am happy I could be of help Slight smile

    The purpose of this function is to provide a callback function to the library that will be called at a regular interval, which is useful if for instance you want to log the time regularly in your code, or if you want to display the time somewhere at regular intervals. 

    If you want to schedule some activity at a certain time in the future you can also use this callback to check the current time once in a while, and perform some activity once you reach a certain point in time. 

    As an example, if you create a void(void) function in your code and forward it to this function with the interval set to 60, your function will be called once every minute:

    void do_something(void)
    {
        // This code will run once every minute
    }
    
    .
    .
    
    nrf_cal_set_callback(do_something, 60);

     

    manikandan said:

    and also how can i print something like this int count =CAL_RTC->COUNTER / 32.768;

    printf("%d",count);;is this correct.I want to see the values myselfs before sending it over ble

    In order to divide the value by 32.768 you would have to convert the COUNTER value to float first, like this for instance:

    int count_ms = (int)((float)CAL_RTC->COUNTER / 32.768f);

    It is also possible to rewrite the formula and perform it all in integers:

    int count_ms = (CAL_RTC->COUNTER * 250 + 125) / 8192;

    Please note I haven't tested any of these code snippets, so take them with a grain of salt ;) 

    manikandan said:
    and also what happens when overflow occurs and how can i rectify that

    When an overflow occurs the RTC COUNTER value will be reset back to 0, and since the code is not set up to handle this it will lead to incorrect time updates. 

    To avoid this simply call the nrf_cal_set_callback(..) function with an interval lower than 512 seconds.

    Then the  RTC IRQ handler will be called before the overflow happens, and you should not have any issues. 

    Best regards
    Torbjørn 

Children
  • hello, thanks for your help  i can be able to get milliseconds and run a 24 hours clock successfully now i want to do time sync up that day you told if we are developing our own app it is possible to get a timestamp in the app and send it over a proprietary service to the nRF52 device every time i connect.

    1)indeed we are developing our own app can you elaborate on how can i get that timestamp in program and set that time in nrf_cal_set_time(..) ??

    2)where do i get my timestamp in ble_app_uart program?? in nus_data_handler(..) function uh??

    thanks and regards

    Manikandan V

  • Hi Manikandan

    1) Not sure which mobile platform you are targeting, but on Android there is a LocalTime library for getting time and date information, and I am sure something similar exists for iOS. 

    The important thing is that you get an integer timestamp that can be passed over the BLE link. 

    2) That is correct. By default the ble_app_uart example uses the nus_data_handler(..) function to process incoming data from the app. 

    Best regards
    Torbjørn

  • hello  i am using android and developed an customised app and doing something like this is

    for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
    {
    str[i]=p_evt->params.rx_data.p_data[i];

    strcpy(buf,str);

    uint8_t j=0;
    char *pch = strtok (buf,"- :");
    while (pch != NULL)
    {

    array[j]=pch;
    j=j+1;
    pch = strtok (NULL, "- :");
    }
    year=atoi(array[0]);
    month=atoi(array[1]);
    day=atoi(array[2]);
    hour=atoi(array[3]);
    minute=atoi(array[4]);
    second=atoi(array[5]);
    ....

    }

    note: i am sending the current time from app everytime i connect with bluetooth and getting the exact values in year,hour,...,seconds variable.

    but if  i call nrf_cal_set_time(..) in main to starts from 1970  but not with the time i sent

    my main looks like this

    int main();

    {

    //all init

    nrf_cal_set_time(year, month, day, hour, minute, second); 

    while(1)
    {

    length=sprintf(cal_string,"%s", nrf_cal_get_time_string(true)); 

    ble_nus_data_send(&m_nus,cal_string,&length,m_conn_handle);
    }

    }

    where should i call nrf_cal_set_time(..) in my program to make it run one time and start sending date and time from the time i sent.

    Thanks and regards

    Manikandan V

  • Hi 

    My initial thought is that you seem to be over complicating things a little. 

    Can't you just code year/month/day/hour/minute/second each into a separate byte without converting to and from ascii representation?

    Then you only need 6 bytes in total to represent a date and time update, and you can easily copy each byte from the rx_data.p_data buffer into the 6 variables (just remember to subtract 1970 from the year before sending it, and add it back here, since a single byte can't store numbers > 255). 

    Best regards
    Torbjørn

  • sir kindly check my new thread about sending 100 packets per send and give me suggestions

    thanks and regards

    manikandan v

Related