Alarms on an ESP32

Internet of Things IoT Frameworks 2 years ago

0 1 0 0 0 tuteeHUB earn credit +10 pts

5 Star Rating 1 Rating
_x000D_ _x000D_ I am using an ESP32 connected to Google Cloud IoT Core to control lights with a raspberry pi as a hub to send messages to the esp32 through IoT core to turn them on and off at set times of the day. What I want to do now is just eliminate the raspberry pi and have the esp32 manage when it needs to turn them on or off but I cant see to find a way to set alarms or something like alarms that trigger at specific times of days. The time value coming in is in milliseconds from UTC Does something like that exists or how could I accomplish alarms on the esp32?

Posted on 16 Aug 2022, this text provides information on IoT Frameworks related to Internet of Things. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Take Quiz To Earn Credits!

Turn Your Knowledge into Earnings.

tuteehub_quiz

Answers (1)

Post Answer
profilepic.png
manpreet Tuteehub forum best answer Best Answer 2 years ago
_x000D_ I don't know if you are using the ESP IDF or some sort of Arduino framework for the ESP32 (with which I am not familiar). This answer is for the ESP IDF. If you are not using the ESP-IDF and don't have access to the relevant header files and libraries, some of the ideas might still be relevant. Activate SNTP Ensure that the clock on the controller is updated by following the SNTP example at https://github.com/espressif/esp-idf/tree/master/examples/protocols/sntp . Use localtime() If you are using the ESP-IDF you will have access to the localtime_r() function. Pass this (a pointer to) the number of 'seconds since the Epoch' - as returned by time(NULL) - and it will fill a struct tm with the day of the week, day of the month, hour, minute and second. The general procedure is (error handling ommitted) ... #include // ... struct tm now = {}; time_t tnow = time(NULL); localtime_r(&tnow, &now); // Compare current day, hour, minute, etc. against pre-defined alarms. Note: You can use gmtime_r() instead of localtime_r() if you prefer to use UTC. You can invoke this periodically from your main while() loop as outlined below. Alarm structures Define a structure for your alarm information. You could use something like the following - tweaking according to the level of granularity you need. Note that it includes a callback member - to specify what the program should actually do when the alarm is triggered. 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; Define alarms and callbacks Define your array of alarms, callback functions and arguments. 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}, }; Periodic scan Define a check_alarms() routine which loads a struct tm structure with the current time and compares this with each of the alarms you have defined. If the current time matches that of the alarm, the callback is invoked. 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); } } This would then be called from your main while() loop with a frequency depending on the granularity of your alarm. Since the alarm_t defined above has a granularity of 1 minute, that is how often I will call check_alarms(). This example is for FreeRTOS but could be adapted as needs be. while (1) { TickType_t tick = xTaskGetTickCount(); if (tick - g_time_last_check > pdMS_TO_TICKS(60000)) { g_time_last_check = tick; check_alarms(); } } Efficiency The above is not very efficient if you have a lot of alarms and / or each alarm should be triggered at high frequency. In such a case, you might consider algorithms which sort the alarms based on time until elapsed, and - instead of iterating over the entire array every time - instead employ a one-shot software timer to invoke the relevant callback. It probably isn't the worth the hassle unless you have a very large number of timers though. Alternatives Both FreeRTOS and the ESP-IDF include APIs for software timers - but these can not be (easily) used for alarms at a specific time of the day - which you state as a requirement. On the other hand - as you may already know - the ESP32 system-on-a-chip does have a built-in RTC, but I think it is best to use a higher-level interface than communicating with it directly.

No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.

Important Internet of Things Links