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

How to schedule events and tasks at particular time intervals

Hi Dev Team,

I am running a program that takes in sensor data at 10 min intervals and publishes it to my server through MQTT at 1hr intervals.

I have different threads running for different events (Taking data from sensor and sending data outside). I am using the kernel timers to execute these events repeatedly.

Now, I want to schedule these events in such a way that I start my program at any time and then it reads the sensor value at 00:00 (12 am), 00:10 (12:10)... with 10 mins interval and then publishes my sensor value to server through MQTT every 1 hour (01:00, 02:00....) at exact times. 

Currently, I just start the program and then the process initiates at that time and continues. But I need the data to be read at specific times i.e: start of the hour time (like exactly at 12:00,12:10, 12:20, 12:30, 12:40, 12:50, 01:00) and then publish the data exactly at 01:00,02:00,03:00... and then continue this process.

Could you let me know how to schedule events such that they happen sequentially at the time I need.

Regards,

Adeel. 

Parents
  • Hi, Adeel!

    You can sample the current time using the Date-Time library of NCS. If you do this on startup, after connecting to LTE, you can start a timer based on the time you get or alternatively submit a delayed work item

    Best regards,
    Carl Richard

  • Hi Carl,

    I am using the date_time library to get the real time using the NTP server. 

    Can you let me know how can I use this time to synchronize my next intervals.

    For example, my sample starts at 17:02:09 and I want my next interval of sending data over MQTT to occur at 18:00:00. 

    For some reason, even if my application sample starts at 17:25:34 , still I want it to send the first data at 18:00:00 . 

    Once I send the data for the first time, then I understand that the kernel timers can schedule it as per our timer allotment.

    How can I schedule events like this because the kernel timers are defined for fixed intervals ? 

    Ex: k_timer_start(&my_connect_timer, K_SECONDS(60), K_SECONDS(3600)); // To send data every hour but the start of the sample and my intervals don't match now. My sample starts at 17:25:34 and I need to synchronize it to send the first data at 18:00:00. Could you help me explain how tis could be done ? 

    Regards,

    Adeel.

  • Hi, Adeel!

    I suggest that you do the following procedure:
    1. Start up, connect and get current time
    2. Submit a delayed work item as described in the documentation. You can calculate the delay by converting to human readable time (see the attached code) and calculating how much time is left to, for example, the next whole hour. 
    3. You can then avoid doing this again by starting a timer with the work item that makes the device transmit at the desired interval afterwards. Note that it may drift over time, so you should calibrate after a certain amount of uploads.

    Delay calculation code below:

    //Get timestamp
    int64_t curr_time;
    date_time_now(&curr_time);
    
    int64_t curr_time_s = curr_time/1000;   			//Convert to seconds
    struct tm * readable_time = gmtime(&(curr_time_s)); //Get human readable time with time.h
    LOG_INF("Curr min: %d", readable_time->tm_min);
    LOG_INF("Curr sec: %d", readable_time->tm_sec);
    
    int delay = 3600-(readable_time->tm_min)*60 - readable_time->tm_sec;


    This requires the time.h library. I hope it makes sense!

    Best regards,
    Carl Richard

Reply
  • Hi, Adeel!

    I suggest that you do the following procedure:
    1. Start up, connect and get current time
    2. Submit a delayed work item as described in the documentation. You can calculate the delay by converting to human readable time (see the attached code) and calculating how much time is left to, for example, the next whole hour. 
    3. You can then avoid doing this again by starting a timer with the work item that makes the device transmit at the desired interval afterwards. Note that it may drift over time, so you should calibrate after a certain amount of uploads.

    Delay calculation code below:

    //Get timestamp
    int64_t curr_time;
    date_time_now(&curr_time);
    
    int64_t curr_time_s = curr_time/1000;   			//Convert to seconds
    struct tm * readable_time = gmtime(&(curr_time_s)); //Get human readable time with time.h
    LOG_INF("Curr min: %d", readable_time->tm_min);
    LOG_INF("Curr sec: %d", readable_time->tm_sec);
    
    int delay = 3600-(readable_time->tm_min)*60 - readable_time->tm_sec;


    This requires the time.h library. I hope it makes sense!

    Best regards,
    Carl Richard

Children
  • Hi Carl,

    Yes, I understood the logic of calculating the delay and this is what I needed.

    Thanks a lot, got it working at my end through the delayed work queue :).

    Regards,

    Adeel.

  • Hi Carl,

    I had a question regarding this ticket. The above code that you sent worked perfectly for NCS v1.3.0 .

    I did this in NCS v1.3.0 and this works perfectly.

    	modem_configure();  //to get LTE connection
    
        date_time_update(); //To get current time
    
        printk("Busy-wait %u s\n", BUSY_WAIT_S);
        k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);  //2 seconds delay
    
        int64_t curr_time;     //above code
        date_time_now(&curr_time);
    
        int64_t curr_time_s = curr_time / 1000;            //Convert to seconds
        struct tm *readable_time = gmtime(&(curr_time_s)); //Get human readable time with time.h
        printk("Curr min: %d\n", readable_time->tm_min);
        printk("Curr sec: %d\n", readable_time->tm_sec);
    
        int32_t delay = 3600 - (readable_time->tm_min) * 60 - readable_time->tm_sec;
        int32_t real_time = delay + 600;
        printk("Delay is: %d\n", delay);
        printk("Real Delay is: %d\n", real_time);

    The above output is correct.

    But when I try to do the same in NCS v1.4.2 or NCS v1.5.0, it doesn't work the way I want it to.

    	modem_configure(); //for LTE connection
    
        date_time_update_async(NULL);  //to get current time
    
        printk("Busy-wait %u s\n", BUSY_WAIT_S);
        k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);  //2 seconds delay
    
        int64_t curr_time;   //above code
        date_time_now(&curr_time);
    
        int64_t curr_time_s = curr_time / 1000;            //Convert to seconds
        struct tm *readable_time = gmtime(&(curr_time_s)); //Get human readable time with time.h
        printk("Curr min: %d\n", readable_time->tm_min);
        printk("Curr sec: %d\n", readable_time->tm_sec);
    
        int32_t delay = 3600 - (readable_time->tm_min) * 60 - readable_time->tm_sec;
        int32_t real_time = delay + 300;
        printk("Delay is: %d\n", delay);
        printk("Real Delay is: %d\n", real_time);
    

    The only change is using : date_time_update_async(NULL) as date_time_update() is not supported in higher NCS versions.

    I get the following in NCS v1.5.0 : 

    This output is incorrect (the Curr min and Curr sec are wrong).

    Could you try to reproduce this in NCS v1.5.0 and verify ?

    Regards,

    Adeel.

  • Hi, Adeel!

    You're getting an error when calling date_time_now that indicates that a valid time aren't available yet. Instead of busy_wait I suggest that you use a blocking semaphore that is released by a handler for date_time_update_async callbacks. This way you can ensure that a valid time is available when calling date_time_now.

    You can how I have done this here.

    Best regards,
    Carl Richard

  • Hi Carl,

    Thanks for this lead. Got it working by using the blocking semaphore Slight smile.

    Regards,

    Adeel.

  • Hi Carl,

    I just had another question to ask regarding the above thread. 

    I am having a pretty poor reception using : CONFIG_LTE_NETWORK_MODE_LTE_M 1

    So, I tried to change to NB-IoT using : CONFIG_LTE_NETWORK_MODE_NBIOT to improve my RSRP.

    I did it through the autoconf.h file.

    The NB-IoT is configured properly as well and I can see it when I do : 

    AT%XSYSTEMMODE?
    
    
    
    
    %XSYSTEMMODE: 0,1,0,0
    
    
    
    
    OK
    
    
    
    

    This helps me understand that I have configured for NB-IoT. 

    I try to run my application with NB-IoT config but I see that the date_time handler does not give me the right time.

    It works perfectly with the : CONFIG_LTE_NETWORK_MODE_LTE_M

    Do I need to do anything else in order to set up my device with NB-IoT config ?

    P:S : I am in Germany and NB-Iot works well here.

    Regards,

    Adeel.

Related