How to update Timestamp using the time.h library in NRF52840

Hello guys,

I'm stuck trying to produce a timestamp for data synchronization in my project. I have gone through some of the issues raised in this regard but none was actually helpful. 

Currently I am using the time.h library, but the time doesn't get updated. it keeps printing the same time.

Now I tried using a static incrementing counter to update the ".tm_secs" struct member, Now the time updates over as the counter increment. but the minute and hour field soesn't get updated when ".tm_secs" gets to 59.

I don't know if this is the best approach, but I just want to produce a time epoch, I can always set the epoch with the current time over my GSM modem.

  • Not sure how helpful this will be, but I just store the epoch as an integer (uint32 to be exact). This will provide a valid timestamp until February 2106 (if my code is still around at that time, then the next person can fix it). Not sure how this relates to what you're wanting to do with the modem, but I don't see why it wouldn't work.

    As an example:

    uint32_t timestamp = 1672531200U; // 01.01.2023 12:00:00 AM

    Then to add a second you can simply:

    timestamp += 1U;

    To get the date and times you can use these public domain functions.

    You can see how it works easily here, just put in the timestamp, convert it, add one to it, convert it, etc.

    Just as an example of how I use it to convert the date & time (may be helpful to others as well).

    Date and Time Structures

    typedef struct CsDate {
        CsMonth_t month;
        uint8_t day;
        uint16_t year;
    } CsDate_t;
    
    typedef struct CsTime {
        uint8_t hours;
        uint8_t minutes;
        uint8_t seconds;
    } CsTime_t;
    
    typedef struct CsDateTime {
        CsDate_t date;
        CsTime_t time;
    } CsDateTime_t;

    Datetime from Timestamp

    You're probably not worried about DST, but if you are let me know and I can show you that code as well. The other function are in the link above.

    CsDateTime_t datetime_from_timestamp(const uint64_t timestamp, const bool apply_dst)
    {
        const uint16_t oneHour = 60U /* seconds */ * 60U /* minutes */;
        uint64_t epoch = timestamp;
        CsDate_t date = civil_from_days(epoch);
    
        CsDateTime_t datetime = {
            .date = {
                .month = date.month,
                .day = date.day,
                .year = date.year + 1900U
            },
            .time = {
                .hours = 0,
                .minutes = 0,
                .seconds = 0
            }
        };
    
        if (apply_dst && dst_active(datetime))
        {
            epoch += oneHour;
            date = civil_from_days(epoch);
        }
    
        const uint32_t remainderHours = epoch - (epoch / 86400) * 86400;
        const uint32_t hours = remainderHours / 60U / 60U;
        const uint32_t remainderMinutes = remainderHours - hours * oneHour;
        const uint32_t minutes = remainderMinutes / 60U;
    
        datetime = (CsDateTime_t) {
            .date = {
                .month = date.month,
                .day = date.day,
                .year = date.year + 1900U
            },
            .time = {
                .hours = hours,
                .minutes = minutes,
                .seconds = remainderMinutes - minutes * 60
            }
        };
    
        return datetime;
    }

    Datetime to Timestamp

    This is helpful if you want to go from the datetime back to the timestamp

    uint32_t datetime_to_timestamp(const CsDateTime_t datetime)
    {
        return (uint32_t)datetime_to_timestamp_64(datetime);
    }
    
    uint64_t datetime_to_timestamp_64(const CsDateTime_t datetime)
    {
        return datetime.time.seconds +
                (60LL * (datetime.time.minutes + 60LL * datetime.time.hours)) +
                (86400LL * days_from_civil(datetime.date));
    }

  • Hi 

    I recently did something similar in a hobby project of mine, where I needed to keep track of time. 

    I set the time using the clock_settime(..) function, like this:

    struct tm start_time;
    struct timespec ts;
    time_t t;
    
    start_time.tm_year = 122;
    start_time.tm_mon = 0;
    start_time.tm_mday = 24;
    start_time.tm_hour = 8;
    start_time.tm_min = 12;
    start_time.tm_sec = 12;
    t = mktime(&start_time);
    
    ts.tv_sec = t;
    ts.tv_nsec = 0;
    
    clock_settime(CLOCK_REALTIME, &ts);
     

    Then I can simply read out the time like this:

    // Check current time 
    t = time(NULL);
    ptr = localtime(&t);

    You can find the source here.

    Best regards
    Torbjørn 

  • This was very helpful James!! I have been able to implement the timestamp algorithm. The attached links were indeed helpful, Thank you so much.

  • While I have solved the underlying issue, I will try this out and compare what I have with yours. Thank you, sir!

    Edit: I have tried replicating this code but I ran into this error:

    main.c:67: undefined reference to `clock_settime'
    collect2.exe: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.
    FATAL ERROR: command exited with status 1: 'C:\ncs\toolchains\31f4403e35\opt\bin\cmake.EXE' --build 'c:\nordic\myapps\firmware\app\build' 

    I have included these libraries:

    #include <time.h>
    /* clock_gettime() prototype */
    #include <zephyr/posix/time.h>
    but the error keeps occurring.
  • I have fixed the error, i included "

    CONFIG_POSIX_CLOCK=y

    "

    in my prj.conf file.

    Thanks!!!!

Related