首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ESP32上的警报

ESP32上的警报
EN

Stack Overflow用户
提问于 2019-06-03 01:23:35
回答 2查看 2.2K关注 0票数 1

我正在使用连接到Google Core的IoT控制灯,以树莓皮为中心,通过IoT核心向ESP32发送消息,在一天中指定的时间打开或关闭它们。

我现在想做的是消除树莓皮,让esp32管理当它需要打开或关闭他们,但我看不到找到一种方式设置警报或类似的警报触发在特定的时间。

输入的时间值以毫秒为单位,从协调时算起。

这样的事情是否存在,或者我如何在esp32上完成警报?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-04 19:25:07

我不知道您是在为ESP32使用ESP还是某种Arduino框架(我对此并不熟悉)。这是ESP以色列国防军的答复。如果您没有使用ESP-国防军,并且无法访问相关的头文件和库,那么其中的一些想法可能仍然是相关的。

激活SNTP

通过在https://github.com/espressif/esp-idf/tree/master/examples/protocols/sntp上遵循SNTP示例,确保控制器上的时钟被更新。

使用localtime()

如果您正在使用ESP,您将可以访问localtime_r()函数。传递这个(指向)‘自时代开始’的秒数(由time(NULL)返回),它将用一周、一天、一小时、一分钟和第二天填充一个struct tm

一般程序是(错误处理).

代码语言:javascript
复制
#include <time.h>
// ...

struct tm now = {};
time_t tnow = time(NULL);
localtime_r(&tnow, &now);
// Compare current day, hour, minute, etc. against pre-defined alarms.

注意:如果您喜欢使用UTC,可以使用gmtime_r()而不是localtime_r()

您可以从主while()循环中周期性地调用它,如下所示。

报警结构

为您的警报信息定义结构。您可以根据需要的粒度级别进行以下调整。请注意,它包括一个callback成员-指定程序在触发警报时实际应该做什么。

代码语言:javascript
复制
typedef struct {
    int week_day;  // -1 for every day of week
    int hour;      // -1 for every hour
    int minute;    // -1 for every minute
    void (*callback)(void);
    void *callback_arg;
} alarm_t;

定义警报和回调

定义警报、回调函数和参数数组。

代码语言:javascript
复制
static void trigger_relay(const void *arg) {
    uint32_t num = *(uint32_t *)arg;
    printf("Activating relay %u ...\n", num);
    // Handle GPIO etc.
}

static uint32_t relay_1 = 0;
static uint32_t relay_2 = 1;

static alarm_t alarms[] = {
    // Trigger relay 1 at 9:00 on Sunday
    {0, 9, 0, trigger_relay, (void *)&relay_1},
    // Relay 2 at 7:30 every day
    {-1, 7, 30, trigger_relay, (void *)&relay_2},
};

周期扫描

定义一个check_alarms()例程,它用当前时间加载一个struct tm结构,并将其与您定义的每个警报进行比较。如果当前时间与警报时间匹配,则调用回调。

代码语言:javascript
复制
static void check_alarms(void) {
    time_t tnow = time(NULL);
    struct tm now = {};
    localtime_r(&tnow, &now);
    ESP_LOGI(TAG, "Time: %u:%u:%u", now.tm_hour, now.tm_min, now.tm_sec);
    size_t n_alarms = sizeof(alarms) / sizeof(alarms[0]);
    for (int i = 0; i < n_alarms; i++) {
        alarm_t *alrm = &alarms[i];
        if (alrm->week_day != -1 && alrm->week_day != now.tm_wday) {
            continue;
        }
        if (alrm->hour != -1 && alrm->hour != now.tm_hour) {
            continue;
        }
        if (alrm->minute != -1 && alrm->minute != now.tm_min) {
            continue;
        }
        alrm->callback(alrm->callback_arg);
    }
}

然后从主while()循环中调用它,频率取决于警报的粒度。由于上面定义的alarm_t粒度为1分钟,所以我将每隔一次调用check_alarms()。此示例适用于FreeRTOS,但可以根据需要进行调整。

代码语言:javascript
复制
while (1) {
   TickType_t tick = xTaskGetTickCount();
   if (tick - g_time_last_check > pdMS_TO_TICKS(60000)) {
       g_time_last_check = tick;
       check_alarms();
   }
}

效率

如果您有大量的警报和/或每一个警报应该在高频触发,上面的效率不是很高。在这种情况下,您可能会考虑根据等待时间对警报进行排序的算法,而不是每次迭代整个数组,而是使用一个一次性软件计时器来调用相关的回调。除非你有大量的计时器,否则这可能不值得麻烦。

备选方案

FreeRTOS和ESP-以色列国防军都包含软件定时器的APIs -但这些API不能(很容易)在一天中的特定时间被用于警报--这是您所要求的。另一方面--正如你可能已经知道的--芯片上的ESP32系统确实有内置的RTC,但我认为最好使用更高级别的接口,而不是直接与它通信。

票数 4
EN

Stack Overflow用户

发布于 2019-06-04 17:24:02

实时时钟是你要找的东西。我从未与ESP32合作过,但显然是它有一个,它是坏的。。但是,5%的错误可能对您来说足够好。如果这是一种选择,我会使用外部的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56420174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档