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
firmware-nucleo/App/Src/task_remote.c (9549B)
   1 /*
   2  * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
   3  *
   4  * See file `LICENSE` for full details
   5  */
   6 
   7 #include <stdio.h>
   8 #include <stdint.h>
   9 #include <stdbool.h>
  10 #include <string.h>
  11 #include <time.h>
  12 
  13 #include "main.h"
  14 #include "app.h"
  15 
  16 #include "task_remote.h"
  17 #include "task_system_attribute.h"
  18 #include "task_system_interface.h"
  19 #include "logger.h"
  20 
  21 #define G_TASK_REMOTE_TICK_INI            0ul
  22 #define G_TASK_REMOTE_TEMP_UPDATE_RATE_MS 1000ul
  23 
  24 // Public variables
  25 //// this variable is incremented by 1 on every ms by HAL_SysTick
  26 volatile uint32_t g_task_remote_tick_cnt;
  27 queue_t task_remote_rx_queue;
  28 uint8_t task_remote_uart_rx_byte;
  29 uint8_t task_remote_uart_tx_dma_buffer[G_TASK_REMOTE_QUEUE_LEN];
  30 
  31 // Private types declaration
  32 typedef enum {
  33     TX_DATA_STATUS_OK             = 'A',
  34     TX_DATA_MAIN_OUTPUT_TOGGLE_OK = 'B',
  35     TX_DATA_TIMER_TOGGLE_OK       = 'C',
  36     TX_DATA_TIMER_SET_VALUES_OK   = 'D',
  37     TX_DATA_TEMP_STATUS_OK        = 'E',
  38     TX_DATA_TEMP_SET_OK           = 'F'
  39 } uart_tx_data_e;
  40 
  41 typedef enum {
  42     RX_DATA_STATUS             = 'A',
  43     RX_DATA_MAIN_OUTPUT_TOGGLE = 'B',
  44     RX_DATA_TIMER_TOGGLE       = 'C',
  45     RX_DATA_TIMER_SET_VALUES   = 'D',
  46     RX_DATA_TEMP_STATUS        = 'E',
  47     RX_DATA_TEMP_SET           = 'F'
  48 } uart_rx_data_e;
  49 
  50 // Private variables definition
  51 uint32_t g_task_remote_tick;
  52 time_t system_time;
  53 static queue_t task_remote_tx_queue;
  54 
  55 // Public functions declaration
  56 void task_remote_queue_enqueue(queue_t *queue, uint8_t value);
  57 
  58 // Private functions declaration
  59 static void task_remote_rx_data_handler(void *parameters);
  60 static void task_remote_queue_init(queue_t *queue);
  61 static uint8_t task_remote_queue_peek(queue_t *queue);
  62 static uint8_t task_remote_queue_count(queue_t *queue);
  63 static uint8_t task_remote_queue_dequeue(queue_t *queue);
  64 static uint8_t task_remote_queue_is_empty(queue_t *queue);
  65 
  66 // Public funtions implementation
  67 void task_remote_init(void *parameters)
  68 {
  69     LOGGER_INFO("Initializing `task_remote`...");
  70 
  71     task_remote_queue_init(&task_remote_tx_queue);
  72     task_remote_queue_init(&task_remote_rx_queue);
  73 
  74     g_task_remote_tick = G_TASK_REMOTE_TICK_INI;
  75     HAL_UART_Receive_IT(&huart3, &task_remote_uart_rx_byte, 1);
  76 
  77     LOGGER_INFO("Done initializing `task_remote`");
  78 }
  79 
  80 void task_remote_update(void *parameters)
  81 {
  82     bool b_time_update_required = false;
  83     shared_data_type *p_shared_data = (shared_data_type *)parameters;
  84 
  85     __asm("CPSID i");
  86     if (G_TASK_REMOTE_TICK_INI < g_task_remote_tick_cnt)
  87     {
  88         g_task_remote_tick_cnt--;
  89         b_time_update_required = true;
  90     }
  91     __asm("CPSIE i");
  92 
  93     while (b_time_update_required)
  94     {
  95         __asm("CPSID i");
  96         if (G_TASK_REMOTE_TICK_INI < g_task_remote_tick_cnt)
  97         {
  98             g_task_remote_tick_cnt--;
  99             b_time_update_required = true;
 100         }
 101         else
 102         {
 103             b_time_update_required = false;
 104         }
 105         __asm("CPSIE i");
 106 
 107         if (!task_remote_queue_is_empty(&task_remote_rx_queue))
 108         {
 109             task_remote_rx_data_handler(parameters);
 110         }
 111 
 112         // Send temp updated values to remote module
 113         if (0 == g_task_remote_tick)
 114         {
 115             g_task_remote_tick = G_TASK_REMOTE_TEMP_UPDATE_RATE_MS;
 116             task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_STATUS_OK);
 117             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor);
 118             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point);
 119         }
 120         else
 121         {
 122             g_task_remote_tick--;
 123         }
 124 
 125         if(!task_remote_queue_is_empty(&task_remote_tx_queue))
 126         {
 127             uint8_t i;
 128             for (i = 0; !task_remote_queue_is_empty(&task_remote_tx_queue); ++i)
 129             {
 130                 task_remote_uart_tx_dma_buffer[i] = task_remote_queue_dequeue(&task_remote_tx_queue);
 131             }
 132             HAL_UART_Transmit_DMA(&huart3, task_remote_uart_tx_dma_buffer, i);
 133         }
 134     }
 135 }
 136 
 137 void task_remote_queue_enqueue(queue_t *queue, uint8_t value)
 138 {
 139     queue->count++;
 140     queue->data[queue->head++] = value;
 141 }
 142 
 143 // Private function implementation
 144 static void task_remote_rx_data_handler(void *parameters)
 145 {
 146     shared_data_type *p_shared_data = (shared_data_type *)parameters;
 147 
 148     uint8_t query_type = task_remote_queue_peek(&task_remote_rx_queue);
 149 
 150     switch(query_type)
 151     {
 152         case RX_DATA_STATUS:
 153             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 154 
 155             task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_STATUS_OK);
 156             task_remote_queue_enqueue(&task_remote_tx_queue,
 157                     p_shared_data->temp_ctrl_enabled);
 158 
 159             HAL_RTC_GetTime(&hrtc, &s_time, RTC_FORMAT_BIN);
 160             HAL_RTC_GetDate(&hrtc, &s_date, RTC_FORMAT_BIN);
 161 
 162             struct tm time_tm = {
 163                 .tm_year = s_date.Year + 100,
 164                 .tm_mon  = s_date.Month - 1,
 165                 .tm_mday = s_date.Date,
 166                 .tm_hour = s_time.Hours,
 167                 .tm_min  = s_time.Minutes,
 168                 .tm_sec  = s_time.Seconds,
 169             };
 170 
 171             system_time = mktime(&time_tm);
 172 
 173             // LSB first
 174             task_remote_queue_enqueue(&task_remote_tx_queue,
 175                     (uint8_t)(system_time & 0xFF));
 176             task_remote_queue_enqueue(&task_remote_tx_queue,
 177                     (uint8_t)((system_time >> 8) & 0xFF));
 178             task_remote_queue_enqueue(&task_remote_tx_queue,
 179                     (uint8_t)((system_time >> 16) & 0xFF));
 180             task_remote_queue_enqueue(&task_remote_tx_queue,
 181                     (uint8_t)((system_time >> 24) & 0xFF));
 182 
 183             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->enabled);
 184             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->start_hour);
 185             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->start_min);
 186             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->end_hour);
 187             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->end_min);
 188 
 189             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor);
 190             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point);
 191 
 192         break;
 193 
 194         case RX_DATA_MAIN_OUTPUT_TOGGLE:
 195 
 196             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 197             task_system_interface_put_event(EV_SYS_REM_TEMP_CTRL_ENABLED);
 198             task_remote_queue_enqueue(&task_remote_tx_queue,
 199                     TX_DATA_MAIN_OUTPUT_TOGGLE_OK);
 200 
 201         break;
 202 
 203         case RX_DATA_TIMER_TOGGLE:
 204 
 205             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 206             task_system_interface_put_event(EV_SYS_REM_TIMER_TOGGLE);
 207             task_remote_queue_enqueue(&task_remote_tx_queue,
 208                     TX_DATA_TIMER_TOGGLE_OK);
 209 
 210         break;
 211 
 212         case RX_DATA_TIMER_SET_VALUES:
 213 
 214             if (task_remote_queue_count(&task_remote_rx_queue) < 5)
 215             {
 216                 // wait for additional data
 217                 break;
 218             }
 219 
 220             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 221 
 222             p_shared_data->timer->start_hour = task_remote_queue_dequeue(&task_remote_rx_queue);
 223             p_shared_data->timer->start_min  = task_remote_queue_dequeue(&task_remote_rx_queue);
 224             p_shared_data->timer->end_hour   = task_remote_queue_dequeue(&task_remote_rx_queue);
 225             p_shared_data->timer->end_min    = task_remote_queue_dequeue(&task_remote_rx_queue);
 226 
 227             task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TIMER_SET_VALUES_OK);
 228 
 229         break;
 230 
 231         case RX_DATA_TEMP_STATUS:
 232 
 233             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 234 
 235             task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_STATUS_OK);
 236             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor);
 237             task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point);
 238 
 239         break;
 240 
 241         case RX_DATA_TEMP_SET:
 242 
 243             if (task_remote_queue_count(&task_remote_rx_queue) < 2)
 244             {
 245                 // wait for additional data
 246                 break;
 247             }
 248 
 249             task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type
 250             p_shared_data->temp_set_point = task_remote_queue_dequeue(&task_remote_rx_queue);
 251             task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_SET_OK);
 252             task_system_interface_put_event(EV_SYS_REM_TEMP_SET);
 253 
 254         break;
 255 
 256         default: 
 257             task_remote_queue_dequeue(&task_remote_rx_queue);
 258         break;
 259     }
 260 }
 261 
 262 static void task_remote_queue_init(queue_t *queue)
 263 {
 264     queue->head = 0;
 265     queue->tail = 0;
 266     queue->count = 0;
 267 
 268     for (uint8_t i = 0; i < G_TASK_REMOTE_QUEUE_LEN; ++i)
 269     {
 270         queue->data[i] = 0;
 271     }
 272 }
 273 
 274 static uint8_t task_remote_queue_peek(queue_t *queue)
 275 {
 276     return queue->data[queue->tail];
 277 }
 278 
 279 static uint8_t task_remote_queue_count(queue_t *queue)
 280 {
 281     return queue->count;
 282 }
 283 
 284 static uint8_t task_remote_queue_dequeue(queue_t *queue)
 285 {
 286     if(task_remote_queue_is_empty(queue))
 287     {
 288         return task_remote_queue_peek(queue);
 289     }
 290 
 291     queue->count--;
 292     return queue->data[queue->tail++];
 293 }
 294 
 295 static uint8_t task_remote_queue_is_empty(queue_t *queue)
 296 {
 297     return (queue->count == 0);
 298 }
 299