Add run limit feature for relay channels with NVS support
- Introduced configuration options for enabling run limits in Kconfig. - Added APIs to get and set run limits for individual relay channels. - Implemented run limit timer functionality to automatically stop channels. - Updated NVS handling to store and retrieve run limit values. - Enhanced documentation in README and code comments to reflect new feature. Closes #1080
This commit is contained in:
@@ -46,6 +46,30 @@ esp_event_loop_handle_t relay_chn_event_loop = NULL;
|
||||
static void relay_chn_event_handler(void* handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
|
||||
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
/*
|
||||
* Run limit timer callback immediately dispatches a STOP command for the
|
||||
* relevant channel as soon as the run limit time times out
|
||||
*/
|
||||
static void relay_chn_run_limit_timer_cb(void* arg)
|
||||
{
|
||||
relay_chn_ctl_t* chn_ctl = (relay_chn_ctl_t*) arg;
|
||||
relay_chn_dispatch_cmd(chn_ctl, RELAY_CHN_CMD_STOP);
|
||||
}
|
||||
|
||||
esp_err_t relay_chn_init_run_limit_timer(relay_chn_ctl_t *chn_ctl)
|
||||
{
|
||||
char timer_name[32];
|
||||
snprintf(timer_name, sizeof(timer_name), "ch_%d_rlimit_timer", chn_ctl->id);
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = relay_chn_run_limit_timer_cb,
|
||||
.arg = chn_ctl,
|
||||
.name = timer_name
|
||||
};
|
||||
return esp_timer_create(&timer_args, &chn_ctl->run_limit_timer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Timer callback function for relay channel direction change inertia.
|
||||
static void relay_chn_timer_cb(void* arg)
|
||||
{
|
||||
@@ -467,6 +491,10 @@ static void relay_chn_execute_stop(relay_chn_ctl_t *chn_ctl)
|
||||
// Invalidate the channel's timer if it is active
|
||||
esp_timer_stop(chn_ctl->inertia_timer);
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
esp_timer_stop(chn_ctl->run_limit_timer);
|
||||
#endif
|
||||
|
||||
// Save the last run time only if the previous state was either STATE FORWARD
|
||||
// or STATE_REVERSE. Then schedule a free command.
|
||||
if (previous_state == RELAY_CHN_STATE_FORWARD || previous_state == RELAY_CHN_STATE_REVERSE) {
|
||||
@@ -489,6 +517,10 @@ static void relay_chn_execute_forward(relay_chn_ctl_t *chn_ctl)
|
||||
}
|
||||
relay_chn_run_info_set_last_run_cmd(chn_ctl->run_info, RELAY_CHN_CMD_FORWARD);
|
||||
relay_chn_update_state(chn_ctl, RELAY_CHN_STATE_FORWARD);
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
relay_chn_start_esp_timer_once(chn_ctl->run_limit_timer, chn_ctl->run_limit_sec * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void relay_chn_execute_reverse(relay_chn_ctl_t *chn_ctl)
|
||||
@@ -499,6 +531,10 @@ static void relay_chn_execute_reverse(relay_chn_ctl_t *chn_ctl)
|
||||
}
|
||||
relay_chn_run_info_set_last_run_cmd(chn_ctl->run_info, RELAY_CHN_CMD_REVERSE);
|
||||
relay_chn_update_state(chn_ctl, RELAY_CHN_STATE_REVERSE);
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
relay_chn_start_esp_timer_once(chn_ctl->run_limit_timer, chn_ctl->run_limit_sec * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void relay_chn_execute_flip(relay_chn_ctl_t *chn_ctl)
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "relay_chn_ctl.h"
|
||||
#include "relay_chn_output.h"
|
||||
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
#include "relay_chn_nvs.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "RELAY_CHN_CTL";
|
||||
|
||||
static relay_chn_ctl_t chn_ctls[RELAY_CHN_COUNT];
|
||||
@@ -30,6 +34,19 @@ esp_err_t relay_chn_ctl_init(relay_chn_output_t *outputs, relay_chn_run_info_t *
|
||||
|
||||
chn_ctl->output = output;
|
||||
chn_ctl->run_info = run_info;
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
uint16_t run_limit_sec = RELAY_CHN_RUN_LIMIT_DEFAULT_SEC;
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
// Load run limit value from NVS
|
||||
ret = relay_chn_nvs_get_run_limit(chn_ctl->id, &run_limit_sec);
|
||||
if (ret != ESP_OK && ret != ESP_ERR_NVS_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to load run limit from NVS for channel %d with error: %s", i, esp_err_to_name(ret));
|
||||
}
|
||||
#endif
|
||||
chn_ctl->run_limit_sec = run_limit_sec;
|
||||
ret = relay_chn_init_run_limit_timer(chn_ctl);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to initialize run limit timer");
|
||||
#endif
|
||||
ret = relay_chn_init_timer(chn_ctl); // Create direction change inertia timer
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to create relay channel timer for channel %d", i);
|
||||
}
|
||||
@@ -44,6 +61,12 @@ void relay_chn_ctl_deinit()
|
||||
esp_timer_delete(chn_ctl->inertia_timer);
|
||||
chn_ctl->inertia_timer = NULL;
|
||||
}
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
if (chn_ctl->run_limit_timer != NULL) {
|
||||
esp_timer_delete(chn_ctl->run_limit_timer);
|
||||
chn_ctl->run_limit_timer = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +146,37 @@ relay_chn_direction_t relay_chn_ctl_get_direction(uint8_t chn_id)
|
||||
return relay_chn_output_get_direction(chn_ctl->output);
|
||||
}
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
uint16_t relay_chn_ctl_get_run_limit(uint8_t chn_id)
|
||||
{
|
||||
if (!relay_chn_is_channel_id_valid(chn_id) || chn_id == RELAY_CHN_ID_ALL) {
|
||||
ESP_LOGE(TAG, "get_run_limit: Invalid channel ID: %d", chn_id);
|
||||
return 0;
|
||||
}
|
||||
return chn_ctls[chn_id].run_limit_sec;
|
||||
}
|
||||
|
||||
void relay_chn_ctl_set_run_limit(uint8_t chn_id, uint16_t time_sec)
|
||||
{
|
||||
if (!relay_chn_is_channel_id_valid(chn_id) || chn_id == RELAY_CHN_ID_ALL) {
|
||||
ESP_LOGE(TAG, "set_run_limit: Invalid channel ID: %d", chn_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for boundaries
|
||||
if (time_sec > RELAY_CHN_RUN_LIMIT_MAX_SEC)
|
||||
time_sec = RELAY_CHN_RUN_LIMIT_MAX_SEC;
|
||||
else if (time_sec < RELAY_CHN_RUN_LIMIT_MIN_SEC)
|
||||
time_sec = RELAY_CHN_RUN_LIMIT_MIN_SEC;
|
||||
|
||||
chn_ctls[chn_id].run_limit_sec = time_sec;
|
||||
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
relay_chn_nvs_set_run_limit(chn_id, time_sec);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
relay_chn_ctl_t *relay_chn_ctl_get(uint8_t chn_id)
|
||||
{
|
||||
if (!relay_chn_is_channel_id_valid(chn_id)) {
|
||||
|
||||
@@ -4,11 +4,17 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "relay_chn_priv_types.h"
|
||||
#include "relay_chn_core.h"
|
||||
#include "relay_chn_ctl.h"
|
||||
#include "relay_chn_output.h"
|
||||
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
#include "relay_chn_nvs.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "RELAY_CHN_CTL";
|
||||
|
||||
static relay_chn_ctl_t chn_ctl;
|
||||
|
||||
@@ -21,6 +27,20 @@ esp_err_t relay_chn_ctl_init(relay_chn_output_t *output, relay_chn_run_info_t *r
|
||||
chn_ctl.pending_cmd = RELAY_CHN_CMD_NONE;
|
||||
chn_ctl.output = output;
|
||||
chn_ctl.run_info = run_info;
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
uint16_t run_limit_sec = RELAY_CHN_RUN_LIMIT_DEFAULT_SEC;
|
||||
esp_err_t ret;
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
// Load run limit value from NVS
|
||||
ret = relay_chn_nvs_get_run_limit(chn_ctl.id, &run_limit_sec);
|
||||
if (ret != ESP_OK && ret != ESP_ERR_NVS_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to load run limit from NVS with error: %s", esp_err_to_name(ret));
|
||||
}
|
||||
#endif
|
||||
chn_ctl.run_limit_sec = run_limit_sec;
|
||||
ret = relay_chn_init_run_limit_timer(&chn_ctl);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to initialize run limit timer");
|
||||
#endif
|
||||
return relay_chn_init_timer(&chn_ctl); // Create direction change inertia timer
|
||||
}
|
||||
|
||||
@@ -31,6 +51,12 @@ void relay_chn_ctl_deinit()
|
||||
esp_timer_delete(chn_ctl.inertia_timer);
|
||||
chn_ctl.inertia_timer = NULL;
|
||||
}
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
if (chn_ctl.run_limit_timer != NULL) {
|
||||
esp_timer_delete(chn_ctl.run_limit_timer);
|
||||
chn_ctl.run_limit_timer = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* relay_chn APIs */
|
||||
@@ -68,6 +94,28 @@ relay_chn_direction_t relay_chn_ctl_get_direction()
|
||||
{
|
||||
return relay_chn_output_get_direction(chn_ctl.output);
|
||||
}
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
uint16_t relay_chn_ctl_get_run_limit()
|
||||
{
|
||||
return chn_ctl.run_limit_sec;
|
||||
}
|
||||
|
||||
void relay_chn_ctl_set_run_limit(uint16_t time_sec)
|
||||
{
|
||||
// Check for boundaries
|
||||
if (time_sec > RELAY_CHN_RUN_LIMIT_MAX_SEC)
|
||||
time_sec = RELAY_CHN_RUN_LIMIT_MAX_SEC;
|
||||
else if (time_sec < RELAY_CHN_RUN_LIMIT_MIN_SEC)
|
||||
time_sec = RELAY_CHN_RUN_LIMIT_MIN_SEC;
|
||||
|
||||
chn_ctl.run_limit_sec = time_sec;
|
||||
|
||||
#if RELAY_CHN_ENABLE_NVS == 1
|
||||
relay_chn_nvs_set_run_limit(chn_ctl.id, time_sec);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* relay_chn APIs */
|
||||
|
||||
relay_chn_ctl_t *relay_chn_ctl_get()
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include "relay_chn_nvs.h"
|
||||
|
||||
#define RELAY_CHN_KEY_DIR "dir" /*!< Direction key */
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
#define RELAY_CHN_KEY_RLIM(ch) "rlim_%d" /*!< Run limit key */
|
||||
#endif
|
||||
#ifdef RELAY_CHN_ENABLE_TILTING
|
||||
#define RELAY_CHN_KEY_TSENS(ch) "tsens_%d" /*!< Tilt sensitivity key */
|
||||
#define RELAY_CHN_KEY_TCNT(ch) "tcnt_%d" /*!< Tilt count key */
|
||||
@@ -69,6 +72,22 @@ esp_err_t relay_chn_nvs_get_direction(uint8_t ch, relay_chn_direction_t *directi
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
esp_err_t relay_chn_nvs_set_run_limit(uint8_t ch, uint16_t time_sec)
|
||||
{
|
||||
esp_err_t ret = nvs_set_u16(relay_chn_nvs, RELAY_CHN_KEY_RLIM(ch), time_sec);
|
||||
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to set run limit for channel %d", ch);
|
||||
return nvs_commit(relay_chn_nvs);
|
||||
}
|
||||
|
||||
esp_err_t relay_chn_nvs_get_run_limit(uint8_t ch, uint16_t *time_sec)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(time_sec != NULL, ESP_ERR_INVALID_ARG, TAG, "Run limit value pointer is NULL");
|
||||
|
||||
return nvs_get_u16(relay_chn_nvs, RELAY_CHN_KEY_RLIM(ch), time_sec);
|
||||
}
|
||||
#endif // RELAY_CHN_ENABLE_RUN_LIMIT == 1
|
||||
|
||||
#ifdef RELAY_CHN_ENABLE_TILTING
|
||||
esp_err_t relay_chn_nvs_set_tilt_sensitivity(uint8_t ch, uint8_t sensitivity)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user