[经验分享] 【建筑施工监测与安防系统】十、Kaluga网络授时和定时器

sonicfirr   2022-9-21 22:59 楼主

          依靠ESP32 IDF提供的SNTP案例(..\esp-idf-v4.4\examples\protocols\sntp)和定时器案例(..\esp-idf-v4.4\examples\system\esp_timer),本人继续进行参赛项目的功能开发,使得Kaluga板在启动并联网后获取网络时间,之后启动s级定时器——为了后续进行周期性监测作准备。依然是单独创建time.c源文件,时间相关代码编写于此。

 

#include "main.h"


/* Private macro -------------------------------------------------- */
#define TAG                                "AITA TIME"
#define CONFIG_SNTP_TIME_SYNC_METHOD_IMMED 1
#define AITA_SNTP_MAX_RETRY_TIMES          10


// SNTP related --------------------------------------------------- //
/* Private functions ---------------------------------------------- */
/*********************************************************************
 * FunctionName : sntp_notification_cb()
 * Description  : time synchronization callback
 * Parameters   : struct timeval *tv ——> epoch time struct pointer
 * Returns      : void
*********************************************************************/
void sntp_notification_cb(struct timeval *tv) {
    ESP_LOGI(TAG, "Epoch sec: %d, usec: %d", 
                (int)tv->tv_sec, (int)tv->tv_usec);
}
/*********************************************************************
 * FunctionName : initialize_sntp()
 * Description  : initialize sntp & synchronize system time
 * Parameters   : void
 * Returns      : void
*********************************************************************/
void initialize_sntp(void) {
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
// 0 - server number, "pool.ntp.org" - server url
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(sntp_notification_cb);
    sntp_init();
}
/*********************************************************************
 * FunctionName : obtain_time()
 * Description  : obtain system time
 * Parameters   : void
 * Returns      : void
*********************************************************************/
void obtain_time(void) {
    initialize_sntp();

// wait for time to be set
    int retry = 0;
    while(sntp_get_sync_status()==SNTP_SYNC_STATUS_RESET && 
                ++retry<AITA_SNTP_MAX_RETRY_TIMES) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", 
                    retry, AITA_SNTP_MAX_RETRY_TIMES);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}
/* Exported functions --------------------------------------------- */
/*********************************************************************
 * FunctionName : aita_PrintCST8()
 * Description  : print cst-8 timezone time
 * Parameters   : time_t *now ——> sytem local time
 * Returns      : void
*********************************************************************/
void aita_PrintCST8(time_t *now) {
    char buf[64];
    struct tm timeinfo;
// set timezone to China standard time
    setenv("TZ", "CST-8", 1);
    tzset();
    localtime_r(now, &timeinfo);
    strftime(buf, sizeof(buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "current date/time in Shanghai: %s", buf);
}
/*********************************************************************
 * FunctionName : aita_InitSNTP()
 * Description  : sntp & print cst-8 timezone time
 * Parameters   : void
 * Returns      : void
*********************************************************************/
void aita_InitSNTP(void) {
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);

// If time is not set, tm_year will be (1970 - 1900).
    if(timeinfo.tm_year < (2016-1900)) {
        ESP_LOGI(TAG, "time is not set yet.");
        ESP_LOGI(TAG, "getting time over NTP.");
        obtain_time();
    // update 'now' variable with current time
        time(&now);
    }
// print China timezone time
    aita_PrintCST8(&now);
}


// timer related -------------------------------------------------- //
/* Private functions ---------------------------------------------- */
/*********************************************************************
 * FunctionName : periodic_timer_callback()
 * Description  : periodic timer callback function
 * Parameters   : void* arg ——> callback's argument
 * Returns      : void
*********************************************************************/
static void periodic_timer_callback(void* arg) {
    int64_t time_since_boot = esp_timer_get_time();
    ESP_LOGI(TAG, "periodic timer called, time since boot: %lld us", 
                    time_since_boot);
    aita_InitSNTP();
}
/* Exported functions --------------------------------------------- */
/*********************************************************************
 * FunctionName : aita_InitTimer()
 * Description  : initialize timer
 * Parameters   : void
 * Returns      : void
*********************************************************************/
void aita_InitTimer(void) {
    const esp_timer_create_args_t periodic_timer_args = {
            .callback = &periodic_timer_callback,
            .name = "periodic"
    };

    esp_timer_handle_t periodic_timer;
    ESP_ERROR_CHECK(
        esp_timer_create(&periodic_timer_args, &periodic_timer)
    );
    
    /* Start the timers */
    ESP_ERROR_CHECK(
        esp_timer_start_periodic(periodic_timer, 1000000)
    );
    ESP_LOGI(TAG, "started timers, time since boot: %lld us", 
                    esp_timer_get_time());
}


/*********** (C) COPYRIGHT AITA TCU ********** END OF FILE **********/

 

          项目入口app_main()中调用aita_InitSNTP()得到网络授时,调用aita_InitTimer()开启1s的周期性定时器。

 

image-20220921225821-1.png

 

image-20220921225821-2.png

图10-1 SNTP和定时器功能测试输出

回复评论 (2)

网络授时,调用aita_InitTimer()开启1s的周期性定时器这里应该没问题吧

点赞  2022-9-22 07:20
引用: Jacktang 发表于 2022-9-22 07:20 网络授时,调用aita_InitTimer()开启1s的周期性定时器这里应该没问题吧

测试没问题,因为我的项目后面功能需要定时采集,还考虑记录本地log,发送心跳包等功能,需要有准确的时间,所以考虑先做授时,再开启定时器。

实际授时使用RTC,Timer使用通用定时器,互补影响的吧。

点赞  2022-9-22 09:09
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复