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 42285ecbb1797194e5151185da17a976f9eef4f9
parent 9cd78f02e661327460626f0c0e74c44fc97ff1ea
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date:   Wed, 18 Mar 2026 14:42:21 -0300

Separar `task_sensor` en tareas para cada conjunto de sensores

Antes `task_sensor` incluia los cuatro botones y el sensor de
temperatura, con este commit se separa esta tarea "grande" en dos tareas
mas "pequeñas": `task_temp_sensor` y `task_buttons`. La primera se encarga
de leer periodicamente la temperatura del sensor, mientras que la
segunda se encarga de leer y acuatlizar el estado de los cuatro botones.

Diffstat:
Dfirmware/app/inc/ds18b20.h | 70----------------------------------------------------------------------
Afirmware/app/inc/task_buttons.h | 25+++++++++++++++++++++++++
Afirmware/app/inc/task_buttons_attribute.h | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dfirmware/app/inc/task_sensor.h | 25-------------------------
Dfirmware/app/inc/task_sensor_attribute.h | 101-------------------------------------------------------------------------------
Afirmware/app/inc/task_temp_sensor.h | 24++++++++++++++++++++++++
Afirmware/app/inc/task_temp_sensor_attribute.h | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfirmware/app/src/app.c | 19+++++++++++--------
Dfirmware/app/src/ds18b20.c | 282-------------------------------------------------------------------------------
Afirmware/app/src/task_buttons.c | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dfirmware/app/src/task_sensor.c | 243-------------------------------------------------------------------------------
Afirmware/app/src/task_temp_sensor.c | 332+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 761 insertions(+), 729 deletions(-)
diff --git a/firmware/app/inc/ds18b20.h b/firmware/app/inc/ds18b20.h
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
- *
- * See file `LICENSE` for full details
- */
-
-#ifndef DS18B20_H_
-#define DS18B20_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void UART1_SetBaud(uint32_t baud);
-void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
-
-void DS18B20_Init(void);
-void DS18B20_Write(uint8_t data);
-void DS18B20_Read_temp(void);
-uint8_t DS18B20_Read(void);
-uint8_t DS18B20_Reset(void);
-
-void DS18B20_Update(void);
-void DS18B20_Read_temp_non_blocking(void);
-
-/* DS18B20 Non Blocking State Machine - Transition Table
- *
- * +------------------------------+-------+------------------------+------------------------------+---------------------------+
- * | Current state                | Event | [Guard]                | Next state                   | Actions                   |
- * +==============================+=======+========================+==============================+===========================+
- * |                              |       | [tick == 0]            | ST_DS18B20_BUSY_WAITING_CONV | Send start conversion cmd |
- * + ST_DS18B20_READY             +-------+------------------------+------------------------------+---------------------------+
- * |                              |       |                        | ST_DS18B20_READY             | tick--                    |
- * +------------------------------+-------+------------------------+------------------------------+---------------------------+
- * |                              |       | [tick == 0]            | ST_DS18B20_BUSY_WAITING_DMA  | Transmit/Receive DMA      |
- * |                              |       |                        |                              | tick = DMA_TIMEOUT_MAX    |
- * |                              |       |                        |                              | Data_LSB = 1              |
- * | ST_DS18B20_BUSY_WAITING_CONV +-------+------------------------+------------------------------+---------------------------+
- * |                              |       |                        | ST_DS18B20_BUSY_WAITING_CONV | tick--                    |
- * |                              |       |                        |                              |                           |
- * +------------------------------+-------+------------------------+------------------------------+---------------------------+
- * |                              |       | [tick == 0]            | ST_DS18B20_READY             | tick = TEMP_PERIOD        |
- * |                              |       |                        |                              |                           |
- * | ST_DS18B20_BUSY_WAITING_DMA  +-------+------------------------+------------------------------+---------------------------+
- * |                              |       | [tick != 0 &&          | ST_DS18B20_BUSY_WAITING_DMA  | tick--                    |
- * |                              |       |  Received_data == 0]   |                              |                           |
- * +                              +-------+------------------------+------------------------------+---------------------------+
- * |                              |       | [tick != 0 &&          | ST_DS18B20_BUSY_WAITING_DMA  | tick = DMA_TIMEOUT_MAX    |
- * |                              |       |  Received_data == 1 && |                              | Data_LSB = 0              |
- * |                              |       |   Data_LSB == 1]       |                              | Save received LSB data    |
- * |                              +-------+------------------------+------------------------------+---------------------------+
- * |                              |       | [tick != 0 &&          | ST_DS18B20_READY             | tick = TEMP_PERIOD        |
- * |                              |       |  Received_data == 0 && |                              | Save received MSB data    |
- * |                              |       |   Data_LSB == 0]       |                              |                           |
- * +------------------------------+-------+------------------------+------------------------------+---------------------------+
- *
- *
- */
-
-typedef enum {
-    ST_DS18B20_READY,
-    ST_DS18B20_BUSY_WAITING_CONV,
-    ST_DS18B20_BUSY_WAITING_DMA
-} DS18B20_st_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DS18B20_H_ */
diff --git a/firmware/app/inc/task_buttons.h b/firmware/app/inc/task_buttons.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#ifndef TASK_INC_TASK_BUTTONS_H_
+#define TASK_INC_TASK_BUTTONS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t g_task_buttons_cnt;
+extern volatile uint32_t g_task_buttons_tick_cnt;
+
+extern void task_buttons_init(void *parameters);
+extern void task_buttons_update(void *parameters);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TASK_INC_TASK_SENSOR_H_ */
diff --git a/firmware/app/inc/task_buttons_attribute.h b/firmware/app/inc/task_buttons_attribute.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#ifndef TASK_INC_TASK_BUTTONS_ATTRIBUTE_H_
+#define TASK_INC_TASK_BUTTONS_ATTRIBUTE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TODO: Move every button related code to a separate generic button module 
+
+/* 
+ * Sensor Statechart - State Transition Table
+ *
+ * +-------------------+----------------+-------------+-------------------+-----------------------+
+ * | Current           | Event          |             | Next              |                       |
+ * | State             | (Parameters)   | [Guard]     | State             | Actions               |
+ * |===================+================+=============+===================+=======================|
+ * | INICIAL           |                |             | ST_BTN_XX_UP      |                       |
+ * |-------------------+----------------+-------------+-------------------+-----------------------|
+ * | ST_BTN_XX_UP      | EV_BTN_XX_UP   |             | ST_BTN_XX_UP      |                       |
+ * |                   +----------------+-------------+-------------------+-----------------------|
+ * |                   | EV_BTN_XX_DOWN |             | ST_BTN_XX_FALLING | tick = TICK_MAX       |
+ * |-------------------+----------------+-------------+-------------------+-----------------------|
+ * | ST_BTN_XX_FALLING | EV_BTN_XX_UP   | [tick == 0] | ST_BTN_XX_UP      |                       |
+ * |                   |                +-------------+-------------------+-----------------------|
+ * |                   |                | [tick >  0] | ST_BTN_XX_FALLING | tick--                |
+ * |                   +----------------+-------------+-------------------+-----------------------|
+ * |                   | EV_BTN_XX_DOWN | [tick == 0] | ST_BTN_XX_DOWN    | put_event_task_system |
+ * |                   |                |             |                   |  (event)              |
+ * |                   |                +-------------+-------------------+-----------------------|
+ * |                   |                | [tick >  0] | ST_BTN_XX_FALLING | tick--                |
+ * |-------------------+----------------+-------------+-------------------+-----------------------|
+ * | ST_BTN_XX_DOWN    | EV_BTN_XX_UP   |             | ST_BTN_XX_RISING  | tick = TICK_MAX       |
+ * |                   +----------------+-------------+-------------------+-----------------------|
+ * |                   | EV_BTN_XX_DOWN |             | ST_BTN_XX_DOWN    |                       |
+ * |-------------------+----------------+-------------+-------------------+-----------------------|
+ * | ST_BTN_XX_RISING  | EV_BTN_XX_UP   | [tick == 0] | ST_BTN_XX_UP      | put_event_task_system |
+ * |                   |                |             |                   |  (event)              |
+ * |                   |                +-------------+-------------------+-----------------------|
+ * |                   |                | [tick >  0] | ST_BTN_XX_RISING  | tick--                |
+ * |                   +----------------+-------------+-------------------+-----------------------|
+ * |                   | EV_BTN_XX_DOWN | [tick == 0] | ST_BTN_XX_DOWN    |                       |
+ * |                   |                +-------------+-------------------+-----------------------|
+ * |                   |                | [tick >  0] | ST_BTN_XX_RISING  | tick--                |
+ * +-------------------+----------------+-------------+-------------------+-----------------------+
+ *
+ */
+
+/* Events to excite Task Sensor */
+typedef enum {
+    EV_BTN_XX_UP,
+    EV_BTN_XX_DOWN
+} task_buttons_ev_t;
+
+/* States of Task Sensor */
+typedef enum {
+    ST_BTN_XX_UP,
+    ST_BTN_XX_FALLING,
+    ST_BTN_XX_DOWN,
+    ST_BTN_XX_RISING,
+    ST_SEN_READY
+} task_buttons_st_t;
+
+/* Identifier of Task Sensor */
+typedef enum {
+    ID_BTN_A,
+    ID_BTN_B,
+    ID_BTN_C,
+    ID_BTN_D,
+} task_buttons_id_t;
+
+typedef struct {
+    task_buttons_id_t identifier;
+    GPIO_TypeDef *gpio_port;
+    uint16_t pin;
+    GPIO_PinState pressed;
+    uint32_t tick_max;
+    task_buttons_ev_t signal_up;
+    task_buttons_ev_t signal_down;
+} task_buttons_cfg_t;
+
+typedef struct {
+    uint32_t tick;
+    task_buttons_st_t state;
+    task_buttons_ev_t event;
+} task_buttons_dta_t;
+
+extern task_buttons_dta_t task_buttons_dta_list[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TASK_INC_TASK_SENSOR_ATTRIBUTE_H_ */
diff --git a/firmware/app/inc/task_sensor.h b/firmware/app/inc/task_sensor.h
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
- * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
- *
- * See file `LICENSE` for full details
- */
-
-#ifndef TASK_INC_TASK_SENSOR_H_
-#define TASK_INC_TASK_SENSOR_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern uint32_t g_task_sensor_cnt;
-extern volatile uint32_t g_task_sensor_tick_cnt;
-
-extern void task_sensor_init(void *parameters);
-extern void task_sensor_update(void *parameters);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TASK_INC_TASK_SENSOR_H_ */
diff --git a/firmware/app/inc/task_sensor_attribute.h b/firmware/app/inc/task_sensor_attribute.h
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
- * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
- *
- * See file `LICENSE` for full details
- */
-
-#ifndef TASK_INC_TASK_SENSOR_ATTRIBUTE_H_
-#define TASK_INC_TASK_SENSOR_ATTRIBUTE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// TODO: Move every button related code to a separate generic button module 
-
-/* 
- * Sensor Statechart - State Transition Table
- *
- * +-------------------+----------------+-------------+-------------------+-----------------------+
- * | Current           | Event          |             | Next              |                       |
- * | State             | (Parameters)   | [Guard]     | State             | Actions               |
- * |===================+================+=============+===================+=======================|
- * | INICIAL           |                |             | ST_BTN_XX_UP      |                       |
- * |-------------------+----------------+-------------+-------------------+-----------------------|
- * | ST_BTN_XX_UP      | EV_BTN_XX_UP   |             | ST_BTN_XX_UP      |                       |
- * |                   +----------------+-------------+-------------------+-----------------------|
- * |                   | EV_BTN_XX_DOWN |             | ST_BTN_XX_FALLING | tick = TICK_MAX       |
- * |-------------------+----------------+-------------+-------------------+-----------------------|
- * | ST_BTN_XX_FALLING | EV_BTN_XX_UP   | [tick == 0] | ST_BTN_XX_UP      |                       |
- * |                   |                +-------------+-------------------+-----------------------|
- * |                   |                | [tick >  0] | ST_BTN_XX_FALLING | tick--                |
- * |                   +----------------+-------------+-------------------+-----------------------|
- * |                   | EV_BTN_XX_DOWN | [tick == 0] | ST_BTN_XX_DOWN    | put_event_task_system |
- * |                   |                |             |                   |  (event)              |
- * |                   |                +-------------+-------------------+-----------------------|
- * |                   |                | [tick >  0] | ST_BTN_XX_FALLING | tick--                |
- * |-------------------+----------------+-------------+-------------------+-----------------------|
- * | ST_BTN_XX_DOWN    | EV_BTN_XX_UP   |             | ST_BTN_XX_RISING  | tick = TICK_MAX       |
- * |                   +----------------+-------------+-------------------+-----------------------|
- * |                   | EV_BTN_XX_DOWN |             | ST_BTN_XX_DOWN    |                       |
- * |-------------------+----------------+-------------+-------------------+-----------------------|
- * | ST_BTN_XX_RISING  | EV_BTN_XX_UP   | [tick == 0] | ST_BTN_XX_UP      | put_event_task_system |
- * |                   |                |             |                   |  (event)              |
- * |                   |                +-------------+-------------------+-----------------------|
- * |                   |                | [tick >  0] | ST_BTN_XX_RISING  | tick--                |
- * |                   +----------------+-------------+-------------------+-----------------------|
- * |                   | EV_BTN_XX_DOWN | [tick == 0] | ST_BTN_XX_DOWN    |                       |
- * |                   |                +-------------+-------------------+-----------------------|
- * |                   |                | [tick >  0] | ST_BTN_XX_RISING  | tick--                |
- * +-------------------+----------------+-------------+-------------------+-----------------------+
- *
- */
-
-/* Events to excite Task Sensor */
-typedef enum {
-    EV_BTN_XX_UP,
-    EV_BTN_XX_DOWN
-} task_sensor_ev_t;
-
-/* States of Task Sensor */
-typedef enum {
-    ST_BTN_XX_UP,
-    ST_BTN_XX_FALLING,
-    ST_BTN_XX_DOWN,
-    ST_BTN_XX_RISING,
-    ST_SEN_READY
-} task_sensor_st_t;
-
-/* Identifier of Task Sensor */
-typedef enum {
-    ID_BTN_A,
-    ID_BTN_B,
-    ID_BTN_C,
-    ID_BTN_D,
-    ID_DS18B20
-} task_sensor_id_t;
-
-typedef struct {
-    task_sensor_id_t identifier;
-    GPIO_TypeDef *gpio_port;
-    uint16_t pin;
-    GPIO_PinState pressed;
-    uint32_t tick_max;
-    task_sensor_ev_t signal_up;
-    task_sensor_ev_t signal_down;
-} task_sensor_cfg_t;
-
-typedef struct {
-    uint32_t tick;
-    task_sensor_st_t state;
-    task_sensor_ev_t event;
-} task_sensor_dta_t;
-
-extern task_sensor_dta_t task_sensor_dta_list[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TASK_INC_TASK_SENSOR_ATTRIBUTE_H_ */
diff --git a/firmware/app/inc/task_temp_sensor.h b/firmware/app/inc/task_temp_sensor.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#ifndef DS18B20_H_
+#define DS18B20_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t g_task_temp_sensor_cnt;
+extern volatile uint32_t g_task_temp_sensor_tick_cnt;
+
+void task_temp_sensor_init(void *parameters);
+void task_temp_sensor_update(void *parameters);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DS18B20_H_ */
diff --git a/firmware/app/inc/task_temp_sensor_attribute.h b/firmware/app/inc/task_temp_sensor_attribute.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#ifndef TASK_INC_TASK_TEMP_SENSOR_ATTRIBUTE_H_
+#define TASK_INC_TASK_TEMP_SENSOR_ATTRIBUTE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DS18B20 Non Blocking State Machine - Transition Table
+ *
+ * +------------------------------+-------+------------------------+------------------------------+---------------------------+
+ * | Current state                | Event | [Guard]                | Next state                   | Actions                   |
+ * +==============================+=======+========================+==============================+===========================+
+ * |                              |       | [tick == 0]            | ST_DS18B20_BUSY_WAITING_CONV | Send start conversion cmd |
+ * + ST_DS18B20_READY             +-------+------------------------+------------------------------+---------------------------+
+ * |                              |       |                        | ST_DS18B20_READY             | tick--                    |
+ * +------------------------------+-------+------------------------+------------------------------+---------------------------+
+ * |                              |       | [tick == 0]            | ST_DS18B20_BUSY_WAITING_DMA  | Transmit/Receive DMA      |
+ * |                              |       |                        |                              | tick = DMA_TIMEOUT_MAX    |
+ * |                              |       |                        |                              | Data_LSB = 1              |
+ * | ST_DS18B20_BUSY_WAITING_CONV +-------+------------------------+------------------------------+---------------------------+
+ * |                              |       |                        | ST_DS18B20_BUSY_WAITING_CONV | tick--                    |
+ * |                              |       |                        |                              |                           |
+ * +------------------------------+-------+------------------------+------------------------------+---------------------------+
+ * |                              |       | [tick == 0]            | ST_DS18B20_READY             | tick = TEMP_PERIOD        |
+ * |                              |       |                        |                              |                           |
+ * | ST_DS18B20_BUSY_WAITING_DMA  +-------+------------------------+------------------------------+---------------------------+
+ * |                              |       | [tick != 0 &&          | ST_DS18B20_BUSY_WAITING_DMA  | tick--                    |
+ * |                              |       |  Received_data == 0]   |                              |                           |
+ * +                              +-------+------------------------+------------------------------+---------------------------+
+ * |                              |       | [tick != 0 &&          | ST_DS18B20_BUSY_WAITING_DMA  | tick = DMA_TIMEOUT_MAX    |
+ * |                              |       |  Received_data == 1 && |                              | Data_LSB = 0              |
+ * |                              |       |   Data_LSB == 1]       |                              | Save received LSB data    |
+ * |                              +-------+------------------------+------------------------------+---------------------------+
+ * |                              |       | [tick != 0 &&          | ST_DS18B20_READY             | tick = TEMP_PERIOD        |
+ * |                              |       |  Received_data == 0 && |                              | Save received MSB data    |
+ * |                              |       |   Data_LSB == 0]       |                              |                           |
+ * +------------------------------+-------+------------------------+------------------------------+---------------------------+
+ *
+ *
+ */
+
+typedef enum {
+    ST_DS18B20_READY,
+    ST_DS18B20_BUSY_WAITING_CONV,
+    ST_DS18B20_BUSY_WAITING_DMA
+} DS18B20_st_t;
+
+/* Identifier of Task Sensor */
+typedef enum {
+    ID_DS18B20_A,
+} task_temp_sensor_id_t;
+
+typedef struct {
+    task_temp_sensor_id_t identifier;
+} task_temp_sensor_cfg_t;
+
+typedef struct {
+    uint32_t tick;
+    DS18B20_st_t state;
+    // task_temp_sensor_ev_t event;
+} task_temp_sensor_dta_t;
+
+extern task_temp_sensor_dta_t task_temp_sensor_dta_list[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TASK_INC_TASK_SENSOR_ATTRIBUTE_H_ */
diff --git a/firmware/app/src/app.c b/firmware/app/src/app.c
@@ -13,7 +13,8 @@
 #include "board.h"
 #include "task_system.h"
 #include "task_actuator.h"
-#include "task_sensor.h"
+#include "task_temp_sensor.h"
+#include "task_buttons.h"
 
 #define G_APP_CNT_INI       0ul
 #define G_APP_TICK_CNT_INI  0ul
@@ -33,9 +34,10 @@ typedef struct {
 } task_dta_t;
 
 const task_cfg_t task_cfg_list[] = {
-    {task_sensor_init,   task_sensor_update,   NULL},
-    {task_system_init,   task_system_update,   NULL},
-    {task_actuator_init, task_actuator_update, NULL}
+    {task_buttons_init,     task_buttons_update,     NULL},
+    {task_temp_sensor_init, task_temp_sensor_update, NULL},
+    {task_system_init,      task_system_update,      NULL},
+    {task_actuator_init,    task_actuator_update,    NULL}
 };
 
 #define TASK_QTY (sizeof(task_cfg_list)/sizeof(task_cfg_t))
@@ -52,8 +54,6 @@ void app_init(void)
 {
     LOGGER_INFO("Initializing `app`...");
 
-    g_app_WCET_us = G_APP_WCET_INI;
-
     cycle_counter_init();
 
     for (uint32_t index = 0; TASK_QTY > index; index++)
@@ -64,12 +64,14 @@ void app_init(void)
 
     __asm("CPSID i");
     g_app_tick_cnt = G_APP_TICK_CNT_INI;
-    g_task_sensor_tick_cnt = G_APP_TICK_CNT_INI;
+    g_task_buttons_tick_cnt = G_APP_TICK_CNT_INI;
+    g_task_temp_sensor_tick_cnt = G_APP_TICK_CNT_INI;
     g_task_system_tick_cnt = G_APP_TICK_CNT_INI;
     g_task_actuator_tick_cnt = G_APP_TICK_CNT_INI;
     __asm("CPSIE i");
 
     LOGGER_INFO("Done initializing `app`");
+    g_app_WCET_us = G_APP_WCET_INI;
 }
 
 void app_update(void)
@@ -130,7 +132,8 @@ void app_update(void)
 void HAL_SYSTICK_Callback(void)
 {
     g_app_tick_cnt++;
-    g_task_sensor_tick_cnt++;
+    g_task_buttons_tick_cnt++;
+    g_task_temp_sensor_tick_cnt++;
     g_task_system_tick_cnt++;
     g_task_actuator_tick_cnt++;
 }
diff --git a/firmware/app/src/ds18b20.c b/firmware/app/src/ds18b20.c
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
- *
- * See file `LICENSE` for full details
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include "main.h"
-
-#include "ds18b20.h"
-#include "logger.h"
-
-#define G_DS18B20_CONV_TIME_MS   180ul // ~188ms for 10 bit resolution
-#define G_DS18B20_DMA_TIMEOUT_MS 5000ul
-#define G_TEMP_PERIOD_MS         2000ul
-
-volatile bool b_DS18B20_Received_data;
-uint8_t g_DS18B20_Received_data_buffer[8];
-float g_DS18B20_temp;
-
-DS18B20_st_t g_DS18B20_state;
-uint32_t g_DS18B20_tick;
-
-uint8_t Temp_LSB;
-uint8_t Temp_MSB;
-static const uint8_t buffer[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-static bool b_DS18B20_Received_data_LSB;
-
-void UART1_SetBaud(uint32_t baud)
-{
-    huart1.Instance = USART1;
-    huart1.Init.BaudRate = baud;
-    huart1.Init.WordLength = UART_WORDLENGTH_8B;
-    huart1.Init.StopBits = UART_STOPBITS_1;
-    huart1.Init.Parity = UART_PARITY_NONE;
-    huart1.Init.Mode = UART_MODE_TX_RX;
-    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
-    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
-    if (HAL_HalfDuplex_Init(&huart1) != HAL_OK)
-    {
-        Error_Handler();
-    };
-}
-
-uint8_t DS18B20_Reset(void)
-{
-    uint8_t data = 0xF0;
-    UART1_SetBaud(9600);
-    HAL_UART_Transmit(&huart1, &data, 1, 100);
-
-    if ((HAL_UART_Receive(&huart1, &data, 1, 1000) != HAL_OK) || (data == 0xF0))
-    {
-        // initialization failed
-        LOGGER_ERROR("Couldn't read temperature sensor");
-        return 1;
-    }
-
-    UART1_SetBaud(115200);
-    return 0;
-}
-
-void DS18B20_SetResolution(uint8_t resolution)
-{
-    uint8_t config;
-
-    switch(resolution)
-    {
-        case 9:  config = 0x1F; break;
-        case 10: config = 0x3F; break;
-        case 11: config = 0x5F; break;
-        case 12: config = 0x7F; break;
-        default: config = 0x7F;
-    }
-
-    DS18B20_Reset();
-    DS18B20_Write(0xCC); // Send 'Skip ROM' command
-    DS18B20_Write(0x4E); // Send 'write scratchpad' command
-
-    DS18B20_Write(0x00); // TH
-    DS18B20_Write(0x00); // TL
-    DS18B20_Write(config);
-
-    DS18B20_Reset();
-
-    DS18B20_Write(0xCC); // Skip ROM
-    DS18B20_Write(0x48); // Write scratchpad to EEPROM
-}
-
-void DS18B20_Init(void)
-{
-    if (DS18B20_Reset() == 0)
-    {
-        LOGGER_INFO("Temperature sensor initialized successfully");
-    }
-    DS18B20_SetResolution(10);
-    g_DS18B20_state = ST_DS18B20_READY;
-    g_DS18B20_tick = G_TEMP_PERIOD_MS;
-}
-
-void DS18B20_Write(uint8_t data)
-{
-    uint8_t buffer[8];
-
-    for (uint8_t i = 0; i < 8; ++i)
-    {
-        if (data & (1 << i))
-        {
-            buffer[i] = 0xFF;
-        }
-        else
-        {
-            buffer[i] = 0x00;
-        }
-    }
-
-    // This is a blocking call and can wait at most 100ms
-    HAL_UART_Transmit(&huart1, buffer, 8, 100);
-}
-
-// Blocking version
-uint8_t DS18B20_Read(void)
-{
-    uint8_t buffer[8];
-    uint8_t received_value = 0;
-
-    for (uint8_t i = 0; i < 8; ++i)
-    {
-        buffer[i] = 0xFF;
-    }
-
-    HAL_UART_Transmit_DMA(&huart1, buffer, 8);
-    HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
-
-    while(b_DS18B20_Received_data == false)
-        ;
-
-    b_DS18B20_Received_data = false;
-
-    for (uint8_t i = 0; i < 8; ++i)
-    {
-        if (g_DS18B20_Received_data_buffer[i] == 0xFF)
-        {
-            received_value |= (1 << i);
-        }
-    }
-
-    return received_value;
-}
-
-void DS18B20_Read_temp(void)
-{
-    DS18B20_Reset();
-    DS18B20_Write(0xCC); // Send 'Skip ROM' command
-    DS18B20_Write(0x44); // Send 'Convert T' command
-
-    DS18B20_Reset();
-    DS18B20_Write(0xCC); // Send 'Skip ROM' command
-    DS18B20_Write(0xBE); // Send 'read scratchpad' command
-
-    Temp_LSB = DS18B20_Read();
-    Temp_MSB = DS18B20_Read();
-
-    uint16_t temp = (Temp_MSB << 8) | Temp_LSB;
-    g_DS18B20_temp = (float) temp / 16.0;
-}
-
-void DS18B20_Read_temp_non_blocking(void)
-{
-    switch (g_DS18B20_state)
-    {
-        case ST_DS18B20_READY:
-            if (0 == g_DS18B20_tick)
-            {
-                // Send start temp conversion command
-                // this needs 96ms to 750ms depending on resolution
-                DS18B20_Reset();
-                DS18B20_Write(0xCC); // Send 'Skip ROM' command
-                DS18B20_Write(0x44); // Send 'Convert T' command
-
-                g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
-                g_DS18B20_tick = G_DS18B20_CONV_TIME_MS;
-            }
-            else
-            {
-                g_DS18B20_tick--;
-            }
-            break;
-
-        case ST_DS18B20_BUSY_WAITING_CONV:
-            if (0 == g_DS18B20_tick)
-            {
-                DS18B20_Reset();
-                DS18B20_Write(0xCC); // Send 'Skip ROM' command
-                DS18B20_Write(0xBE); // Send 'read scratchpad' command
-
-                if (HAL_OK == HAL_UART_Transmit_DMA(&huart1, buffer, 8))
-                {
-                    if (HAL_OK == HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8))
-                    {
-                        b_DS18B20_Received_data_LSB = true;
-                        g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
-                        g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
-                    }
-                }
-            }
-            else
-            {
-                g_DS18B20_tick--;
-            }
-
-            break;
-
-        case ST_DS18B20_BUSY_WAITING_DMA:
-
-            if (0 == g_DS18B20_tick)
-            {
-                // DMA Timeout, reset conversion
-                g_DS18B20_state = ST_DS18B20_READY;
-                g_DS18B20_tick = G_TEMP_PERIOD_MS;
-                break;
-            }
-            else
-            {
-                g_DS18B20_tick--;
-            }
-
-            if (true == b_DS18B20_Received_data)
-            {
-                b_DS18B20_Received_data = false;
-
-                uint8_t received_value = 0;
-                for (uint8_t i = 0; i < 8; ++i)
-                {
-                    if (g_DS18B20_Received_data_buffer[i] == 0xFF)
-                    {
-                        received_value |= (1 << i);
-                    }
-                }
-
-
-
-                if (true == b_DS18B20_Received_data_LSB)
-                {
-                    if (HAL_OK == HAL_UART_Transmit_DMA(&huart1, buffer, 8))
-                    {
-                        if (HAL_OK == HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8))
-                        {
-                            b_DS18B20_Received_data_LSB = false;
-                            Temp_LSB = received_value;
-                            g_DS18B20_tick = G_DS18B20_DMA_TIMEOUT_MS;
-                        }
-                    }
-                }
-                else
-                {
-                    Temp_MSB = received_value;
-                    uint16_t temp = ((Temp_MSB << 8) | Temp_LSB);
-                    g_DS18B20_temp = (float) temp / 16.0;
-                    g_DS18B20_state = ST_DS18B20_READY;
-                    g_DS18B20_tick = G_TEMP_PERIOD_MS;
-                }
-            }
-
-            break;
-
-        default: break;
-    }
-}
-
-void DS18B20_Update(void)
-{
-    DS18B20_Read_temp_non_blocking();
-}
-
-void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
-{
-    b_DS18B20_Received_data = true;
-}
diff --git a/firmware/app/src/task_buttons.c b/firmware/app/src/task_buttons.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#include "main.h"
+
+#include "logger.h"
+#include "dwt.h"
+
+#include "board.h"
+#include "app.h"
+#include "task_buttons_attribute.h"
+#include "task_system_attribute.h"
+#include "task_system_interface.h"
+
+#define G_TASK_SEN_TICK_CNT_INI   0ul
+
+#define DEL_BTN_XX_MIN          0ul
+#define DEL_BTN_XX_MED          25ul
+#define DEL_BTN_XX_MAX          50ul
+
+const task_buttons_cfg_t task_buttons_cfg_list[] = {
+    {ID_BTN_A, BTN_A_GPIO_Port, BTN_A_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
+    {ID_BTN_B, BTN_B_GPIO_Port, BTN_B_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
+    {ID_BTN_C, BTN_C_GPIO_Port, BTN_C_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
+    {ID_BTN_D, BTN_D_GPIO_Port, BTN_D_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
+};
+
+#define BUTTONS_CFG_QTY (sizeof(task_buttons_cfg_list)/sizeof(task_buttons_cfg_t))
+
+task_buttons_dta_t task_buttons_dta_list[] = {
+    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
+    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
+    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
+    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
+};
+
+#define BUTTONS_DTA_QTY (sizeof(task_buttons_dta_list)/sizeof(task_buttons_dta_t))
+
+// this variable is incremented by 1 on every ms by HAL_SysTick
+volatile uint32_t g_task_buttons_tick_cnt;
+
+void task_buttons_init(void *parameters)
+{
+    const task_buttons_cfg_t *p_task_buttons_cfg;
+    task_buttons_dta_t *p_task_buttons_dta;
+
+    LOGGER_INFO("Initializing `task_buttons`...");
+
+    for (uint32_t index = 0; BUTTONS_DTA_QTY > index; index++)
+    {
+        p_task_buttons_cfg = &task_buttons_cfg_list[index];
+        p_task_buttons_dta = &task_buttons_dta_list[index];
+
+        p_task_buttons_dta->state = ST_BTN_XX_UP;
+        p_task_buttons_dta->event = EV_BTN_XX_UP;
+    }
+
+    LOGGER_INFO("Done initializing `task_buttons`");
+}
+
+void task_buttons_update(void *parameters)
+{
+    const task_buttons_cfg_t *p_task_buttons_cfg;
+    task_buttons_dta_t *p_task_buttons_dta;
+
+    bool b_time_update_required = false;
+
+    __asm("CPSID i");
+    if (G_TASK_SEN_TICK_CNT_INI < g_task_buttons_tick_cnt)
+    {
+        g_task_buttons_tick_cnt--;
+        b_time_update_required = true;
+    }
+    __asm("CPSIE i");
+
+    while (b_time_update_required)
+    {
+        task_buttons_statechart();
+
+        __asm("CPSID i");
+        if (G_TASK_SEN_TICK_CNT_INI < g_task_buttons_tick_cnt)
+        {
+            g_task_buttons_tick_cnt--;
+            b_time_update_required = true;
+        }
+        else
+        {
+            b_time_update_required = false;
+        }
+        __asm("CPSIE i");
+
+    }
+}
+
+void task_buttons_statechart(void)
+{
+    uint32_t index;
+    const task_buttons_cfg_t *p_task_buttons_cfg;
+    task_buttons_dta_t       *p_task_buttons_dta;
+    uint8_t button_pin_status;
+
+    for (index = 0; BUTTONS_DTA_QTY > index; index++)
+    {
+        p_task_buttons_cfg = &task_buttons_cfg_list[index];
+        p_task_buttons_dta = &task_buttons_dta_list[index];
+
+        button_pin_status = HAL_GPIO_ReadPin(p_task_buttons_cfg->gpio_port, p_task_buttons_cfg->pin);
+
+        if (button_pin_status == p_task_buttons_cfg->pressed)
+        {
+            p_task_buttons_dta->event = EV_BTN_XX_DOWN;
+        }
+        else
+        {
+            p_task_buttons_dta->event = EV_BTN_XX_UP;
+        }
+
+        switch (p_task_buttons_dta->state)
+        {
+            case ST_BTN_XX_UP:
+                if (EV_BTN_XX_DOWN == p_task_buttons_dta->event)
+                {
+                    p_task_buttons_dta->state = ST_BTN_XX_FALLING;
+                    p_task_buttons_dta->tick  = DEL_BTN_XX_MAX;
+                }
+            break;
+
+            case ST_BTN_XX_FALLING:
+                if (EV_BTN_XX_UP == p_task_buttons_dta->event)
+                {
+                    if (0 == p_task_buttons_dta->tick) {
+                        p_task_buttons_dta->state = ST_BTN_XX_UP;
+                    }
+
+                    if (p_task_buttons_dta->tick > 0) {
+                        p_task_buttons_dta->state = ST_BTN_XX_FALLING;
+                        p_task_buttons_dta->tick--;
+                    }
+                }
+
+                if (EV_BTN_XX_DOWN == p_task_buttons_dta->event)
+                {
+                    if (0 == p_task_buttons_dta->tick) {
+                        p_task_buttons_dta->state = ST_BTN_XX_DOWN;
+                        put_event_task_system(p_task_buttons_cfg->signal_down);
+                    }
+
+                    if (p_task_buttons_dta->tick > 0) {
+                        p_task_buttons_dta->tick--;
+                    }
+                }
+            break;
+
+            case ST_BTN_XX_DOWN:
+                if (EV_BTN_XX_UP == p_task_buttons_dta->event)
+                {
+                    p_task_buttons_dta->state = ST_BTN_XX_RISING;
+                    p_task_buttons_dta->tick  = DEL_BTN_XX_MAX;
+                }
+            break;
+
+            case ST_BTN_XX_RISING:
+                if (EV_BTN_XX_UP == p_task_buttons_dta->event)
+                {
+                    if (0 == p_task_buttons_dta->tick) {
+                        put_event_task_system(p_task_buttons_cfg->signal_up);
+                        p_task_buttons_dta->state = ST_BTN_XX_UP;
+                    }
+
+                    if (p_task_buttons_dta->tick > 0) {
+                        p_task_buttons_dta->tick--;
+                    }
+                }
+
+                if (EV_BTN_XX_DOWN == p_task_buttons_dta->event)
+                {
+                    if (0 == p_task_buttons_dta->tick) {
+                        p_task_buttons_dta->state = ST_BTN_XX_DOWN;
+                    }
+
+                    if (p_task_buttons_dta->tick > 0) {
+                        p_task_buttons_dta->tick--;
+                    }
+                }
+            break;
+
+            default: break;
+        }
+    }
+}
diff --git a/firmware/app/src/task_sensor.c b/firmware/app/src/task_sensor.c
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2023 Juan Manuel Cruz <jcruz@fi.uba.ar> <jcruz@frba.utn.edu.ar>.
- * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
- *
- * See file `LICENSE` for full details
- */
-
-#include "main.h"
-
-#include "logger.h"
-#include "dwt.h"
-
-#include "board.h"
-#include "app.h"
-#include "task_sensor_attribute.h"
-#include "task_system_attribute.h"
-#include "task_system_interface.h"
-#include "ds18b20.h"
-
-#define G_TASK_SEN_TICK_CNT_INI   0ul
-#define G_TASK_SEN_TEMP_PERIOD_MS 1000ul
-
-#define DEL_BTN_XX_MIN          0ul
-#define DEL_BTN_XX_MED          25ul
-#define DEL_BTN_XX_MAX          50ul
-
-const task_sensor_cfg_t task_sensor_cfg_list[] = {
-    {ID_BTN_A, BTN_A_GPIO_Port, BTN_A_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
-    {ID_BTN_B, BTN_B_GPIO_Port, BTN_B_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
-    {ID_BTN_C, BTN_C_GPIO_Port, BTN_C_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
-    {ID_BTN_D, BTN_D_GPIO_Port, BTN_D_Pin, BTN_A_PRESSED, DEL_BTN_XX_MAX, EV_SYS_IDLE, EV_SYS_IDLE},
-    {ID_DS18B20}
-};
-
-#define SENSOR_CFG_QTY (sizeof(task_sensor_cfg_list)/sizeof(task_sensor_cfg_t))
-
-task_sensor_dta_t task_sensor_dta_list[] = {
-    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
-    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
-    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
-    {DEL_BTN_XX_MIN, ST_BTN_XX_UP, EV_BTN_XX_UP},
-    {G_TASK_SEN_TEMP_PERIOD_MS, ST_SEN_READY}
-};
-
-#define SENSOR_DTA_QTY (sizeof(task_sensor_dta_list)/sizeof(task_sensor_dta_t))
-
-// void task_sensor_statechart(void);
-
-// local global variables
-uint32_t g_task_sensor_tick;
-
-// this variable is incremented by 1 on every ms by HAL_SysTick
-volatile uint32_t g_task_sensor_tick_cnt;
-
-void task_sensor_init(void *parameters)
-{
-    const task_sensor_cfg_t *p_task_sensor_cfg;
-    task_sensor_dta_t *p_task_sensor_dta;
-
-    LOGGER_INFO("Initializing `task_sensor`...");
-
-    g_task_sensor_tick = G_TASK_SEN_TEMP_PERIOD_MS;
-
-    for (uint32_t index = 0; SENSOR_DTA_QTY > index; index++)
-    {
-        p_task_sensor_cfg = &task_sensor_cfg_list[index];
-        p_task_sensor_dta = &task_sensor_dta_list[index];
-
-        switch (p_task_sensor_cfg->identifier) {
-            case ID_DS18B20:
-                DS18B20_Init();
-            break;
-
-            default:
-
-                p_task_sensor_dta = &task_sensor_dta_list[index];
-
-                p_task_sensor_dta->state = ST_BTN_XX_UP;
-                p_task_sensor_dta->event = EV_BTN_XX_UP;
-
-            break;
-        }
-
-    }
-
-    LOGGER_INFO("Done initializing `task_sensor`");
-}
-
-uint8_t sensor_pin_status;
-void task_sensor_update(void *parameters)
-{
-    const task_sensor_cfg_t *p_task_sensor_cfg;
-    task_sensor_dta_t *p_task_sensor_dta;
-
-    bool b_time_update_required = false;
-
-    __asm("CPSID i");
-    if (G_TASK_SEN_TICK_CNT_INI < g_task_sensor_tick_cnt)
-    {
-        g_task_sensor_tick_cnt--;
-        b_time_update_required = true;
-    }
-    __asm("CPSIE i");
-
-    while (b_time_update_required)
-    {
-        for (uint32_t index = 0; SENSOR_DTA_QTY > index; index++)
-        {
-            p_task_sensor_cfg = &task_sensor_cfg_list[index];
-            p_task_sensor_dta = &task_sensor_dta_list[index];
-
-            switch (p_task_sensor_cfg->identifier)
-            {
-                case ID_DS18B20:
-                    DS18B20_Update();
-                break;
-
-                default:
-                    sensor_pin_status = HAL_GPIO_ReadPin(p_task_sensor_cfg->gpio_port, p_task_sensor_cfg->pin);
-
-                    if (sensor_pin_status == p_task_sensor_cfg->pressed)
-                    {
-                        p_task_sensor_dta->event = EV_BTN_XX_DOWN;
-                    }
-                    else
-                    {
-                        p_task_sensor_dta->event = EV_BTN_XX_UP;
-                    }
-
-                    switch (p_task_sensor_dta->state)
-                    {
-                        case ST_BTN_XX_UP:
-                            if (EV_BTN_XX_DOWN == p_task_sensor_dta->event)
-                            {
-                                p_task_sensor_dta->state = ST_BTN_XX_FALLING;
-                                p_task_sensor_dta->tick  = DEL_BTN_XX_MAX;
-                            }
-                        break;
-
-                        case ST_BTN_XX_FALLING:
-                            if (EV_BTN_XX_UP == p_task_sensor_dta->event)
-                            {
-                                if (0 == p_task_sensor_dta->tick) {
-                                    p_task_sensor_dta->state = ST_BTN_XX_UP;
-                                }
-
-                                if (p_task_sensor_dta->tick > 0) {
-                                    p_task_sensor_dta->state = ST_BTN_XX_FALLING;
-                                    p_task_sensor_dta->tick--;
-                                }
-                            }
-
-                            if (EV_BTN_XX_DOWN == p_task_sensor_dta->event)
-                            {
-                                if (0 == p_task_sensor_dta->tick) {
-                                    p_task_sensor_dta->state = ST_BTN_XX_DOWN;
-                                    put_event_task_system(p_task_sensor_cfg->signal_down);
-                                }
-
-                                if (p_task_sensor_dta->tick > 0) {
-                                    p_task_sensor_dta->tick--;
-                                }
-                            }
-                        break;
-
-                        case ST_BTN_XX_DOWN:
-                            if (EV_BTN_XX_UP == p_task_sensor_dta->event)
-                            {
-                                p_task_sensor_dta->state = ST_BTN_XX_RISING;
-                                p_task_sensor_dta->tick  = DEL_BTN_XX_MAX;
-                            }
-                        break;
-
-                        case ST_BTN_XX_RISING:
-                            if (EV_BTN_XX_UP == p_task_sensor_dta->event)
-                            {
-                                if (0 == p_task_sensor_dta->tick) {
-                                    put_event_task_system(p_task_sensor_cfg->signal_up);
-                                    p_task_sensor_dta->state = ST_BTN_XX_UP;
-                                }
-
-                                if (p_task_sensor_dta->tick > 0) {
-                                    p_task_sensor_dta->tick--;
-                                }
-                            }
-
-                            if (EV_BTN_XX_DOWN == p_task_sensor_dta->event)
-                            {
-                                if (0 == p_task_sensor_dta->tick) {
-                                    p_task_sensor_dta->state = ST_BTN_XX_DOWN;
-                                }
-
-                                if (p_task_sensor_dta->tick > 0) {
-                                    p_task_sensor_dta->tick--;
-                                }
-                            }
-                        break;
-
-                        default: break;
-                    }
-                break;
-            }
-        }
-
-        __asm("CPSID i");
-        if (G_TASK_SEN_TICK_CNT_INI < g_task_sensor_tick_cnt)
-        {
-            g_task_sensor_tick_cnt--;
-            b_time_update_required = true;
-        }
-        else
-        {
-            b_time_update_required = false;
-        }
-        __asm("CPSIE i");
-
-    }
-}
-
-/*
-void task_sensor_statechart(void)
-{
-    uint32_t index;
-    const task_sensor_cfg_t *p_task_sensor_cfg;
-    // task_sensor_dta_t       *p_task_sensor_dta;
-
-
-    for (index = 0; SENSOR_DTA_QTY > index; index++)
-    {
-        p_task_sensor_cfg = &task_sensor_cfg_list[index];
-        // p_task_sensor_dta = &task_sensor_dta_list[index];
-
-        switch (p_task_sensor_cfg->identifier)
-        {
-            case ID_DS18B20:
-                DS18B20_Update();
-            break;
-
-            default: break;
-        }
-    }
-}
-*/
diff --git a/firmware/app/src/task_temp_sensor.c b/firmware/app/src/task_temp_sensor.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar>
+ *
+ * See file `LICENSE` for full details
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "main.h"
+
+#include "task_temp_sensor_attribute.h"
+#include "task_temp_sensor.h"
+#include "logger.h"
+
+#define G_TASK_SEN_TICK_CNT_INI  0ul
+#define G_DS18B20_CONV_TIME_MS   180ul // ~188ms for 10 bit resolution
+#define G_DS18B20_DMA_TIMEOUT_MS 2000ul
+#define G_TEMP_PERIOD_MS         1000ul
+
+// local global variables
+volatile bool b_DS18B20_Received_data;
+uint8_t g_DS18B20_Received_data_buffer[8];
+float g_DS18B20_temp;
+
+DS18B20_st_t g_DS18B20_state;
+uint32_t g_task_temp_sensor_tick;
+
+uint8_t Temp_LSB;
+uint8_t Temp_MSB;
+static const uint8_t buffer[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+static bool b_DS18B20_Received_data_LSB;
+
+// this variable is incremented by 1 on every ms by HAL_SysTick
+volatile uint32_t g_task_temp_sensor_tick_cnt;
+
+// private functions declaration
+void UART1_SetBaud(uint32_t baud);
+void DS18B20_Write(uint8_t data);
+void DS18B20_Read_temp(void);
+void DS18B20_Read_temp_non_blocking(void);
+void DS18B20_Init(void);
+uint8_t DS18B20_Read(void);
+uint8_t DS18B20_Reset(void);
+
+void UART1_SetBaud(uint32_t baud)
+{
+    huart1.Instance = USART1;
+    huart1.Init.BaudRate = baud;
+    huart1.Init.WordLength = UART_WORDLENGTH_8B;
+    huart1.Init.StopBits = UART_STOPBITS_1;
+    huart1.Init.Parity = UART_PARITY_NONE;
+    huart1.Init.Mode = UART_MODE_TX_RX;
+    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+    if (HAL_HalfDuplex_Init(&huart1) != HAL_OK)
+    {
+        Error_Handler();
+    };
+}
+
+uint8_t DS18B20_Reset(void)
+{
+    uint8_t data = 0xF0;
+    UART1_SetBaud(9600);
+    HAL_UART_Transmit(&huart1, &data, 1, 10);
+
+    if ((HAL_UART_Receive(&huart1, &data, 1, 10) != HAL_OK) || (data == 0xF0))
+    {
+        // initialization failed
+        LOGGER_ERROR("Couldn't read temperature sensor");
+        return 1;
+    }
+
+    UART1_SetBaud(115200);
+    return 0;
+}
+
+void DS18B20_SetResolution(uint8_t resolution)
+{
+    uint8_t config;
+
+    switch(resolution)
+    {
+        case 9:  config = 0x1F; break;
+        case 10: config = 0x3F; break;
+        case 11: config = 0x5F; break;
+        case 12: config = 0x7F; break;
+        default: config = 0x7F;
+    }
+
+    DS18B20_Reset();
+    DS18B20_Write(0xCC); // Send 'Skip ROM' command
+    DS18B20_Write(0x4E); // Send 'write scratchpad' command
+
+    DS18B20_Write(0x00); // TH
+    DS18B20_Write(0x00); // TL
+    DS18B20_Write(config);
+
+    DS18B20_Reset();
+
+    DS18B20_Write(0xCC); // Skip ROM
+    DS18B20_Write(0x48); // Write scratchpad to EEPROM
+}
+
+void DS18B20_Init(void)
+{
+    if (DS18B20_Reset() == 0)
+    {
+        LOGGER_INFO("Temperature sensor initialized successfully");
+    }
+    DS18B20_SetResolution(10);
+    g_DS18B20_state = ST_DS18B20_READY;
+    g_task_temp_sensor_tick = G_TEMP_PERIOD_MS;
+}
+
+void DS18B20_Write(uint8_t data)
+{
+    uint8_t buffer[8];
+
+    for (uint8_t i = 0; i < 8; ++i)
+    {
+        if (data & (1 << i))
+        {
+            buffer[i] = 0xFF;
+        }
+        else
+        {
+            buffer[i] = 0x00;
+        }
+    }
+
+    // This is a blocking call and can wait at most 100ms
+    // TODO: convert to non-blocking call using DMA
+    HAL_UART_Transmit(&huart1, buffer, 8, 10);
+}
+
+// Blocking version
+uint8_t DS18B20_Read(void)
+{
+    uint8_t buffer[8];
+    uint8_t received_value = 0;
+
+    for (uint8_t i = 0; i < 8; ++i)
+    {
+        buffer[i] = 0xFF;
+    }
+
+    HAL_UART_Transmit_DMA(&huart1, buffer, 8);
+    HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8);
+
+    while(b_DS18B20_Received_data == false)
+        ;
+
+    b_DS18B20_Received_data = false;
+
+    for (uint8_t i = 0; i < 8; ++i)
+    {
+        if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+        {
+            received_value |= (1 << i);
+        }
+    }
+
+    return received_value;
+}
+
+void DS18B20_Read_temp(void)
+{
+    DS18B20_Reset();
+    DS18B20_Write(0xCC); // Send 'Skip ROM' command
+    DS18B20_Write(0x44); // Send 'Convert T' command
+
+    DS18B20_Reset();
+    DS18B20_Write(0xCC); // Send 'Skip ROM' command
+    DS18B20_Write(0xBE); // Send 'read scratchpad' command
+
+    Temp_LSB = DS18B20_Read();
+    Temp_MSB = DS18B20_Read();
+
+    uint16_t temp = (Temp_MSB << 8) | Temp_LSB;
+    g_DS18B20_temp = (float) temp / 16.0;
+}
+
+void DS18B20_Read_temp_non_blocking(void)
+{
+    switch (g_DS18B20_state)
+    {
+        case ST_DS18B20_READY:
+            if (0 == g_task_temp_sensor_tick)
+            {
+                // Send start temp conversion command
+                // this needs 96ms to 750ms depending on resolution
+                DS18B20_Reset();
+                DS18B20_Write(0xCC); // Send 'Skip ROM' command
+                DS18B20_Write(0x44); // Send 'Convert T' command
+
+                g_DS18B20_state = ST_DS18B20_BUSY_WAITING_CONV;
+                g_task_temp_sensor_tick = G_DS18B20_CONV_TIME_MS;
+            }
+            else
+            {
+                g_task_temp_sensor_tick--;
+            }
+            break;
+
+        case ST_DS18B20_BUSY_WAITING_CONV:
+            if (0 == g_task_temp_sensor_tick)
+            {
+                DS18B20_Reset();
+                DS18B20_Write(0xCC); // Send 'Skip ROM' command
+                DS18B20_Write(0xBE); // Send 'read scratchpad' command
+
+                if (HAL_OK == HAL_UART_Transmit_DMA(&huart1, buffer, 8))
+                {
+                    if (HAL_OK == HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8))
+                    {
+                        b_DS18B20_Received_data_LSB = true;
+                        g_DS18B20_state = ST_DS18B20_BUSY_WAITING_DMA;
+                        g_task_temp_sensor_tick = G_DS18B20_DMA_TIMEOUT_MS;
+                    }
+                }
+            }
+            else
+            {
+                g_task_temp_sensor_tick--;
+            }
+
+            break;
+
+        case ST_DS18B20_BUSY_WAITING_DMA:
+
+            if (0 == g_task_temp_sensor_tick)
+            {
+                // DMA Timeout, reset conversion
+                g_DS18B20_state = ST_DS18B20_READY;
+                g_task_temp_sensor_tick = G_TEMP_PERIOD_MS;
+                break;
+            }
+            else
+            {
+                g_task_temp_sensor_tick--;
+            }
+
+            if (true == b_DS18B20_Received_data)
+            {
+                b_DS18B20_Received_data = false;
+
+                uint8_t received_value = 0;
+                for (uint8_t i = 0; i < 8; ++i)
+                {
+                    if (g_DS18B20_Received_data_buffer[i] == 0xFF)
+                    {
+                        received_value |= (1 << i);
+                    }
+                }
+
+                if (true == b_DS18B20_Received_data_LSB)
+                {
+                    if (HAL_OK == HAL_UART_Transmit_DMA(&huart1, buffer, 8))
+                    {
+                        if (HAL_OK == HAL_UART_Receive_DMA(&huart1, g_DS18B20_Received_data_buffer, 8))
+                        {
+                            b_DS18B20_Received_data_LSB = false;
+                            Temp_LSB = received_value;
+                            g_task_temp_sensor_tick = G_DS18B20_DMA_TIMEOUT_MS;
+                        }
+                    }
+                }
+                else
+                {
+                    Temp_MSB = received_value;
+                    uint16_t temp = ((Temp_MSB << 8) | Temp_LSB);
+                    g_DS18B20_temp = (float) temp / 16.0;
+                    g_DS18B20_state = ST_DS18B20_READY;
+                    g_task_temp_sensor_tick = G_TEMP_PERIOD_MS;
+                }
+            }
+
+            break;
+
+        default: break;
+    }
+}
+
+void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
+{
+    b_DS18B20_Received_data = true;
+}
+
+void task_temp_sensor_init(void *parameters)
+{
+    LOGGER_INFO("Initializing `task_temp_sensor`...");
+
+    g_task_temp_sensor_tick = G_TASK_SEN_TICK_CNT_INI;
+    DS18B20_Init();
+
+    LOGGER_INFO("Done initializing `task_temp_sensor`");
+}
+
+void task_temp_sensor_update(void *parameters)
+{
+    bool b_time_update_required = false;
+
+    __asm("CPSID i");
+    if (G_TASK_SEN_TICK_CNT_INI < g_task_temp_sensor_tick_cnt)
+    {
+        g_task_temp_sensor_tick_cnt--;
+        b_time_update_required = true;
+    }
+    __asm("CPSIE i");
+
+    while (b_time_update_required)
+    {
+        DS18B20_Read_temp_non_blocking();
+
+        __asm("CPSID i");
+        if (G_TASK_SEN_TICK_CNT_INI < g_task_temp_sensor_tick_cnt)
+        {
+            g_task_temp_sensor_tick_cnt--;
+            b_time_update_required = true;
+        }
+        else
+        {
+            b_time_update_required = false;
+        }
+        __asm("CPSIE i");
+
+    }
+}