<div align="center">

<img src="img/logofiuba.png" width="100%">

**UNIVERSIDAD DE BUENOS AIRES**  
**Facultad de Ingeniería**  
**TA134 - Taller de Sistemas Embebidos**

# Controlador de derretidor de miel

**Martin Klöckner** - [mklockner@fi.uba.ar](mailto:mklockner@fi.uba.ar)

**Fecha:** 31 de mayo de 2026  
**Cuatrimestre de cursada:** Segundo cuatrimestre de 2025

*Trabajo realizado entre marzo y mayo de 2026.*

</div>

<br><br>

En el presente trabajo se diseña e implementa un sistema para el control de un
derretidor eléctrico de miel, reemplazando el sistema original basado en un
termostato de bulbo capilar por un sistema digital. Las principales
características del sistema diseñado son:

- Control de temperatura mediante PID con salida PWM sobre MOSFET.
- Sensor digital de temperatura DS18B20.
- Interfaz local con display, botones, luces indicadores y buzzer.
- Control remoto vía Wi-Fi con interfaz web.
- Reloj de tiempo real con batería de respaldo y temporizador programable.
- Persistencia de parámetros incluso si se pierde la alimentación.

Los resultados demuestran la conveniencia de utilizar un controlador digital por
sobre uno analógico de los equipos comerciales existentes. En las siguientes
secciones se describe el diseño, la implementación y los resultados de las
pruebas realizadas.

<br>

# Índice

- [1. Introducción general](#1-introducción-general)
  - [1.1. Alcance](#11-alcance)
  - [1.2. Trabajos similares y alternativas](#12-trabajos-similares-y-alternativas)
- [2. Introducción específica](#2-introducción-específica)
  - [2.1. Requisitos](#21-requisitos)
  - [2.2. Casos de uso](#22-casos-de-uso)
  - [2.3. Descripción de módulos principales](#23-descripción-de-módulos-principales)
    - [2.3.1. Control principal](#231-control-principal)
    - [2.3.2. Módulo remoto](#232-módulo-remoto)
    - [2.3.3. Sensor de temperatura](#233-sensor-de-temperatura)
    - [2.3.4. Control de temperatura](#234-control-de-temperatura)
    - [2.3.5. Display y adaptador paralelo a serie I2C](#235-display-y-adaptador-paralelo-a-serie-i2c)
    - [2.3.6. Cable y conector IDC](#234-cable-y-conector-idc)
- [3. Diseño e implementación](#3-diseño-e-implementación)
  - [3.1. Hardware del sistema](#31-hardware-del-sistema)
    - [3.1.1. Placa NUCLEO](#311-placa-nucleo)
    - [3.1.2. Sensor DS18B20](#312-sensor-ds18b20)
    - [3.1.3. Módulo ESP-01S](#313-modulo-esp-01s)
    - [3.1.4. Display LCD 16x2 I2C](#314-display-lcd-16x2-i2c)
    - [3.1.5. Control de temperatura](#315-control-de-temperatura)
    - [3.1.6. Luces indicadoras](#316-luces-indicadoras)
    - [3.1.7. Buzzer](#317-buzzer)
    - [3.1.8. Botones](#318-botones)
  - [3.2. Firmware del sistema](#32-firmware-del-sistema)
    - [3.2.1. Ejecutor cíclico](#321-ejecutor-cíclico)
    - [3.2.2. Tarea central](#322-tarea-central)
    - [3.2.3. Tarea para botones](#323-tarea-para-botones)
    - [3.2.4. Tarea para el buzzer](#324-tarea-para-el-buzzer)
    - [3.2.5. Tarea para luces indicadoras](#325-tarea-para-luces-indicadoras)
    - [3.2.6. Tarea para el menu](#326-tarea-para-el-menu)
    - [3.2.7. Tarea para control de temperatura](#327-tarea-para-control-de-temperatura)
    - [3.2.8. Tarea para sensor de temperatura](#328-tarea-para-sensor-de-temperatura)
    - [3.2.9. Tarea para módulo remoto](#329-tarea-para-modulo-remoto)
    - [3.2.10. Medición de tiempo de ejecución](#3210-medición-de-tiempo-de-ejecución)
- [4. Ensayos y resultados](#4-ensayos-y-resultados)
  - [4.1. Pruebas funcionales del hardware](#41-pruebas-funcionales-del-hardware)
  - [4.2. Pruebas funcionales del firmware](#42-pruebas-funcionales-del-firmware)
  - [4.3. Pruebas de integración](#43-pruebas-de-integración)
  - [4.4. Cumplimiento de requisitos](#44-cumplimiento-de-requisitos)
  - [4.5. Comparación con trabajos similares](#45-comparación-con-trabajos-similares)
  - [4.6. Documentación del desarrollo realizado](#46-documentación-del-desarrollo-realizado)
    - [4.6.1. Consumo de corriente](#461-consumo-de-corriente)
    - [4.6.2. Tiempo de ejecución](#462-tiempo-de-ejecución)
    - [4.6.3. Factor de uso de CPU](#463-consumo-de-corriente)
    - [4.6.4. Uso de memorias](#464-uso-de-memorias)
- [5. Conclusiones](#5-conclusiones)
  - [5.1. Resultados obtenidos](#51-resultados-obtenidos)
  - [5.2. Próximos pasos](#52-próximos-pasos)
- [6. Referencias](#6-referencias)

# 1. Introducción general

## 1.1. Alcance

Un derretidor eléctrico de miel es un equipo diseñado para elevar la temperatura
de la miel de forma controlada, con el fin de reducir su viscosidad y facilitar
su manipulación en procesos como envasado, filtrado y bombeo. En la figura 1.1
se muestra un ejemplo de un derretidor eléctrico de miel convencional.

<div align="center">
    <img src="img/derretidor_convencional.png" style="padding: 10px" width="600">
    <p align="center"><em>Figura 1.1: Derretidor de miel convencional.</em></p>
</div>

Los equipos comerciales actuales utilizan un sistema de control basado en un
termostato de bulbo capilar, los cuales ofrecen un control rudimentario, sin
capacidad de programación, monitoreo remoto o registro de datos. Es por esto que
el objetivo del trabajo es diseñar e implementar un controlador digital para un
derretidor eléctrico de miel para tambores, reemplazando el sistema original
basado en un termostato por un sistema digital con mayor control, que permita:

- Control preciso de temperatura.
- Interfaz de usuario local con display y botones.
- Control y monitoreo remoto vía Wi-Fi.
- Programación de ciclos de derretido con temporizador.
- Persistencia de parámetros ante cortes de energía.
- Indicación luminosa y sonora de estados.

El alcance de este proyecto está delimitado al desarrollo, implementación y
validación de un Producto Mínimo Viable (MVP) que demuestre la factibilidad
técnica del controlador digital. Quedan fuera del alcance el diseño de una placa
PCB definitiva, el ensayo en un entorno de producción real con miel, y la
validación térmica exhaustiva del conjunto completo. Estos aspectos se
identificaron como un trabajo futuro para una posterior etapa de
industrialización y comercialización del prototipo.

## 1.2. Trabajos similares y alternativas

No se encontraron productos comerciales que integren todas las funcionalidades
propuestas a un costo accesible en el mercado nacional. Los derretidores de miel
comerciales existentes se limitan a sistemas basados en termostatos, con control
on/off y sin display, conectividad y capacidad de programación.

En el ámbito académico, se identificaron trabajos similares en cuanto al
control de temperatura, como un [horno eléctrico para gastronomía](https://docs.google.com/document/d/1ypnhOz-Gx_ZRbwiI6vEn4dvr7_YqNVnpy5sfgalQAoA/edit)
y un [horno para componentes SMD](https://docs.google.com/document/d/1rQf3P1D7NSb7egpnlkKMTvL_rzy9PuMcMBPcu7NxmQw/edit),
ambos de la misma materia (Sistemas Embebidos, FIUBA). Sin embargo, ninguno
aborda la combinación de control PID, conectividad Wi-Fi con interfaz web, y
temporizador programable en el contexto de derretido de miel.

# 2. Introducción específica

Se desarrolló un sistema de control de temperatura basado en el microcontrolador
STM32F103RB de la placa NUCLEO-F103RB y el sensor de temperatura digital
DS18B20. El sistema lee la temperatura de la miel a traves del sensor y controla
automáticamente el dispositivo de calefacción del derretidor. El calefactor del
derretidor se modela como una resistencia de 12 V y 48 W.

El usuario puede interactuar con el sistema a traves de dos interfaces: una
local, mediante botones, un display, luces indicadoras y un buzzer; y de manera
remota, mediante un navegador web de un dispositivo dentro de la red local del
sistema, accediendo a la pagina proporcionada por el modulo remoto ESP-01S del
sistema.

## 2.1. Requisitos

En la tabla 2.1 se listan los requisitos alcanzados del trabajo, junto con su
descripción correspondiente. En esta tabla no se incluyen requisitos no
alcanzados, los cuales fueron considerados inicialmente durante la definición
del proyecto pero que por restricciones de tiempo no se pudieron alcanzar.

| ID | Requisito                  | Descripción                                                                   |
| :- | :------------------------- | :---------------------------------------------------------------------------- |
|  1 | Control por botones        | El usuario puede establecer y modificar parámetros mediante 4 botones físicos |
|  2 | Control remoto             | El usuario puede controlar el dispositivo de manera remota vía Wi-Fi          |
|  3 | Programación de ciclos     | El usuario puede programar ciclos con hora de inicio y fin                    |
|  4 | Display                    | El sistema muestra el estado actual en un display LCD 16x2                    |
|  5 | LEDs indicadores           | El sistema tiene LEDs para indicar estado de operación                        |
|  6 | Alarma sonora              | El sistema tiene un buzzer para eventos y alarmas                             |
|  7 | Monitoreo en tiempo real   | El sistema muestra temperatura, set point y duty cycle                        |
|  8 | Conectividad Wi-Fi         | El sistema se conecta a redes Wi-Fi para comunicación remota                  |
|  9 | Persistencia de parámetros | El sistema recuerda la última configuración al encender                       |
| 10 | Reloj de tiempo real       | El sistema mantiene la hora incluso sin alimentación                          |

<p align="center"><em>Tabla 2.1: Requisitos del trabajo</em></p>

En la tabla 2.2 se muestran requisitos que quedaron fuera del alcance final del
trabajo debido a restricciones de tiempo y complejidad. Se consideran requisitos
futuros o deseables para una futura iteración del trabajo. 

| ID | Requisito               | Descripción                                        |
| :- | :---------------------- | :------------------------------------------------- |
| 11 | Curvas de temperatura   | El usuario puede definir perfiles de calentamiento |
| 12 | Registro de temperatura | El sistema almacena registro de temperatura        |
| 13 | Límite de temperatura   | El sistema tiene un límite máximo de temperatura   |

<p align="center"><em>Tabla 2.2: Requisitos futuros del trabajo</em></p>

## 2.2. Casos de uso

En las tablas 2.3, 2.4 y 2.5 se ejemplifican algunos casos de uso del derretidor
de miel para cada uno de los modos de operación del sistema.

| Elemento            | Definición                                                                                                                                                                |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Disparador          | Se quiere detener un ciclo de derretido de miel de manera remota                                                                                                          |
| Precondiciones      | El sistema está en modo normal operando el calefactor                                                                                                                     |
| Flujo principal     | El usuario interactúa con la interfaz remota seleccionando la opción detener calefactor, se detiene el calefactor y se cambia a modo de operación en reposo               |
| Flujos alternativos | Se pierde la conexión con el sistema, en caso de ocurrir previo a seleccionar la opción el sistema sigue operando en modo normal, se reintenta la conexión con el usuario |

<p align="center"><em>Tabla 2.3: Caso de uso modo normal</em></p>

| Elemento            | Definición                                                                                                                                                                                                                                                                                                                                           |
| :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Disparador          | Se desea programar un ciclo de derretido para una hora y fecha especifica                                                                                                                                                                                                                                                                            |
| Precondiciones      | El sistema está en modo reposo                                                                                                                                                                                                                                                                                                                       |
| Flujo principal     | El usuario interactúa con la interfaz remota seleccionando la opción programar ciclo, elije entre las opciones disponibles y guarda la configuración. Llegado el momento definido por el usuario se cambia a modo de operación normal, enciendo el calefactor                                                                                        |
| Flujos alternativos | En caso de que se pierda la energía previo a iniciar el ciclo, luego de que se vuelva a energizar el sistema y vuelva a modo reposo (si no hay fallas) el ciclo configurado permanece guardado porque los parámetros se guardan en memoria no volátil, llegado el momento configurado por el ciclo se cambia a modo normal encendiendo el calefactor |

<p align="center"><em>Tabla 2.4: Caso de uso modo reposo</em></p>

| Elemento            | Definición                                                                                                                                                                                                    |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Disparador          | El sistema se energiza                                                                                                                                                                                        |
| Precondiciones      | El sistema se encontraba apagado, desenergizado                                                                                                                                                               |
| Flujo principal     | El sistema inicializa todos los bloques, se comprueba que no haya ciclos de derretido predefinidos para el momento actual, en caso de que los haya se pasa a modo normal, si no los hay se pasa a modo reposo |
| Flujos alternativos | Si hubo un error durante la inicialización de alguna tarea el sistema no se inicializa                                                                                                                        |

<p align="center"><em>Tabla 2.5: Caso de uso modo transición</em></p>

## 2.3. Descripción de módulos principales

### 2.3.1. Control principal

El control principal se implementa en la placa NUCLEO-F103RB, la cual se puede
ver en la figura 2.3.1. Esta placa utiliza un microcontrolador ARM Cortex-M3 de
32 bits, el STM32F103RBT6. En la placa se ejecuta el firmware principal del
sistema, compuesto por un ejecutor cíclico con una pauta establecida de que un
tick nunca supere 1 ms. Este ejecutar cíclico tiene asociado 8 tareas, las
cuales controlan diferentes partes del sistema: 'system', 'buttons', 'buzzer',
'leds', 'menu', 'temp_ctrl', 'temp_sensor' y 'remote'. La comunicación entre
tareas se realiza mediante eventos y una estructura de datos compartida.

<div align="center">
    <img src="img/nucleo_f103rb_views.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.1: Placa NUCLEO F103RB</em></p>
</div>

Esta placa NUCLEO se utilizó exhaustivamente en la materia a lo largo de la
cursada y fue por esto principalmente que se eligió para el desarrollo del
trabajo. 

### 2.3.2. Módulo remoto

Para el control remoto se utilizó el módulo Wi-Fi ESP-01S basado en un
microcontrolador Espressif ESP8266. Este se comunica a través de UART con la
placa NUCLEO para intercambiar comandos con un formato especifico. La elección
se basó en su bajo costo, disponibilidad en el mercado local y capacidad para
actuar como servidor web. En la figura 2.2 se pueden ver imágenes de la placa,
así como también las conexiones que ofrece la misma.

<div align="center">
    <img src="img/esp01s_views.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.2: Modulo ESP-01S</em></p>
</div>

El firmware utilizado en la placa ESP-01S fue desarrollado utilizando librerías
de Arduino a través de PlatformIO. El firmware implementa funciones como la
conexión a una red Wi-Fi fija, un servidor HTTP en el puerto 80 para servir la
interfaz web estática desde el sistema de archivos, un servidor WebSocket en el
puerto 81 para comunicación bidireccional en tiempo real y la comunicación UART
con la placa NUCLEO.

### 2.3.3. Sensor de temperatura

Para medir la temperatura real del liquido, se utilizó el sensor DS18B20 de
Maxim Integrated el cual es un termómetro digital con interfaz OneWire que
ofrece una precisión de 0.5 °C en el rango de -10 °C a 85 °C. Se seleccionó por
su bajo costo, disponibilidad en el mercado local y por tener la precisión
adecuada para la aplicación.

<div align="center">
    <img src="img/ds18b20_views.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.3: Sensor de temperatura DS18B20</em></p>
</div>

La placa NUCLEO no es compatible con el protocolo OneWire por defecto es por
esto que se implementó un "emulador" del protocolo utilizando el periférico UART
de la NUCLEO cambiando dinámicamente la tasa de baudios (9600 baudios para
reset, 96500 baudios para transferencia de datos). Y dado que la NUCLEO lo
permite, se utilizo DMA para la comunicación con el sensor, disminuyendo así el
tiempo de bloqueo del ejecutor cíclico.

### 2.3.4. Control de temperatura

Para controlar la temperatura, se modeló el derretidor eléctrico de miel
utilizando un resistor de 12 V y 48 W, y el control de temperatura mediante un
transistor MOSFET, controlado por modulación de ancho de pulsos (Pulse Width
Modulation, PWM). El sistema regula la temperatura mediante un controlador
Proporcional-Integral-Derivativo (PID) implementado en el firmware, siendo la
señal de referencia a la temperatura establecida por el usuario y el valor leído
de temperatura aquel obtenido mediante el sensor de temperatura.

En la figura 2.4 se muestra, a la izquierda, el encapsulado TO-220 del MOSFET, y
a la derecha, el resistor utilizado para modelar el calefactor del derretidor
eléctrico de miel.

<div align="center">
    <img src="img/temp_ctrl_views.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.4: Dispositivos utilizados para el control de temperatura</em></p>
</div>

El MOSFET es controlado por la señal PWM generada por un timer de la placa
NUCLEO. La frecuencia de conmutación de la señal se estableció en
aproximadamente 500 Hz y el duty cycle se calcula mediante el algoritmo PID
implementado en la tarea 'temp_ctrl'.

### 2.3.5. Display y adaptador paralelo a serie I2C

Para el control local se utilizó un display LCD con interfaz paralelo de 16x2
caracteres, y para disminuir el número de pines usados de la NUCLEO, se utilizó
una adaptador de interfaz paralelo del display a serie I2C para la NUCLEO,
reduciendo el numero de pines necesarios de la NUCLEO de 6 a 2.

En la figura 2.5 se muestra a la izquierda el display LCD de 16x2 caracteres
utilizado y a la derecha el adaptador de interfaz paralela a serie I2C.

<div align="center">
    <img src="img/display_views.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.5: Display LCD y adaptador paralelo a serie I2C</em></p>
</div>

### 2.3.6. Cable y conector IDC

Durante el diseño de hardware que se detallará en la sección siguiente, se
separó el sistema en dos placas perforadas separadas. Por un lado la placa una
placa donde se pueda conectar la NUCLEO y por otro una placa con todos los
módulos y demás bloques que componen al sistema. Para interconectar estas dos
placas perforadas se utilizaron conectores IDC de 20 pines (2 hileras de 10
pines cada una). 

En la figura 2.6 se muestran imágenes de los conectores utilizados, a la
izquierda el conector hembra junto con el cable y a la derecha el conector macho
soldado en ambas placas perforadas.

<div align="center">
    <img src="img/idc.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 2.6: Display LCD y adaptador paralelo a serie I2C</em></p>
</div>

# 3. Diseño e implementación

En la figura 3.1 se muestra el diagrama en bloques con los principales
módulos y conexiones del sistema. Se puede ver que la placa NUCLEO es el
módulo central y luego todos los demás módulos se conectan a este.

<div align="center">
    <img style="padding: 10px" align=center src="img/diagrama_de_bloques.png" width="600">
    <p><em>Figura 3.1: Diagrama en bloques del sistema.</em></p>
</div>

## 3.1. Hardware del sistema

El trabajo se divide en dos placas perforadas experimentales. Estas placas
perforadas se utilizan para unir los módulos, evitando utilizar cables. Las
placas perforadas se conectan entre si a través de un cable IDC de 20 hilos, tal
como se ve en la figura 3.2.

<div align="center">
    <img src="img/conexion_placas_perforadas_TA134.png" style="padding: 10px;" width="700">
    <p align="center"><em>Figura 3.2: Conexión placas perforadas.</em></p>
</div>

La primer placa perforada se muestra en la figura 3.3 y hace de adaptador de los
pines de la placa NUCLEO a cable con conector IDC de 2x10.

<div align="center">
    <img src="img/stm32_nucleo_expansion_board_cropped.png" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 3.3: Placa perforada adaptador NUCLEO a conector IDC 2x10.</em></p>
</div>

La segunda placa perforada, considerada la placa principal, se utilizó para unir
todos los módulos restantes del sistema, como el modulo de acceso remoto, la
bornera para el sensor de temperatura, las luces indicadoras, los botones, el
portapilas para almacenar la pila CR2032, entre otros. En la figura 3.3 se
muestra una vista de como se conectan los módulos dentro de la placa y al
conector IDC.

<div align="center">
    <img src="img/main_perf_board.png" style="padding: 10px" align=center width="400px">
    <p><em>Figura 3.4: Placa perforada principal.</em></p>
</div>

En las figuras 3.5, 3.6 y 3.7 se muestran imágenes de las placas armadas en
placa perforada experimental, como se indicó previamente en las figuras 3.3 y
3.4.

<div align="center">
    <img src="img/vista_sup_placa_con_modulos.jpg" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 3.5: Vista superior de placas con modulos en los zócalos.</em></p>
</div>

<div align="center">
    <img src="img/vista_sup_placa_sin_modulos.jpg" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 3.6: Vista superior de placas sin modulos en los zócalos.</em></p>
</div>

<div align="center">
    <img src="img/vista_inf_placa_sin_modulos.jpg" style="padding: 10px;" width="600">
    <p align="center"><em>Figura 3.7: Vista inferior de placas sin modulos en los zócalos.</em></p>
</div>

### 3.1.1. Placa NUCLEO

Como bien se mencionó, el trabajo se desarrolló utilizando la placa NUCLEO, esta
placa utiliza el procesador STM32F103RBT6 configurado para operar a 64 MHz, ya
que esta frecuencia es la que mejor se adapta a los periféricos utilizados. En
particular los periféricos que se utilizaron son los siguientes:

- I2C1: Conexion con display LCD 16x2.
- USART1: Sensor DS18B20 (modo half-duplex, emulacion de protocolo OneWire).
- USART3: Módulo ESP-01S.
- TIM1_CH1: Salida PWM para control del MOSFET (PA8).
- TIM3_CH1: Salida PWM para buzzer (PA6).
- RTC: Reloj de tiempo real.
- GPIO: Botones (PC13, PA10, PB5, PB4), LEDs (PA5, PB10).
- DMA: Acceso directo a memoria para reducir uso de CPU.

En la figura 3.8 se muestra una imagen de los pines utilizados del
microcontrolador. Luego en la tabla 3.1 se muestran los nombres asignados y las
funciones para los que fueron utilizados.

<div align="center">
    <img src="img/stm32_pinout_view.png" style="padding: 10px" align=center width="500px">
    <p><em>Figura 3.8: Pines utilizados de microcontrolador STM32F103RBT6.</em></p>
</div>

| Pin  | Etiqueta  | Función                        |
| :--- | :-------- | :----------------------------- |
| PA5  | LD2       | LED verde de la placa NUCLEO   |
| PA6  | TIM3_CH1  | Salida PWM buzzer              |
| PA8  | TIM1_CH1  | Salida PWM control temperatura |
| PA9  | USART1_TX | DS18B20                        |
| PC13 | BTN_A     | Botón A                        |
| PA10 | BTN_B     | Botón B                        |
| PB4  | BTN_D     | Botón D                        |
| PB5  | BTN_C     | Botón C                        |
| PB6  | I2C1_SCL  | Linea SCL bus I2C              |
| PB7  | I2C1_SDA  | Linea SDA bus I2C              |
| PB10 | LD3       | LED azul                       |
| PC10 | USART3_TX | ESP-01S Linea TX               |
| PC11 | USART3_RX | ESP-01S Linea RX               |

<p align="center"><em>Tabla 3.1: Pinout del sistema</em></p>

La placa NUCLEO se puede alimentar a través del USB (ST-Link) o por el pin de 5
V externo. Los 5 V externos provienen de un regulador LM7505 ubicado sobre la
placa perforada principal, este regulador recibe alimentación de una fuente de
12 V externa. Para seleccionar que tipo de alimentación se desea utilizar se
debe ajustar la posición del jumper JP5 en la placa NUCLEO, tal como lo indica
la Tabla 8 del manual de usuario de la placa.[1]

### 3.1.2. Sensor DS18B20

El sensor DS18B20 se conectó al USART1 de la placa NUCLEO en modo half-duplex,
es decir, utilizando una sola linea del par TX/RX. De esta forma se puede
aprovechar el periférico emulando el protocolo OneWire. Este protocolo requiere
temporización y niveles específicos, tal como se indica en el manual del sensor
DS18B20.[2]

Para emular el protocolo OneWire utilizando el periférico USART1, se cambian
dinámicamente la tasa en baudios (o baud rate, en inglés) de transmisión. Para
enviar una señal de reset se requiere de como mínimo 480 μs, por lo que enviando
un byte a 9600 baudios de tasa de transmisión, con los respectivos bits de
inicio y fin (resultando en total 10 bits) se tiene un período de
aproximadamente 1.04 ms:

$$T_{bit} = \frac{1}{9600\ baudios} \approx 104\ \mu s \Rightarrow \boxed{T_{byte}
\approx 1.04\ ms}$$

En cambio tomando 96000 baudios de tasa de transmisión, se tiene un
período de bit, y de byte, de aproximadamente $10.4\ \mu s$ y $104\ \mu s$,
respectivamente.

$$T_{bit} = \frac{1}{96000\ baudios} \approx 10.4\ \mu s \Rightarrow
\boxed{T_{byte} \approx 104\ \mu s}$$

Teniendo estas dos tasas de transmisión, enviando el byte hexadecimal 0xF0
(equivalente al numero binario 11110000) a 9600 baudios, se logra un pulso lo
suficientemente parecido al reset de OneWire.

Para transmitir datos, se utiliza la tasa más rápida, de 96000 baudios, y se
envía cada bit de datos en un byte, es decir si se desea enviar un byte de
datos, se deben enviar 8 bytes en la transmisión, un byte por cada dato. Se
transmite el byte 0xFF para representar un bit lógico 1 y el byte 0x00 para
representar un bit lógico 0. Al transmitir el byte 0xFF la línea permanece en
nivel alto durante casi toda la trama, salvo el bit de inicio que es siempre
bajo, esto genera un pulso bajo breve, compatible con la escritura de un bit
lógico 1 del protocolo OneWire. Por otro lado, al transmitir el byte 0x00, la
línea permanece en nivel bajo durante casi toda la trama, a excepción del bit de
fin que es siempre 1, esto produce un pulso bajo de mayor duración, similar al
requerido para transmitir un bit lógico 0.

Por lo tanto, se utiliza la tasa de 9600 baudios únicamente para aproximar el
pulso de reset, el cual posee una duración considerablemente mayor y es
necesario para comenzar al comunicación con el sensor, y la tasa de 96000
baudios para transmitir datos, ya que se generan intervalos temporales
compatibles con los slots de tiempo definidos por el protocolo OneWire.

Y aprovechando aún más el periférico USART1, se realizaron las operaciones de
forma no bloqueante mediante acceso directo a memoria (DMA) de esta forma se
reduce aun más el tiempo de bloqueo del ejecutor cíclico y de uso de la CPU.

### 3.1.3. Módulo ESP-01S

El módulo Wi-Fi ESP-01S se conecta con la placa NUCLEO a través del periférico
USART3 a una tasa de transmisión de 115200 baudios.

Dado que el modulo ESP-01S trabaja con Wi-Fi y requiere, en promedio, entre 150
mA y 250 mA, con picos de corriente durante la transmisión Wi-Fi de hasta 430 mA
a 3,3 V, y dado que la corriente maxima suministrada por el regulador de la
placa NUCLEO es de 500 mA, se decidió utilizar un regulador externo de 3,3 V, el
AIC1117-33PT, montado sobre la misma placa perforada principal, suministrada por
los 12 V de la fuente de tensión externa.

El desarrollo del firmware del modulo ESP-01S no esta dentro del alcance de la
materia, pero se desarrolló de todas formas utilizando PlatformIO y el framework
Arduino. El firmware se desarrolló para que cumpla las siguientes funciones:

- Conexión a una red Wi-Fi fija.
- Servidor HTTP en el puerto 80, sirviendo la página web estática desde el
  sistema de archivos.
- Servidor WebSocket en el puerto 81 para evitar refrescar la pagina web
  constantemente para actualizar la información.
- Sistema de archivos LittleFS.

### 3.1.4. Display LCD 16x2 I2C

El display LCD se conecta al bus I2C1 a través del adaptador paralelo a serie
mencionado previamente. Si bien es posible conectar el display directamente a la
placa NUCLEO sin adaptador, esto requiere del uso de más pines de la placa, es
por esto que se optó por el uso del adaptador I2C. Además al utilizar el
periférico I2C se puede utilizar DMA, reduciendo el tiempo de bloqueo del
ejecutor cíclico y for consiguiente el uso de la CPU.

### 3.1.5. Control de temperatura

La etapa de control de temperatura consiste en un MOSFET IRFZ44N de canal N, el
IRFZ44N, controlado por la señal PWM del TIM1_CH1 (PA8). Dado que el MOSFET es
un dispositivo controlador por tensión, se observó que utilizando directamente
la salida GPIO de la placa NUCLEO para controlar el MOSFET esté elevaba su
temperatura considerablemente. Para solucionar esto se implementó un driver para
controlar el MOSFET con una señal PWM de mayor tensión, en particular 12 V de la
fuente externa. El driver utiliza un transistor TBJ 2N3904 actuando como llave
controlador por la señal PWM de la placa NUCLEO, como se puede ver en el
esquemático de la figura 3.9.

<div align="center">
    <img src="img/npn_inv_mosfet_driver.png" style="padding: 10px" align=center width="700px">
    <p><em>Figura 3.9: Driver para el MOSFET que controla el calefactor.</em></p>
</div>

Este circuito es simple de implementar, pero invierte la señal PWM como se
observa en la figura 3.10. Existe la posibilidad de agregar una etapa adicional
inversora, implementado con otro transistor, pero en este caso no es necesario
ya que se puede invertir la polaridad de la señal PWM desde el firmware de la
placa NUCLEO.

<div align="center">
    <img src="img/npn_inv_mosfet_driver_plot.png" style="padding: 10px" align=center width="700px">
    <p><em>Figura 3.10: Simulación del driver para el MOSFET que controla el calefactor.</em></p>
</div>

El calefactor del derretidor de miel se modeló como una carga resistiva pura,
por lo que se utilizó un resistor de alta potencia de 12 V y 40 W para las
pruebas de laboratorio.

### 3.1.6. Luces indicadoras

Para la luz indicadora, se utilizó un diodo emisor de luz (Light Emitting Diode,
LED) de 5 mm de color verde. Este tipo de LEDs requieren de aproximadamente 20
mA. Se observó que para 20 mA de corriente la luz emitida por el LED es tenue y
que se obtienen mejores resultados con entre 30 mA y 45 mA de corriente.

Para suministrar esta corriente y evitar sobrecargar el regulador de la placa
NUCLEO, se implementó un circuito driver para alimentar al LED con la fuente de
tensión de 12 V externa, controlando solo el estado del led mediante una pequeña
corriente subintrada por la placa NUCLEO. El circuito resultante se muestra en
la figura 3.11.

<div align="center">
    <img src="img/npn_led_driver.png" style="padding: 10px" align=center width="550px">
    <p><em>Figura 3.11: Driver para las luces indicadoras.</em></p>
</div>

El resistor RC se elige de manera tal que la corriente sobre el LED sea de
aproximadamente 45 mA, como se muestra a continuación.

$$RC=\frac{12\text{ V} - 2.2\text{ V}}{45\text{ mA}} \approx 220\ \Omega$$

<!-- El LED 2 LEDs (PA5, PB10) con modos ON, OFF, BLINK (500 ms) y PULSE (250 ms). -->

### 3.1.7. Buzzer

Para el buzzer o parlante se utilizó un zumbador piezoeléctrico pasivo de 12 V.
El termino pasivo implica que se debe suministrar una señal PWM para que este
emita un sonido. Teniendo esto en cuenta, y dado que se requieren de 12 V de
tensión, se replicó el circuito de la figura 3.6 utilizado para controlar el
MOSFET.

<!-- (TIM3_CH1, 1 kHz) con eventos de beep corto (35 ms) y largo (500 ms). -->

### 3.1.8. Botones

Para los botones, se utilizaron 3 tact switch en la placa perforada principal
con los resistores de pull-up internos de la placa NUCLEO.

<!--
4 pulsadores tact switch con pull-up externo. Antirebote por máquina
de estados en firmware (50 ms de filtro).
-->

## 3.2. Firmware del sistema

El firmware de la placa NUCLEO se compone de una aplicación que implementa un
ejecutor cíclico con 8 tareas asociadas. Estas tareas se organizan de acuerdo al
rol que cumplen: actuador, sensor o lógica del sistema.

En la figura 3.12 se muestra un diagrama de bloques de las tareas del sistema y
como interactúan entre ellas. La interacción puede ser a través de eventos o
mediante la estructura global compartida `shared_data`.

<div align="center">
    <img src="img/diagrama_de_bloques_firmware_nucleo_TA134.png" style="padding: 10px" align=center width="650px">
    <p><em>Figura 3.12: Diagrama de bloques firmware del sistema.</em></p>
</div>

<!--
Esta aplicacion tiene como principal caracteristica ser no bloqueante.
-->

### 3.2.1. Ejecutor cíclico

El ejecutor cíclico se implementa en el archivo `app.c`. Este ejecutor ciclico
posee un tick de 1 ms generado por el timer SysTick propio del microcontrolador.
En cada tick, la función `app_update()` recorre secuencialmente las ocho tareas
asociadas, ejecutando tantas iteraciones como ticks estén pendientes. En
operación normal, se cumple que la función `app_update()` no se bloquea por más
de 1 ms, por lo que en cada tick no debería haber más de una operación pendiente
en cada tarea.

En particular del archivo `app.c` se destaca a continuación la lista de tareas
que se asocian a la aplicación. Las tareas son: `task_system`, `task_buttons`,
`task_buzzer`, `task_leds`, `task_menu`, `task_temp_ctrl`, `task_temp_sensor` y
`task_remote`. Cada tarea tiene asociada una función de inicialización y una
función de actualización, denotadas por el sufijo `_init` y `_update`,
respectivamente.

```c
const task_cfg_t task_cfg_list[] = {
    {task_system_init,      task_system_update,      &shared_data},
    {task_buttons_init,     task_buttons_update,     NULL},
    {task_buzzer_init,      task_buzzer_update,      NULL},
    {task_leds_init,        task_leds_update,        NULL},
    {task_menu_init,        task_menu_update,        &shared_data},
    {task_temp_ctrl_init,   task_temp_ctrl_update,   &shared_data},
    {task_temp_sensor_init, task_temp_sensor_update, &shared_data},
    {task_remote_init,      task_remote_update,      &shared_data},
};
```

La función de actualización de cada tarea sigue el mismo patrón: consulta su
contador de ticks (incrementado en cada tick de `SysTick`) y si hay ticks
pendientes, se decrementa el contadora en una unidad y se ejecuta su máquina de
estados o lógica correspondiente, si no hay ticks pendientes no hace nada.

Las tareas se comunican entre sí mediante dos mecanismos: eventos, a través de
buffers circulares con una interfaz dedicada para cada tarea; o mediante la
estructura global compartida `shared_data`. Que mecanismo utiliza cada tarea se
puede observar en la figura 3.12, en la cual las flechas con lineas punteadas
indican el mecanismo de acceso a la variable compartida y las flechas con lineas
continuas indican el mecanismo de eventos.

### 3.2.2. Tarea central

La tarea central, `task_system`, gestiona la lógica del sistema y la máquina de
estados principal. En la figura 3.13 se muestra un diagrama de estados de la
maquina que implementa la tarea. Este diagrama es una versión simplificada de la
lógica que se implementa en la tarea, ya que no se muestran los eventos que se
envían a otras tareas, pero sirve para mostrar como se cambia la funcionalidad
de los botones de acuerdo al estado.

<div align="center">
    <img src="img/system_statechart.png" style="padding: 10px" align=center width="800px">
    <p><em>Figura 3.13: Diagrama de estados de tarea central. Version simplificada.</em></p>
</div>

Se tienen los siguientes estados:

- `ST_SYS_IDLE`: Estado de reposo, se muestran varios parámetros en el display,
  tal como el estado del calefactor, la temperatura actual, la temperatura
  deseada y si hay un timer programado. Este estado también contempla que el
  calefactor esté activo, lo que puede resultar confuso. Un mejor nombre quizás
  hubiese sido `ST_SYS_MAIN`.
- `ST_SYS_CLOCK_SET`: Configuración de hora del reloj de tiempo real.
- `ST_SYS_TEMP_SET`: Ajuste de temperatura deseada.
- `ST_SYS_TIMER_SET_STATUS`: Habilitación/deshabilitación del timer.
- `ST_SYS_TIMER_SET_START`: Configuración de hora de inicio del timer.
- `ST_SYS_TIMER_SET_END`: Configuración de hora de fin del timer.

Además en esta tarea se gestiona:

- Persistencia en flash: Utiliza una página completa (1024 bytes) en la
  dirección `0x0801FC00` como emulación EEPROM. Los valores se escriben en
  direcciones contiguas para reducir el desgaste, borrando la página solo cuando
  está llena (512 escrituras).
- Temporizador programable: Si el timer está activo, en cada segundo se compara
  la hora actual del RTC con los límites configurados. Si `end_hour > start_hour`
  (mismo día) o `end_hour < start_hour` (cruce de medianoche) se activa o
  desactiva el calefactor automáticamente.

### 3.2.3. Tarea para botones

En la tarea `task_buttons` se implementa una máquina de estados de anti-rebote
para cada uno de los botones. En la figura 3.14 se muestra un diagrama de
estados de la maquina.

<div align="center">
    <img src="img/button_statechart.png" style="padding: 10px" align=center width="700px">
    <p><em>Figura 3.14: Diagrama de estados para botones.</em></p>
</div>

Al detectar una pulsación válida (flanco ascendente o descendente confirmado) se
envía un evento a `task_system` y, aunque no se muestra en la figura 3.14, se
envían eventos directamente a `task_buzzer` para que inmediatamente luego de
presionar el botón se active el buzzer, sin interactuar con la tarea central
`task_system`. Esto se observa también en el diagrama de bloques del firmware de
la figura 3.12.

### 3.2.4. Tarea para el buzzer

En la tarea `task_buzzer` se controla el buzzer generando una señal PWM de 1
kHz. Esta tarea recibe eventos para generar beeps cortos (de 35 ms para
pulsación de botón) o largos (de 500 ms para activación/desactivación del
calefactor).

Para controlar el buzzer se implementa una maquina de estados con los estados
`ST_BUZ_XX_OFF` y `ST_BUZ_XX_ON` con auto-apagado por timeout, tal como se
observa en la figura 3.15.

<div align="center">
    <img src="img/buzzer_statechart.png" style="padding: 10px" align=center width="600px">
    <p><em>Figura 3.15: Diagrama de estados de buzzer.</em></p>
</div>

### 3.2.5. Tarea para luces indicadoras

En la tarea `task_leds` se controlan las luces indicadoras o LEDs (LD2, LD3)
permitiendo los modos: encendido, apagado, intermitente y un único pulso. Para
esto se implementa la maquina de estados cuyo diagrama de estados se muestra en
la figura 3.16, con los siguientes estados:

- `ST_LED_XX_OFF`: LED apagado.
- `ST_LED_XX_ON`: LED encendido fijo.
- `ST_LED_XX_BLINK_ON` / `ST_LED_XX_BLINK_OFF`: Parpadeo cada 500 ms.
- `ST_LED_XX_PULSE`: Encendido por 250 ms y luego apagado.

<div align="center">
    <img src="img/led_statechart.png" style="padding: 10px" align=center width="800px">
    <p><em>Figura 3.16: Diagrama de estados de luces indicadoras.</em></p>
</div>

El modo intermitente se utiliza para cuando el calefactor está activo, indicando
visualmente el estado de operación. Cuando el calefactor esta inactivo las luces
permaneces apagadas.

### 3.2.6. Tarea para el menú

La tarea `task_menu`, gestiona la actualización del display LCD 16x2 según el
estado actual del sistema. Se implementa también una maquina de estados similar
a la implementada para el sistema, con estados similares, de manera tal que cada
estado del sistema tiene su correspondiente estado del menú y cada estado del
menú define su contenido del display. En la figura 3.17 se muestran diferentes
contenidos del display para diferentes estados.

Por ejemplo en estado reposo (estado del sistema `ST_SYS_IDLE`) con el
calefactor apagado y un timer programado, como se muestra en la figura 3.17(b),
en la primer linea se muestra el estado del calefactor ("Off"), y en la segunda
linea el estado del timer ("[P]" si activo, "   ", si no), la temperatura
actual, la temperatura deseada (entre paréntesis) y la unidad de la temperatura.

<div align="center">

<table>

<tr>
<td align="center">
<img src="img/lcd/lcd_off.png" width="350px"><br>
<em>(a) Calefactor apagado.</em>
</td>

<td align="center">
<img src="img/lcd/lcd_off_prog.png" width="350px"><br>
<em>(b) Calefactor apagado con timer programado.</em>
</td>
</tr>

<tr>
<td align="center">
<img src="img/lcd/lcd_on.png" width="350px"><br>
<em>(c) Calefactor encendido con timer programado.</em>
</td>

<td align="center">
<img src="img/lcd/lcd_clock_set.png" width="350px"><br>
<em>(d) Configuración de reloj.</em>
</td>
</tr>

<tr>
<td align="center">
<img src="img/lcd/lcd_temp_set.png" width="350px"><br>
<em>(e) Configuracion de temperatura deseada.</em>
</td>

<td align="center">
<img src="img/lcd/lcd_timer_set.png" width="350px"><br>
<em>(f) Configuracion de encendido/apagado de timer.</em>
</td>
</tr>

<tr>
<td align="center">
<img src="img/lcd/lcd_timer_set_start.png" width="350px"><br>
<em>(g) Configuracion de inicio de timer.</em>
</td>

<td align="center">
<img src="img/lcd/lcd_timer_set_end.png" width="350px"><br>
<em>(h) Configuracion de fin de timer.</em>
</td>
</tr>

</table>

<em>Figura 3.17: Interfaces mostradas en el display LCD 16x2.</em>
</div>

La comunicación con el LCD es asíncrona: las operaciones se encolan y se
procesan en cada tick de la tarea mediante `display_i2c_async_tick()`.

### 3.2.7. Tarea para control de temperatura

En la tarea `task_temp_ctrl` se implementa un controlador proporcional, integral
y derivativo (PID) para regular la temperatura. Se toma como señal de referencia
el punto de temperatura deseada, y como señal de error la diferencia entre la
señal de referencia y la temperatura actual leída por el sensor.

En particular, la sección de código que implementa el controlador PID se muestra
a continuación.

```c
p_pid->error = temp_set_point - temp_sensor;
p_pid->pid_p = error * Kp;
p_pid->pid_i = (pid_i + (error * dt)) * Ki;
p_pid->pid_d = ((error - prev_error) / dt) * Kd;
output = clampf(pid_p + pid_i + pid_d, 0.0f, 100.0f);
```

Siendo las constantes proporcionales, integrales y derivativas, `Kp`, `Ki` y
`Kd`, respectivamente, las que se muestran a continuación:

- Kp = 40,0
- Ki = 0,75
- Kd = 0,01
- dt = 250 ms

La salida del controladora (0 % a 100 %) se asigna directamente al ciclo de
trabajo del PWM que controla el calefactor a través de la variable compartida
por las tareas `shared_data`. Si el calefactor está deshabilitado, se fuerza el
ciclo de trabajo a 0 %.

### 3.2.8. Tarea para sensor de temperatura

La tarea `task_temp_sensor` gestiona la lectura asíncrona del sensor DS18B20.
Cada 1 segundo inicia una secuencia de comandos:

1. Reset (cambio a 9600 baudios + pulso de presencia).
2. `SKIP_ROM` + `CONVERT_T` (inicia conversión).
3. Espera 100 ms (tiempo de conversión aproximado para resolución de 9 bits).
4. Reset + `SKIP_ROM` + `READ_SCRATCHPAD`.
5. Lectura de bytes LSB y MSB.
6. Conversion de los bytes leídos a temperatura real y almacenamiento en
   estructura compartida `shared_data`.

Todas las operaciones se encolan y ejecutan mediante DMA, con callbacks que
indican la finalización de transmisión/recepción.

### 3.2.9. Tarea para módulo remoto

En la tarea `task_remote` se administra la comunicación con el módulo ESP-01S a
través de USART3. Se implementa un protocolo propio basado en comandos de un
byte (caracteres 'A' a 'F') con parámetros adicionales según el comando.

Comandos recibidos desde el ESP-01S:

| Comando | Función                                    | Respuesta                                                                               |
| :------ | :----------------------------------------- | :-------------------------------------------------------------------------------------- |
| 'A'     | Solicitar estado completo                  | 'A' + main_output + system_time + timer_status + timer_params(4B) + temp_now + temp_set |
| 'B'     | Toggle calefactor                          | 'B'                                                                                     |
| 'C'     | Toggle timer                               | 'C'                                                                                     |
| 'D'     | Set timer (start_h, start_m, end_h, end_m) | 'D'                                                                                     |
| 'E'     | Solicitar temperatura                      | 'E' + temp_now + temp_set                                                               |
| 'F'     | Set temperatura deseada                    | 'F' + temp_set_point                                                                    |

Comandos enviados al ESP-01S periódicamente cada 1 segundo:

| Comando | Función                | Datos                     |
| :------ | :--------------------- | :------------------------ |
| 'E'     | Actualizar temperatura | 'E' + temp_now + temp_set |

La recepción se realiza por interrupción (`HAL_UART_RxCpltCallback`) con
encolado en un buffer circular. Cada vez que se recibe un byte se encola
automáticamente, para luego ser procesado.

La transmisión utiliza DMA para no bloquear el ejecutor cíclico, para esto se
implementa un buffer circular similar al de recepción. En este buffer circular
se encolan los bytes que se desean enviar y mientras la cola no esté vacía, y
siempre que DMA haya terminado, se enviando los bytes.

<div align="center">
<table>

<tr>
<td align="center">
<img src="img/pagina_web_dark.png" width="400px"><br>
<em>(a) Esquema de colores oscuro.</em>
</td>

<td align="center">
<img src="img/pagina_web_light.png" width="400px"><br>
<em>(b) Esquema de colores claro.</em>
</td>

</tr>

</table>

<p><em>Figura 3.18: Pagina web del modulo remoto. Esquema de colores adaptado al
dispositivo.</em></p>

</div>

### 3.2.10. Medición de tiempo de ejecución

En el ejecutor cíclico se mide el tiempo de ejecución de cada tarea y del ciclo
completo mediante el contador de ciclos del DWT. Por cada tarea se mide:

- `WCET`: Peor tiempo de ejecución desde que se inicializa el sistema.
- `WCET_interval`: Peor tiempo de ejecución en un intervalo de 10 segundos.
- `runtime_us`: Tiempo total del ciclo actual.
- `runtime_us_mean`: Promedio sobre 1000 muestras (1 segundo).

Los resultados se pueden consultar mediante la consola de semi-hosting, lo que
permite caracterizar temporalmente el sistema sin afectar los tiempos de
ejecución.

# 4. Ensayos y resultados

En esta sección se evaluará el sistema desarrollado, tanto el firmware como el
hardware, en aspectos como consumo de corriente, memoria, factor de uso de CPU,
entres otras cosas. De esta forma, se verificará si las decisiones tomadas para
el diseño fueron correctas y si se cumplen los requisitos. En caso de que se
cumplan los requisitos, se comparará el sistema desarrollado con proyectos
similares.

## 4.1. Pruebas funcionales del hardware

| Ensayo                          | Resultado                            | Estado   |
| :------------------------------ | :----------------------------------- | :------: |
| Alimentación y regulación 3,3 V | Tensión estable en placa NUCLEO      | Correcto |
| Comunicación I2C con LCD        | Inicialización y escritura correctas | Correcto |
| Lectura DS18B20                 | Detección y lectura de temperatura   | Correcto |
| Comunicación UART con ESP-01S   | Intercambio de datos bidireccional   | Correcto |
| Control PWM sobre MOSFET        | Variación de ciclo de trabajo        | Correcto |
| Buzzer PWM                      | Generación de tono a 1 kHz           | Correcto |
| LEDs                            | Estados ON/OFF/BLINK correctos       | Correcto |
| Botones con antirebote          | Eventos limpios sin rebotes          | Correcto |

<p align="center"><em>Tabla 4.1: Pruebas funcionales de hardware.</em></p>

## 4.2. Pruebas funcionales del firmware

| Ensayo                        | Resultado                                   | Estado   |
| :---------------------------- | :------------------------------------------ | :------: |
| Ejecutor cíclico (1 ms tick)  | Tiempo de ejecucion menor a 1 ms            | Correcto |
| Máquina de estados de sistema | Transiciones correctas en todos los estados | Correcto |
| Algoritmo PID                 | Cálculo con valores esperados               | Correcto |
| Lectura DS18B20 asíncrona     | Actualización cada 1 segundo sin bloqueo    | Correcto |
| Comunicación UART remota      | Envío/recepción de comandos A-F             | Correcto |
| Persistencia en flash         | Lectura/escritura en página dedicada        | Correcto |
| RTC con respaldo              | Mantenimiento de hora sin alimentación      | Correcto |
| Antirebote de botones         | Filtro de 50 ms sin falsos positivos        | Correcto |

<p align="center"><em>Tabla 4.2: Pruebas funcionales de firmware.</em></p>

## 4.3. Pruebas de integración

Se validó la interacción completa del sistema:

1. Ciclo completo local: Botón enciende calefactor, PID regula temperatura,
   display muestra valores, LEDs parpadean, buzzer suena.
2. Ciclo completo remoto: Web solicita status, ESP-01S envía comando 'A', NUCLEO
   responde con estado, WebSocket actualiza interfaz web.
3. Temporizador: Configuración de timer, cambio automático de estado al alcanzar
   la hora programada.
4. Persistencia de parámetros: Configuración de la temperatura deseada, corte de
   energía, restauración correcta al encender.

En el siguiente [video](https://www.youtube.com/watch?v=ZpNlU7789YU) se presenta
el sistema y se muestran las pruebas funcionales. En primer lugar, se realiza la
configuración de parámetros de manera local y remota. Luego, se verifica la
persistencia de parámetros al perder la alimentación. Por último, se hace una
prueba del sistema calentando agua desde 19 °C a 30 °C en un vaso.

Como parte de las pruebas de integración, se utilizó un analizador lógico
(Saleae) para verificar la comunicación mediante el protocolo UART entre la
placa NUCLEO y el módulo ESP-01S, así como también la comunicación mediante el
protocolo OneWire entre la placa NUCLEO y el sensor de temperatura DS18B20.

## 4.4. Cumplimiento de requisitos

| ID   | Requisito                  | Estado          |
| :--- | :------------------------- | :-------------- |
| 1    | Control por botones        | Implementado    |
| 2    | Control remoto             | Implementado    |
| 3    | Programación de ciclos     | Implementado    |
| 4    | Curvas de temperatura      | No implementado |
| 5    | Display                    | Implementado    |
| 6    | LEDs indicadores           | Implementado    |
| 7    | Alarma sonora              | Implementado    |
| 8    | Monitoreo en tiempo real   | Implementado    |
| 9    | Conectividad Wi-Fi         | Implementado    |
| 10   | Registro de temperatura    | No implementado |
| 11   | Límite de temperatura      | Implementado    |
| 12   | Persistencia de parámetros | Implementado    |
| 13   | Reloj de tiempo real       | Implementado    |

<p align="center"><em>Tabla 4.6: Estado de cumplimiento de requisitos propuestos
inicialmente.</em></p>

Notas sobre requisitos no implementados:

- Requisito 4 (curvas de temperatura): No implementado por restricciones de
  tiempo. Requeriría una interfaz de usuario más compleja y un algoritmo PID más
  sofisticado que el actual.
- Requisito 10 (registro de temperatura): No implementado por restricciones de
  tiempo.

## 4.5. Comparación con trabajos similares

En la tabla 4.7 se presentan las principales diferencias entre el sistema
desarrollado y los productos y proyectos académicos mencionados previamente.

| Característica         | Derretidor comercial  | Horno gastronomía | Horno SMD   | Este trabajo |
| :--------------------- | :-------------------- | :---------------- | :---------- | :----------- |
| Control de temperatura | On/off con termocupla | PID digital       | PID digital | PID digital  |
| Control remoto         | No                    | No                | No          | Si           |
| Display                | No                    | Sí                | Sí          | Si           |
| Programación de ciclos | No                    | No                | No          | Sí           |
| Persistencia           | No                    | No                | No          | Sí           |
| RTC                    | No                    | No                | No          | Sí           |

<p align="center"><em>Tabla 4.7: Comparación con sistemas similares.</em></p>

## 4.6. Documentación del desarrollo realizado

En esta sección se presentan los resultados de las mediciones de consumo de
corriente, tiempos de ejecución, factor de uso de CPU y uso de memoria.

### 4.6.1. Consumo de corriente

Las mediciones de consumo se realizaron en primer lugar sobre el conjunto NUCLEO
y periféricos, luego sobre el calefactor.

| Componente                  | Tension [V]  | Corriente [mA]  |
| :-------------------------- | -----------: | --------------: |
| NUCLEO                      | 5            | 31              |
| ESP-01S (conectado, sin TX) | 3,3          | 68              |
| ESP-01S (transmitiendo)     | 3,3          | 210             |
| Buzzer                      | 12           | 34              |
| Luces indicadoras           | 12           | 52              |
| Calefactor                  | 12           | 2600            |

<p align="center"><em>Tabla 4.3: Consumo de corriente del sistema.</em></p>

La placa NUCLEO consume menos de 100 mA a 5 V en operación normal, lo cual es
menor al límite de 500 mA de un puerto USB estándar.

### 4.6.2. Tiempo de ejecución

Se midió el tiempo de ejecución de cada tarea utilizando el DWT. Mientras se
realizaban las mediciones se presionaron multiples botones, navegando por
diferentes interfaces, de manera de obtener el peor tiempo de ejecucion posible.
En la tabla 4.4 se muestran los tiempos de ejecucion obtenidos de cada tarea y
el total para el ejecutor ciclico. Denotando $M_{i}$ al peor tiempo de ejecucion
en un intervalo de 10 segundos y $C_{i}$ al peor tiempo de ejecución total,
desde que se inicializa el sistema.

| Tarea              | $M_{i}\ [\mu s]$ | $C_{i}\ [\mu s]$ |
| :----------------- | ---------------: | -------------: |
| `task_system`      | 5                | 5              |
| `task_buttons`     | 13               | 13             |
| `task_buzzer`      | 4                | 219            |
| `task_leds`        | 6                | 6              |
| `task_menu`        | 6                | 140            |
| `task_temp_ctrl`   | 4                | 5              |
| `task_temp_sensor` | 33               | 33             |
| `task_remote`      | 4                | 94             |
| **Total**          | **75**           | **515**        |

<p align="center"><em>Tabla 4.4: Tiempo de ejecución aproximado por tarea.</em></p>

<!--
En la figura 4.1 se muestra la evolución del WCET del sistema a lo largo del tiempo.

<div align="center">
    <img src="img/g_app_WCET_without_DMA.png" width="80%">
    <p><em>Figura 4.1: WCET del sistema sin contar transfers DMA</em></p>
</div>

<div align="center">
    <img src="img/g_app_WCET_DMA.png" width="80%">
    <p><em>Figura 4.2: WCET del sistema con transfers DMA</em></p>
</div>

<div align="center">
    <img src="img/g_app_runtime_us_mean.png" width="80%">
    <p><em>Figura 4.3: Tiempo de ejecución promedio (1000 muestras)</em></p>
</div>
-->

### 4.6.3. Factor de uso de CPU

Utilizando la expresión clásica de sistemas en tiempo real, se define el factor
de uso $U$ como la sumatoria del peor tiempo de ejecucion de cada tarea $C_{i}$
dividido el tiempo de un tick del ejecutor ciclico $T$ (1 ms).

$$U = \sum_{i=1}^{n} \frac{C_i}{T} = \frac{515\,\mu\text{s}}{1000\,\mu\text{s}} = 51,5\\%$$

El factor de uso resultante de 51,5\% se mide en el peor caso posible.
Tomando el tiempo de ejecucion en un intervalo de 10 segunddos se tine un factor
de uso de CPU aproximado de 7,5\%.

<!--
| Tarea            | $C_i$ [us] | $T$ [us] | $C_i/T$ |
| :--------------- | ---------: | -------: | ------: |
| Todas (conjunto) |        515 |     1000 |   0.368 |

<p align="center"><em>Tabla 4.5: Factor de uso de CPU</em></p>

En ambos casos se tiene un amplio margen para futuras extensiones, por lo que se
confirma que el microcontrolador STM32F103RBT6 es adecuado para este proyecto.
-->

### 4.6.4. Uso de memorias

El uso de memoria del firmare se reporta al momento de realizar la compilación.
La salida del programa se muestra a continuación.

```
   text   data    bss     dec     hex   filename
  64648    276   5616   70540   1138c   tdse-tf_3-02.elf
```

Por lo tanto se tiene:

- Flash: 64648 bytes + 276 bytes = 64924 bytes (~50,7 % de 128 KB).
- RAM: 5616 bytes + 276 bytes = 5892 bytes (~29,4 % de 20 KB).

# 5. Conclusiones

En esta sección se presentan las conclusiones generales del proyecto de acuerdo
con las etapas de desarrollo de firmware y hardware, y los resultados obtenidos.

Se condensan los hallazgos más significativos del Producto Mínimo Viable (MVP) y
se determina en qué medida el trabajo implementado responde al problema de
ingeniería inicialmente planteado, abriendo camino para las líneas de trabajo
futuro.

## 5.1. Resultados obtenidos

Los principales aportes del trabajo realizado son:

1. Diseño completo de un sistema embebido funcional para control de temperatura
   con conectividad Wi-Fi y múltiples interfaces de usuario.
2. Implementación de un ejecutor cíclico con ocho tareas, máquinas de estado y
   medición de WCET, demostrando la factibilidad temporal del diseño (U < 52 %
   en el peor caso).
3. Comunicación remota funcional mediante ESP-01S con WebSocket, permitiendo
   control y monitoreo desde cualquier dispositivo con navegador web.
4. Control PID de temperatura implementado con éxito, con parámetros ajustables
   y salida PWM sobre MOSFET.
5. Persistencia de configuración en flash con manejo de desgaste por escritura
   en direcciones contiguas.

El sistema cumple 11 de los 13 requisitos inicialmente planteados, con los dos
restantes identificados como mejoras para versiones futuras.

## 5.2. Próximos pasos

- Implementar perfiles de temperatura programables (curvas multi-paso).
- Agregar registro histórico de temperatura en memoria externa.
- Migrar a una placa PCB dedicada en lugar de NUCLEO + protoboard.
- Agregar modos de calibración para el sensor DS18B20.
- Unificar las implementaciones de colas en un módulo genérico.
- Implementar exclusión mutua entre interfaz local y remota, es decir, que no se
  puedan utilizar al mismo tiempo.
- Permitir un único usuario por vez en la interfaz remota.
- Agregar modo de bajo consumo (Sleep/Stop) para ahorro energético.
## 6. Referencias

1. STMicroelectronics, "UM1724 User manual - STM32 Nucleo-64 boards (MB1136)"
    Rev. 17, 2025. [En linea]. Disponible en:
    [https://www.st.com/resource/en/user_manual/um1724-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf](https://www.st.com/resource/en/user_manual/um1724-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf)

2. Analog Devices, "DS18B20 - Programmable Resolution 1-Wire Digital
   Thermometer," Rev. 6, ago. 2019. [En linea]. Disponible en:
   [https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf](https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf)

