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
   1 /*
   2  * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
   3  * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
   4  *
   5  * See file `LICENSE` for full details
   6  */
   7 
   8 // TODO: *_interface libraries should already include *_attribute headers
   9 
  10 #include "main.h"
  11 
  12 #include "logger.h"
  13 #include "dwt.h"
  14 
  15 #include "app.h"
  16 #include "task_system.h"
  17 #include "task_buttons.h"
  18 #include "task_buzzer.h"
  19 #include "task_leds.h"
  20 #include "task_menu.h"
  21 #include "task_temp_ctrl.h"
  22 #include "task_temp_sensor.h"
  23 #include "task_remote.h"
  24 
  25 #define G_APP_CNT_INI           0ul
  26 #define G_APP_TICK_CNT_INI      0ul
  27 #define G_APP_WCET_INI          0ul
  28 #define G_APP_WCET_MEAN_SAMPLES 1000 // 1 second update rate
  29 
  30 #define TASK_X_WCET_INI            0ul
  31 #define TASK_X_WCET_SAMPLE_TIME_MS 10000ul
  32 #define TASK_X_TICK_INI            0ul
  33 #define TASK_X_DELAY_MIN           0ul
  34 
  35 typedef struct {
  36     void (*task_init)(void *);
  37     void (*task_update)(void *);
  38     void *parameters;
  39 } task_cfg_t;
  40 
  41 typedef struct {
  42     uint32_t WCET;          // Task worst-case execution time in microseconds
  43     uint32_t WCET_interval; // WCET in last `TASK_X_WCET_SAMPLE_TIME_MS` ms
  44 } task_dta_t;
  45 
  46 shared_data_type shared_data;
  47 uint32_t g_app_runtime_us;
  48 uint32_t g_app_runtime_us_mean;     // Mean of g_app_runtime_us in
  49                                     // G_APP_WCET_MEAN_SAMPLES
  50 uint32_t g_app_runtime_us_mean_aux;
  51 uint32_t g_app_runtime_us_mean_cnt;
  52 uint32_t g_app_WCET_us;             // Worst case execution time historically
  53 uint32_t g_app_WCET_sample_us;      // Worst case execution time in sample time
  54 volatile uint32_t g_app_tick_cnt;
  55 
  56 const task_cfg_t task_cfg_list[] = {
  57     {task_system_init,      task_system_update,      &shared_data},
  58     {task_buttons_init,     task_buttons_update,     NULL},
  59     {task_buzzer_init,      task_buzzer_update,      NULL},
  60     {task_leds_init,        task_leds_update,        NULL},
  61     {task_menu_init,        task_menu_update,        &shared_data},
  62     {task_temp_ctrl_init,   task_temp_ctrl_update,   &shared_data},
  63     {task_temp_sensor_init, task_temp_sensor_update, &shared_data},
  64     {task_remote_init,      task_remote_update,      &shared_data},
  65 };
  66 
  67 #define TASK_QTY (sizeof(task_cfg_list)/sizeof(task_cfg_t))
  68 
  69 task_dta_t task_dta_list[TASK_QTY] = {0};
  70 
  71 void app_init(void)
  72 {
  73     LOGGER_INFO("Initializing `app`...");
  74 
  75     cycle_counter_init();
  76 
  77     shared_data_type *p_shared_data = &shared_data;
  78 
  79     p_shared_data->temp_set_point    = 0;
  80     p_shared_data->temp_sensor       = -20;
  81     p_shared_data->temp_ctrl_pwm_dc  = 0;
  82     p_shared_data->temp_ctrl_enabled = false;
  83     p_shared_data->timer             = NULL;
  84 
  85     for (uint32_t index = 0; TASK_QTY > index; index++)
  86     {
  87         (*task_cfg_list[index].task_init)(task_cfg_list[index].parameters);
  88         task_dta_list[index].WCET = TASK_X_WCET_INI;
  89     }
  90 
  91     __asm("CPSID i");
  92     g_app_tick_cnt              = G_APP_TICK_CNT_INI;
  93     g_task_system_tick_cnt      = G_APP_TICK_CNT_INI;
  94     g_task_buttons_tick_cnt     = G_APP_TICK_CNT_INI;
  95     g_task_leds_tick_cnt        = G_APP_TICK_CNT_INI;
  96     g_task_menu_tick_cnt        = G_APP_TICK_CNT_INI;
  97     g_task_temp_ctrl_tick_cnt   = G_APP_TICK_CNT_INI;
  98     g_task_temp_sensor_tick_cnt = G_APP_TICK_CNT_INI;
  99     g_task_remote_tick_cnt      = G_APP_TICK_CNT_INI;
 100     __asm("CPSIE i");
 101 
 102     LOGGER_INFO("Done initializing `app`");
 103     g_app_WCET_us = G_APP_WCET_INI;
 104     g_app_runtime_us_mean = g_app_runtime_us_mean_aux = G_APP_WCET_INI;
 105     g_app_runtime_us_mean_cnt = 0;
 106 }
 107 
 108 void app_update(void)
 109 {
 110     uint32_t index;
 111     bool b_time_update_required = false;
 112     uint32_t cycle_counter_time_us;
 113 
 114     __asm("CPSID i");
 115     if (G_APP_TICK_CNT_INI < g_app_tick_cnt)
 116     {
 117         g_app_tick_cnt--;
 118         b_time_update_required = true;
 119     }
 120     __asm("CPSIE i");
 121 
 122     while (b_time_update_required)
 123     {
 124         g_app_runtime_us = 0;
 125 
 126         for (index = 0; TASK_QTY > index; index++)
 127         {
 128             cycle_counter_reset();
 129 
 130             if (0 == g_app_WCET_sample_us)
 131             {
 132                 g_app_WCET_sample_us = TASK_X_WCET_SAMPLE_TIME_MS;
 133                 task_dta_list[index].WCET_interval = 0;
 134             }
 135             else
 136             {
 137                 g_app_WCET_sample_us--;
 138             }
 139 
 140             (*task_cfg_list[index].task_update)(task_cfg_list[index].parameters);
 141 
 142             cycle_counter_time_us = cycle_counter_get_time_us();
 143             g_app_runtime_us += cycle_counter_time_us;
 144 
 145             if (g_app_WCET_us < g_app_runtime_us) {
 146                 g_app_WCET_us = g_app_runtime_us;
 147                 LOGGER_INFO("App worst execution time (WCET): %lu us", g_app_WCET_us);
 148             }
 149 
 150             if (task_dta_list[index].WCET < cycle_counter_time_us)
 151             {
 152                 task_dta_list[index].WCET = cycle_counter_time_us;
 153             }
 154 
 155             if (task_dta_list[index].WCET_interval< cycle_counter_time_us)
 156             {
 157                 task_dta_list[index].WCET_interval = cycle_counter_time_us;
 158             }
 159         }
 160 
 161         if (G_APP_WCET_MEAN_SAMPLES == g_app_runtime_us_mean_cnt)
 162         {
 163             g_app_runtime_us_mean_cnt = 0;
 164             g_app_runtime_us_mean = g_app_runtime_us_mean_aux / G_APP_WCET_MEAN_SAMPLES;
 165             g_app_runtime_us_mean_aux = G_APP_WCET_INI;
 166         }
 167         else
 168         {
 169             g_app_runtime_us_mean_cnt++;
 170             g_app_runtime_us_mean_aux += g_app_runtime_us;
 171         }
 172 
 173         __asm("CPSID i");
 174         if (G_APP_TICK_CNT_INI < g_app_tick_cnt)
 175         {
 176             g_app_tick_cnt--;
 177             b_time_update_required = true;
 178         }
 179         else
 180         {
 181             b_time_update_required = false;
 182         }
 183         __asm("CPSIE i");
 184     }
 185 }
 186 
 187 // Callbacks definition
 188 
 189 // This is called every ms
 190 void HAL_SYSTICK_Callback(void)
 191 {
 192     g_app_tick_cnt++;
 193 
 194     g_task_system_tick_cnt++;
 195     g_task_buttons_tick_cnt++;
 196     g_task_buzzer_tick_cnt++;
 197     g_task_leds_tick_cnt++;
 198     g_task_menu_tick_cnt++;
 199     g_task_temp_ctrl_tick_cnt++;
 200     g_task_temp_sensor_tick_cnt++;
 201     g_task_remote_tick_cnt++;
 202 }
 203 
 204 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
 205 {
 206     if (huart->Instance == USART1)
 207     {
 208         b_ds18b20_dma_tx_done = true;
 209     }
 210 }
 211 
 212 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
 213 {
 214     if (huart->Instance == USART1)
 215     {
 216         b_ds18b20_dma_rx_done = true;
 217     }
 218     if (huart->Instance == USART3)
 219     {
 220         task_remote_queue_enqueue(&task_remote_rx_queue, task_remote_uart_rx_byte);
 221         HAL_UART_Receive_IT(&huart3, &task_remote_uart_rx_byte, 1);
 222     }
 223 }
 224 
 225 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
 226 {
 227     if (huart->Instance == USART1)
 228     {
 229         b_ds18b20_dma_rx_done = true;
 230     }
 231 }
 232 
 233 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
 234 {
 235     if(huart->Instance == USART1)
 236     {
 237         ;
 238     }
 239 }