tdse-tf_3-02

Controlador PID para derretidor de miel con control local via botones y remoto via WiFi
Index Commits Files Refs Submodules README
commit 05af93cdfbf239496a3d5adc4c95d183abb3a92c
parent e62f6defe36046fac0f527cf1f1b6a425a6e6f33
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Wed,  1 Apr 2026 14:39:00 -0300

Agregar lógica y menus para programar encendido/apagado automático

Diffstat:
Mfirmware/app/inc/app.h | 11+++++++++--
Mfirmware/app/inc/task_system_attribute.h | 3+++
Mfirmware/app/src/app.c | 1+
Mfirmware/app/src/task_menu.c | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mfirmware/app/src/task_system.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
5 files changed, 251 insertions(+), 10 deletions(-)
diff --git a/firmware/app/inc/app.h b/firmware/app/inc/app.h
@@ -19,10 +19,17 @@ extern uint32_t g_app_WCET_us;
 extern volatile uint32_t g_app_tick_cnt;
 
 typedef struct {
+    uint8_t start_hour, start_min;
+    uint8_t end_hour, end_min;
+    bool enabled;
+} task_system_timer_t;
+
+typedef struct {
     int16_t temp_set_point;   // Desired temp
-    int16_t temp_sensor;       // Actual temp
-    uint8_t temp_ctrl_pwm_dc;  // Duty cycle of output [0, 100]
+    int16_t temp_sensor;      // Actual temp
+    uint8_t temp_ctrl_pwm_dc; // Duty cycle of output [0, 100]
     bool temp_ctrl_enabled;
+    task_system_timer_t *timer;
 } shared_data_type;
 
 extern void app_init(void);
diff --git a/firmware/app/inc/task_system_attribute.h b/firmware/app/inc/task_system_attribute.h
@@ -42,6 +42,9 @@ typedef enum task_system_st {
     ST_SYS_IDLE,
     ST_SYS_CLOCK_SET,
     ST_SYS_TEMP_SET,
+    ST_SYS_TIMER_SET_STATUS,
+    ST_SYS_TIMER_SET_START,
+    ST_SYS_TIMER_SET_END,
 } task_system_st_t;
 
 typedef struct {
diff --git a/firmware/app/src/app.c b/firmware/app/src/app.c
@@ -71,6 +71,7 @@ void app_init(void)
     p_shared_data->temp_sensor = -20;
     p_shared_data->temp_ctrl_pwm_dc = 0;
     p_shared_data->temp_ctrl_enabled = false;
+    p_shared_data->timer = NULL;
 
     for (uint32_t index = 0; TASK_QTY > index; index++)
     {
diff --git a/firmware/app/src/task_menu.c b/firmware/app/src/task_menu.c
@@ -60,7 +60,7 @@ void task_menu_init(void *parameters)
 
     display_i2c_init();
     display_i2c_set_cursor_pos(0, 0);
-    display_i2c_write_string("Inicializando...");
+    display_i2c_write_string("Initializing...");
     g_display_update = true;
 
     LOGGER_INFO("Done initializing `task_menu`");
@@ -167,6 +167,18 @@ void task_menu_statechart(void *parameters)
                 menu_set_state(ST_MEN_TEMP_SET);
             break;
 
+            case EV_MEN_ST_TIMER_SET_STATUS:
+                menu_set_state(ST_MEN_TIMER_SET_STATUS);
+            break;
+
+            case EV_MEN_ST_TIMER_SET_START:
+                menu_set_state(ST_MEN_TIMER_SET_START);
+            break;
+
+            case EV_MEN_ST_TIMER_SET_END:
+                menu_set_state(ST_MEN_TIMER_SET_END);
+            break;
+
             default: break;
         }
     }
@@ -265,6 +277,66 @@ void task_menu_statechart(void *parameters)
 
         break;
 
+        case ST_MEN_TIMER_SET_STATUS:
+
+            if (g_display_update)
+            {
+                g_display_update = false;
+                display_i2c_async_clear();
+                display_i2c_async_write_string("Timer>");
+                display_i2c_async_set_cursor_pos(8, 0);
+                memset(menu_row_str, '\0', sizeof(menu_row_str));
+                sprintf(menu_row_str, "%8s", 
+                        p_shared_data->timer->enabled ? "enabled" : "disabled");
+                display_i2c_async_write_string(menu_row_str);
+
+                display_i2c_async_set_cursor_pos(3, 1);
+                memset(menu_row_str, '\0', sizeof(menu_row_str));
+                sprintf(menu_row_str, "%s%2d:%02d - %d:%02d",
+                        (p_shared_data->timer->end_hour >= 10) ? "" : " ",
+                        p_shared_data->timer->start_hour,
+                        p_shared_data->timer->start_min,
+                        p_shared_data->timer->end_hour,
+                        p_shared_data->timer->end_min);
+                display_i2c_async_write_string(menu_row_str);
+            }
+
+        break;
+
+        case ST_MEN_TIMER_SET_START:
+
+            if (g_display_update)
+            {
+                g_display_update = false;
+                display_i2c_async_clear();
+                display_i2c_async_write_string("Timer>start>");
+                display_i2c_async_set_cursor_pos(11, 1);
+                memset(menu_row_str, '\0', sizeof(menu_row_str));
+                sprintf(menu_row_str, "%2d:%02d",
+                        p_shared_data->timer->start_hour,
+                        p_shared_data->timer->start_min);
+                display_i2c_async_write_string(menu_row_str);
+            }
+
+        break;
+
+        case ST_MEN_TIMER_SET_END:
+
+            if (g_display_update)
+            {
+                g_display_update = false;
+                display_i2c_async_clear();
+                display_i2c_async_write_string("Timer>end>");
+                display_i2c_async_set_cursor_pos(11, 1);
+                memset(menu_row_str, '\0', sizeof(menu_row_str));
+                sprintf(menu_row_str, "%2d:%02d",
+                        p_shared_data->timer->end_hour,
+                        p_shared_data->timer->end_min);
+                display_i2c_async_write_string(menu_row_str);
+            }
+
+        break;
+
         default:
 
             p_task_menu_dta->tick  = G_TASK_MEN_TICK_INI;
diff --git a/firmware/app/src/task_system.c b/firmware/app/src/task_system.c
@@ -28,6 +28,14 @@
 #define DEL_SYS_MIN 0ul
 #define DEL_SYS_MED 50ul
 #define DEL_SYS_MAX 500ul
+#define G_TASK_SYSTEM_TICK_UPDATE_RATE_MS 1000ul
+
+//  If persistent values are lost these are the timer default values
+#define TIMER_DEFAULT_START_HOUR 0000
+#define TIMER_DEFAULT_START_MIN  0000
+#define TIMER_DEFAULT_END_HOUR   0000
+#define TIMER_DEFAULT_END_MIN    0000
+#define TIMER_DEFAULT_STATUS     false
 
 task_system_dta_t task_system_dta = {
     DEL_SYS_MIN, ST_SYS_IDLE, EV_SYS_IDLE, false
@@ -35,12 +43,21 @@ task_system_dta_t task_system_dta = {
 
 #define SYSTEM_DTA_QTY (sizeof(task_system_dta)/sizeof(task_system_dta_t))
 
+// Private variables
+static task_system_timer_t task_system_timer = {
+    TIMER_DEFAULT_START_HOUR, TIMER_DEFAULT_START_MIN,
+    TIMER_DEFAULT_END_HOUR, TIMER_DEFAULT_END_MIN,
+    TIMER_DEFAULT_STATUS
+};
+
+uint32_t g_task_system_timer_tick;
+
 // Exported variables
-volatile uint32_t g_task_system_tick;
 volatile uint32_t g_task_system_tick_cnt; // Updated every ms by SysTick callback
 
 // Private function declaration
 void task_system_statechart(void *parameters);
+void task_system_timer_update(void *parameters);
 void task_system_rtc_init(void);
 void task_system_rtc_increment_hour(void);
 void task_system_rtc_increment_min(void);
@@ -56,7 +73,8 @@ void task_system_init(void *parameters)
 
     LOGGER_INFO("Initializing `task_system`...");
 
-    g_task_system_tick = G_TASK_SYS_CNT_INI;
+    g_task_system_tick_cnt = G_TASK_SYS_TICK_CNT_INI;
+    g_task_system_timer_tick = G_TASK_SYS_CNT_INI;
 
     task_system_interface_init_event_queue();
     task_system_rtc_init();
@@ -67,6 +85,9 @@ void task_system_init(void *parameters)
     state = ST_SYS_IDLE;
     p_task_system_dta->state = state;
 
+    shared_data_type *p_shared_data = (shared_data_type *)parameters;
+    p_shared_data->timer = &task_system_timer;
+
     LOGGER_INFO("Done initializing `task_system`");
 }
 
@@ -84,8 +105,15 @@ void task_system_update(void *parameters)
 
     while (b_time_update_required)
     {
-        g_task_system_tick++;
-
+        if (0 == g_task_system_timer_tick)
+        {
+            g_task_system_timer_tick = G_TASK_SYSTEM_TICK_UPDATE_RATE_MS;
+            task_system_timer_update(parameters);
+        }
+        else
+        {
+            g_task_system_timer_tick--;
+        }
         task_system_statechart(parameters);
 
         __asm("CPSID i");
@@ -307,8 +335,8 @@ void task_system_statechart(void *parameters)
                 {
                     case EV_SYS_BTN_A_ACTIVE:
                     case EV_SYS_BTN_D_ACTIVE:
-                        p_task_system_dta->state = ST_SYS_IDLE;
-                        task_menu_interface_put_event(EV_MEN_ST_IDLE);
+                        p_task_system_dta->state = ST_SYS_TIMER_SET_STATUS;
+                        task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_STATUS);
                         task_system_eeprom_write_param(parameters);
                     break;
 
@@ -330,11 +358,141 @@ void task_system_statechart(void *parameters)
             }
         break;
 
-        default: 
+        case ST_SYS_TIMER_SET_STATUS:
             if (true == p_task_system_dta->event_flag)
             {
                 p_task_system_dta->event_flag = false;
+                switch (p_task_system_dta->event)
+                {
+
+                    case EV_SYS_BTN_C_ACTIVE:
+                        p_shared_data->timer->enabled = !p_shared_data->timer->enabled;
+                        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+                    break;
+
+                    case EV_SYS_BTN_A_ACTIVE:
+                    case EV_SYS_BTN_B_ACTIVE:
+                        p_task_system_dta->state = ST_SYS_IDLE;
+                        task_menu_interface_put_event(EV_MEN_ST_IDLE);
+                        break;
+
+                    case EV_SYS_BTN_D_ACTIVE:
+                        p_task_system_dta->state = ST_SYS_TIMER_SET_START;
+                        task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_START);
+                    break;
+
+                    default: break;
+                }
             }
         break;
+
+        case ST_SYS_TIMER_SET_START:
+            if (true == p_task_system_dta->event_flag)
+            {
+                p_task_system_dta->event_flag = false;
+                switch (p_task_system_dta->event)
+                {
+                    case EV_SYS_BTN_B_ACTIVE:
+                        p_shared_data->timer->start_hour =
+                            ((p_shared_data->timer->start_hour + 1) % 24);
+                        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+                    break;
+
+                    case EV_SYS_BTN_C_ACTIVE:
+                        p_shared_data->timer->start_min =
+                            ((p_shared_data->timer->start_min + 1) % 60);
+                        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+                    break;
+
+                    case EV_SYS_BTN_A_ACTIVE:
+                    case EV_SYS_BTN_D_ACTIVE:
+                        p_task_system_dta->state = ST_SYS_TIMER_SET_END;
+                        task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_END);
+                    break;
+
+                    default: break;
+                }
+            }
+        break;
+
+        case ST_SYS_TIMER_SET_END:
+            if (true == p_task_system_dta->event_flag)
+            {
+                p_task_system_dta->event_flag = false;
+                switch (p_task_system_dta->event)
+                {
+                    case EV_SYS_BTN_B_ACTIVE:
+                        p_shared_data->timer->end_hour =
+                            ((p_shared_data->timer->end_hour + 1) % 24);
+                        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+                    break;
+
+                    case EV_SYS_BTN_C_ACTIVE:
+                        p_shared_data->timer->end_min =
+                            ((p_shared_data->timer->end_min + 1) % 60);
+                        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+                    break;
+
+                    case EV_SYS_BTN_A_ACTIVE:
+                    case EV_SYS_BTN_D_ACTIVE:
+                        p_task_system_dta->state = ST_SYS_IDLE;
+                        task_menu_interface_put_event(EV_MEN_ST_IDLE);
+                    break;
+
+                    default: break;
+                }
+            }
+        break;
+
+        default: 
+            p_task_system_dta->state = ST_SYS_IDLE;
+            p_task_system_dta->event_flag = false;
+            p_shared_data->temp_ctrl_enabled = false;
+            task_menu_interface_put_event(EV_MEN_ST_IDLE);
+            task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_A);
+            task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_B);
+        break;
+    }
+}
+
+// TOOD: Only check timer conditions every second (not on every tick)
+void task_system_timer_update(void *parameters)
+{
+    shared_data_type *p_shared_data = (shared_data_type *)parameters;
+    uint16_t start_24, end_24, clock_24;
+    bool new_temp_ctrl_state;
+
+    if (false == p_shared_data->timer->enabled)
+    {
+        return;
+    }
+
+    HAL_RTC_GetTime(&hrtc, &s_time, RTC_FORMAT_BIN);
+
+    clock_24 = (s_time.Hours*100) + s_time.Minutes;
+    start_24 = (p_shared_data->timer->start_hour*100) + p_shared_data->timer->start_min;
+    end_24   = (p_shared_data->timer->end_hour*100) + p_shared_data->timer->end_min;
+
+    new_temp_ctrl_state = ((end_24 > start_24)
+                ? ((clock_24 >= start_24) && (clock_24 < end_24))
+                : ((clock_24 >= start_24) || (clock_24 < end_24)));
+
+    if (new_temp_ctrl_state != p_shared_data->temp_ctrl_enabled)
+    {
+        p_shared_data->temp_ctrl_enabled = new_temp_ctrl_state;
+
+        task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+        task_buzzer_interface_put_event(EV_BUZ_XX_LONG_BEEP, ID_BUZ_A);
+
+        if (true == p_shared_data->temp_ctrl_enabled)
+        {
+            task_leds_interface_put_event(EV_LED_XX_BLINK, ID_LED_A);
+            task_leds_interface_put_event(EV_LED_XX_BLINK, ID_LED_B);
+        }
+        else
+        {
+            task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_A);
+            task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_B);
+        }
     }
 }