NTP time synchronisation help

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

NTP time synchronisation help

Postby zazas321 » Mon Jan 03, 2022 9:08 am

Hello. In my project, I need to save some data in the external flash memory. The data must contain a 4 byte timestamp so I know when certain events happened. I have never implemented anything regarding NTP hence I am not 100% sure how it works. I have the following code (I took it from the esp idf examples just simplified it) :

Code: Select all


static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
    sntp_init();
}


static void obtain_time(void)
{

    wifi_init_sta();
    initialize_sntp();

    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 10;
    while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
    time(&now);
    localtime_r(&now, &timeinfo);

    ESP_LOGI("WIFI", "WiFi closing down..");
	ESP_ERROR_CHECK( esp_wifi_disconnect());
	vTaskDelay(100 / portTICK_RATE_MS);
	ESP_ERROR_CHECK( esp_wifi_stop());
	vTaskDelay(100 / portTICK_RATE_MS);
	ESP_ERROR_CHECK( esp_wifi_deinit());
	vTaskDelay(100 / portTICK_RATE_MS);
}
In my main.c I call:

Code: Select all

void app_main(void)
{
    
    esp_err_t ret;
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
    // Is time set? If not, tm_year will be (1970 - 1900).
    if (timeinfo.tm_year < (2016 - 1900)) {
        ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
        obtain_time();
        // update 'now' variable with current time
        time(&now);
    }
    char strftime_buf[64];
    setenv("TZ", "EET-2EEST,M3.5.0/3,M10.5.0/4", 1); // time in Riga/Lithuania
    tzset();
    localtime_r(&now, &timeinfo);
    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint32_t time_sec = (uint32_t)tv_now.tv_sec;
    printf("time sec = %u \n",time_sec);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in Riga is: %s", strftime_buf);
}
And then after the setup, every 1 hour, I save some data to flash memory, so I just call gettimeofday function to get the latest timestamp:

Code: Select all

                    struct timeval tv_now;
                    gettimeofday(&tv_now, NULL);
                    uint32_t time_sec = (uint32_t)tv_now.tv_sec;
                    timestamp_for_logging = time_sec; // take timestamp here
 

This seems to be working, however, I would like to understand how the time is syncrhonised? From what I understand, the time will slowly drift and at some point it will need to be resynchronised. How does this happen? Does it happen automatically or does it get synchronised whenever I call gettimeofday(&tv_now, NULL);? If it does not happen automatically, do I need to implement something to make sure my device connects to the wifi and resynchronise the time and disconnects the same way it happens during the setup?

From what I have found, I need to update ntp myself. For example, I can have a freertos task that is responsible for synchronising the ntp time. Would below work to synchronise and update the ntp timestamp? Do I need to establish wifi connection before doing that?

Code: Select all

static void update_ntp(void* pvParameters) {
  while (true) {
    printf("synchronising time \n");
    sntp_stop();
    sntp_init();
    vTaskDelay(60000 / portTICK_RATE_MS);
  }
}

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: NTP time synchronisation help

Postby ESP_Sprite » Tue Jan 04, 2022 1:06 am

The ESP-IDF SNTP implementation uses the LWIP SNTP function calls. From what I can tell, those automatically will poll the time every so often (each hour by default, configurable with menuconfig: LWIP_SNTP_UPDATE_DELAY) and that will keep the gettimeofday() and friends result in sync. There's no need to manually stop/reinit to get a sync going.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: NTP time synchronisation help

Postby zazas321 » Tue Jan 04, 2022 6:57 am

Thank you very much for the answer. In that case, do I must ensure that I always have the wifi connection active so the time can be synchronised? (I assumed synchronisation requires network connection) ?

ESP_Sprite
Posts: 9746
Joined: Thu Nov 26, 2015 4:08 am

Re: NTP time synchronisation help

Postby ESP_Sprite » Tue Jan 04, 2022 7:18 am

Yes, syncing requires a network connection.

Who is online

Users browsing this forum: Google [Bot] and 77 guests