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 4193f449ffb23cb8dc3f6c82f7ff5f19dcd47516
parent 12a09fe9b6f23d50750ddfa9c70b586b1a18a40d
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Tue,  7 Apr 2026 16:59:04 -0300

Implementar controlador PID para el control de temperatura

Diffstat:
Mfirmware/app/src/task_temp_ctrl.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 52 insertions(+), 23 deletions(-)
diff --git a/firmware/app/src/task_temp_ctrl.c b/firmware/app/src/task_temp_ctrl.c
@@ -14,7 +14,12 @@
 #include "task_temp_ctrl.h"
 #include "logger.h"
 
-#define G_TASK_CTRL_TICK_CNT_INI  0ul
+#define G_TASK_TEMP_CTRL_TICK_CNT_INI  0ul
+
+#define G_TASK_TEMP_CTRL_PID_KP 40.0f
+#define G_TASK_TEMP_CTRL_PID_KI 0.75f
+#define G_TASK_TEMP_CTRL_PID_KD 0.01f
+#define G_TASK_TEMP_CTRL_PID_DT 250 // 100 ms
 
 // Private data definition
 typedef struct {
@@ -22,10 +27,20 @@ typedef struct {
     uint32_t tim_channel;
 } task_temp_ctrl_cfg_t;
 
+typedef struct {
+    float pid_kp, pid_ki, pid_kd;
+    float pid_p, pid_i, pid_d;
+    float error, prev_error;
+    uint32_t tick;
+} task_temp_ctrl_pid_t;
+
 static const task_temp_ctrl_cfg_t task_temp_ctrl_cfg = {&htim1, TIM_CHANNEL_1};
+static task_temp_ctrl_pid_t task_temp_ctrl_pid = {
+    G_TASK_TEMP_CTRL_PID_KP, G_TASK_TEMP_CTRL_PID_KI, G_TASK_TEMP_CTRL_PID_KD 
+};
 
 // Private functions declaration
-static inline int16_t ceil_i16(int16_t val, int16_t max_val);
+static inline int16_t clampf(float val, float min, float max);
 static void task_temp_ctrl_set_duty(TIM_HandleTypeDef *htim, uint32_t ch, uint8_t duty);
 
 // Public data definition
@@ -51,19 +66,15 @@ void task_temp_ctrl_init(void *parameters)
     LOGGER_INFO("Done initializing `task_temp_ctrl`");
 }
 
-static inline int16_t ceil_i16(int16_t val, int16_t max_val)
-{
-    return val > max_val ? max_val : val;
-}
-
 void task_temp_ctrl_update(void *parameters)
 {
     bool b_time_update_required;
     shared_data_type *p_shared_data = (shared_data_type *)parameters;
     const task_temp_ctrl_cfg_t *p_task_cfg = &task_temp_ctrl_cfg;
+    task_temp_ctrl_pid_t *p_pid = &task_temp_ctrl_pid;
 
     __asm("CPSID i");
-    if (G_TASK_CTRL_TICK_CNT_INI < g_task_temp_ctrl_tick_cnt)
+    if (G_TASK_TEMP_CTRL_TICK_CNT_INI < g_task_temp_ctrl_tick_cnt)
     {
         g_task_temp_ctrl_tick_cnt--;
         b_time_update_required = true;
@@ -73,7 +84,7 @@ void task_temp_ctrl_update(void *parameters)
     while (b_time_update_required)
     {
         __asm("CPSID i");
-        if (G_TASK_CTRL_TICK_CNT_INI < g_task_temp_ctrl_tick_cnt)
+        if (G_TASK_TEMP_CTRL_TICK_CNT_INI < g_task_temp_ctrl_tick_cnt)
         {
             g_task_temp_ctrl_tick_cnt--;
             b_time_update_required = true;
@@ -84,32 +95,50 @@ void task_temp_ctrl_update(void *parameters)
         }
         __asm("CPSIE i");
 
-        int16_t error = p_shared_data->temp_set_point - p_shared_data->temp_sensor;
-
-        if (error > 0)
+        if (false == p_shared_data->temp_ctrl_enabled)
         {
-            p_shared_data->temp_ctrl_pwm_dc = ceil_i16(error*error, 80);
-        }
-        else {
+            if (0 != __HAL_TIM_GET_COMPARE(p_task_cfg->htim, p_task_cfg->tim_channel))
+            {
                 task_temp_ctrl_set_duty(p_task_cfg->htim, p_task_cfg->tim_channel, 0);
+            }
         }
-
-        if (true == p_shared_data->temp_ctrl_enabled)
+        else
         {
-            if (p_shared_data->temp_ctrl_pwm_dc != TIM1->CCR1)
+            if (0 < p_pid->tick)
             {
+                p_pid->tick--;
+            }
+            else
+            {
+                p_pid->tick = G_TASK_TEMP_CTRL_PID_DT;
+                float dt = (p_pid->tick / 1000.0f);
+
+                p_pid->prev_error = p_pid->error;
+                p_pid->error = p_shared_data->temp_set_point - p_shared_data->temp_sensor;
+
+                p_pid->pid_p = p_pid->error * p_pid->pid_kp;
+                p_pid->pid_i = (p_pid->pid_i + (p_pid->error*dt)) * p_pid->pid_ki;
+                p_pid->pid_d = ((p_pid->error - p_pid->prev_error)/dt) * p_pid->pid_kd;
+
+                p_shared_data->temp_ctrl_pwm_dc = clampf(
+                        p_pid->pid_p + p_pid->pid_i + p_pid->pid_d,
+                        0.0f,
+                        100.0f);
+
                 task_temp_ctrl_set_duty(p_task_cfg->htim,
                         p_task_cfg->tim_channel,
                         p_shared_data->temp_ctrl_pwm_dc);
             }
         }
-        else
-        {
-            __HAL_TIM_SET_COMPARE(p_task_cfg->htim,
-                    p_task_cfg->tim_channel, 0);
-        }
     }
 }
+
+// Public functions declaration
+static inline int16_t clampf(float val, float min, float max)
+{
+    return (val > max) ? max : ((val < min) ? min : val);
+}
+
 static void task_temp_ctrl_set_duty(TIM_HandleTypeDef *htim, uint32_t ch, uint8_t duty)
 {
     uint32_t ARR = __HAL_TIM_GET_AUTORELOAD(htim);     // Auto Reload Reg