INFORME DE PROYECTO

Dashboard de Monitoreo de Sensores en Tiempo Real
Desarrollo en C++ y Qt6

Asignatura: Diseño y Programación Orientados a Objetos

Profesor: Agustín González Valenzuela

Estudiantes: Valentina Soto - Julián Nuñez - Vicente Mujica - Vicente Andrade

Fecha: 1 de Julio 2026

Tabla de Contenidos

1. Descripción del Problema

El monitoreo de sensores en procesos industriales es una tarea crítica que, en ciertos entornos, se realiza de forma tal que no permite la visualización histórica ni la lectura directa de métricas de interés.

El presente proyecto propone una interfaz gráfica de usuario que permite visualizar en tiempo real la temperatura de múltiples sensores, graficando su evolución histórica y ofreciendo estadísticas (mínimo, máximo y promedio histórico), convirtiendo el monitoreo en una experiencia intuitiva.

2. Análisis del Problema

El sistema HMI Sensores se enmarca en el contexto del control y monitoreo de procesos donde la temperatura es una variable de control fundamental.

Elementos que participan en el sistema

ElementoDescripción
Sensores de temperaturaDispositivos físicos (o simulados) que miden la temperatura en distintos puntos del proceso. En el prototipo se definieron tres canales: Ambiente (18-25 °C), Proceso (60-80 °C) y Crítico (90-110 °C).
Fuente de datosPuede ser un simulador que genera valores pseudoaleatorios mediante una función senoidal con ruido, o un puerto serial que recibe datos en formato CSV desde un dispositivo externo.
Interfaz gráfica (HMI)Componente visual que presenta las lecturas, gráficos de evolución temporal y estadísticas consolidadas.
Usuario operadorPersona que interactúa con la interfaz para seleccionar sensores, cambiar la fuente de datos y visualizar la información.

Límites del sistema

Interacción con el medio externo

El sistema interactúa con el mundo exterior a través del puerto serial, canal por el que eventualmente llegan los datos de sensores conectados a un microcontrolador. Cuando se utiliza el modo simulador, la aplicación es completamente autonómica y no requiere conexión externa alguna.

3. Definición de Requerimientos

Caso de Uso 1: Visualizar datos simulados PRUEBA PRINCIPAL

Actor principalOperador del sistema
Precondiciones
  • La aplicación debe estar compilada y ejecutándose en el entorno local.
  • No se requiere conexión a dispositivos externos.
Flujo principal
  1. El operador inicia la aplicación.
  2. El sistema presenta por defecto la pestaña de "Simulador" como fuente de datos activa.
  3. El sistema inicia la generación automática de datos simulados cada 500 ms para los tres sensores (Ambiente, Proceso y Crítico).
  4. El operador visualiza en el panel izquierdo las tarjetas de cada sensor con su valor actualizado.
  5. El operador visualiza en el panel derecho el gráfico de línea temporal del sensor seleccionado por defecto (Ambiente).
  6. El sistema actualiza las estadísticas (MIN, MAX, AVG) en la barra inferior del gráfico.
Postcondiciones
  • Los datos se muestran actualizados en la interfaz.
  • El gráfico refleja la evolución temporal de las lecturas.
Simulador activo con tres sensores

Figura 3: Aplicación con simulador activo mostrando los tres sensores y el gráfico en tiempo real.

Caso de Uso 2: Seleccionar un sensor para visualizar su gráfico PRUEBA SECUNDARIA

Actor principalOperador del sistema
Precondiciones
  • La aplicación debe estar en ejecución recibiendo datos (simulador o serial).
  • Debe existir al menos un sensor configurado en el sistema.
Flujo principal
  1. El operador hace clic en una de las tarjetas de sensor en el panel izquierdo (por ejemplo, "Proceso").
  2. El sistema resalta visualmente la tarjeta seleccionada con un borde del color correspondiente al sensor.
  3. El sistema restablece el gráfico: limpia los puntos anteriores del eje X.
  4. El sistema cambia el color de la línea del gráfico al color asignado al sensor seleccionado.
  5. El sistema restablece las estadísticas (MIN, MAX, AVG) a valores iniciales.
  6. A partir de ese momento, el gráfico muestra exclusivamente los datos del sensor seleccionado.
Postcondiciones
  • El gráfico muestra la evolución del sensor seleccionado.
  • Las estadísticas corresponden al sensor seleccionado.
Sensor Proceso seleccionado

Figura 4: Sensor "Proceso" seleccionado, con gráfico verde y estadísticas actualizadas.

Caso de Uso 3: Cambiar la fuente de datos a un puerto serial

Actor principalOperador del sistema
Precondiciones
  • La aplicación debe estar en ejecución.
  • Debe existir un dispositivo serial conectado al equipo (por ejemplo, un Arduino con sensores de temperatura).
  • El operador debe conocer el nombre del puerto COM al que esta conectado el dispositivo.
Flujo principal
  1. El operador selecciona la opcion "Serial" en el panel de controles del panel izquierdo.
  2. El operador selecciona el puerto COM correspondiente en el menú desplegable de puertos disponibles.
  3. El operador presiona el boton "Conectar".
  4. El sistema detiene la fuente de datos anterior (simulador) y establece la conexión con el puerto serial seleccionado.
  5. El sistema comienza a recibir líneas de datos en formato CSV (por ejemplo: "23.5,72.1,95.3") y las distribuye a los tres sensores.
  6. El sistema actualiza las tarjetas, el gráfico y las estadísticas con los datos recibidos.
  7. El indicador de estado cambia a "Serial: [nombre del puerto]" con un color azul.
Postcondiciones
  • La fuente de datos activa es el puerto serial.
  • Los datos mostrados provienen del dispositivo externo conectado.
Fuente serial activa

Figura 5: Fuente serial activa con indicador azul y datos recibidos.

4. Diseño

Arquitectura general

El sistema sigue un patrón de arquitectura basado en componentes con una interfaz abstracta que permite el intercambio de fuentes de datos sin modificar la lógica de presentación. La separación de responsabilidades se logra mediante el patrón Strategy, donde la clase MainWindow delega la obtención de datos a un objeto que implementa la interfaz IDataSource.

La arquitectura se compone de las siguientes capas:

Descripción de clases principales

ClaseAtributos claveMétodos claveResponsabilidad
SensorChannel m_name, m_min, m_max, m_color, m_currentValue, m_phase name(), color(), currentValue(), update(), setValue() Modela un canal de sensor individual. El método update() genera un nuevo valor simulado usando una función senoidal con fase acumulativa y ruido aleatorio.
IDataSource (interfaz sin atributos) start(), stop(), sensorCount(), sensor() Define el contrato que toda fuente de datos debe cumplir. Permite que MainWindow trabaje con cualquier implementación sin acoplamiento directo.
DataSimulator m_timer, m_sensors start(), stop(), sensorCount(), sensor(), onTick() Genera datos simulados a intervalos regulares (500 ms). En cada tick, actualiza todos los sensores y emite la señal dataUpdated().
SerialSource m_port, m_sensors, m_buffer setPort(), start(), stop(), sensorCount(), sensor(), onDataReady() Recibe datos desde un puerto serial en formato CSV, los parsea y distribuye a los sensores correspondientes.
SensorCard m_sensor, m_nameLabel, m_valueLabel, m_selected updateValue(), setSelected(), mousePressEvent(), updateStyle() Widget visual que muestra el nombre y valor actual de un sensor. Emite la señal clicked() al ser presionado.
MainWindow m_source, m_simulator, m_serial, m_cards, m_chart, m_series, m_tick, m_min, m_max, m_sum, m_count setupUI(), setupChart(), switchSource(), onDataUpdated(), onSensorCardClicked(), onConnectClicked() Orquesta toda la aplicación. Construye la interfaz, gestiona el cambió entre fuentes de datos, actualiza el gráfico y las estadísticas.

Diagrama de Clases

Diagrama de Clases UML del sistema HMI Sensores
Figura 1: Diagrama de Clases del sistema HMI Sensores. Se muestra la jerarquía de herencia, composiciones y referencias entre las clases principales.

La arquitectura del sistema se fundamenta en el principio de inversión de dependencias y una estricta separación de responsabilidades. Como núcleo orquestador, MainWindow ejerce una relación de composición sobre las fuentes de datos concretas (DataSimulator y SerialSource), pero interactúa con ellas a través del polimorfismo que le provee la herencia de la interfaz abstracta IDataSource. Esta decisión de diseño garantiza que la ventana principal pueda intercambiar el flujo de información en tiempo de ejecución sin acoplarse a la lógica específica de generación o recepción de datos. A su vez, las fuentes de datos concretas componen y administran internamente el ciclo de vida de los modelos SensorChannel. Para el despliegue visual, MainWindow agrega dinámicamente instancias de SensorCard; cada una de estas tarjetas mantiene una referencia directa y unidireccional hacia su SensorChannel correspondiente. De este modo, se asegura que la interfaz gráfica actúe como una vista pasiva que refleja el estado del modelo de forma independiente, aislando la adquisición de datos de la capa de presentación.

Diagrama de Secuencia — Caso de uso 1

A continuación se describe el flujo lógico paso a paso que representa el diagrama de secuencia para el caso de uso 1:

  1. El Operador ejecuta la aplicación, lo que invoca a main(), que crea una instancia de MainWindow.
  2. MainWindow crea un objeto DataSimulator y un objeto SerialSource en su constructor.
  3. MainWindow conecta la señal dataUpdated() de DataSimulator al slot onDataUpdated().
  4. MainWindow llama a m_source->start(), que inicia un QTimer con intervalo de 500 ms.
  5. El QTimer dispara la señal timeout() cada 500 ms, ejecutando DataSimulator::onTick().
  6. onTick() recorre el vector de sensores y llama a update() en cada uno.
  7. Cada SensorChannel::update() calcula un nuevo valor usando la función seno con fase acumulativa mas ruido aleatorio.
  8. onTick() emite la señal dataUpdated().
  9. MainWindow::onDataUpdated() recibe la señal.
  10. onDataUpdated() consulta el valor actual de cada sensor mediante m_source->sensor(i).currentValue().
  11. onDataUpdated() actualiza el texto de cada SensorCard con updateValue().
  12. onDataUpdated() agrega el nuevo punto al QLineSeries del gráfico.
  13. onDataUpdated() ajusta el rango del eje X si es necesario y actualiza las estadísticas MIN, MAX y AVG.
Diagrama de Secuencia UML
Figura 2: Diagrama de Secuencia para el caso de uso "Visualizar datos simulados en tiempo real".

5. Resultados de Pruebas y Bugs

Resultados de pruebas

Se realizaron pruebas funciónales de los tres casos de uso definidos. A continuación se describen los resultados obtenidos:

Caso de uso 1 — Visualizar datos simulados: La aplicación se compiló y ejecutó correctamente en el entorno Windows utilizando Qt Creator con el compilador MinGW. Al iniciar, el simulador comenzó a generar datos inmediatamente. Las tarjetas de sensor se actualizaron con valores dentro de los rangos esperados (Ambiente: 18-25 °C, Proceso: 60-80 °C, Critico: 90-110 °C). El gráfico de línea se dibujó correctamente y las estadísticas MIN, MAX y AVG se calcularon de forma precisa a lo largo del tiempo.

Simulador activo con tres sensores

Figura 6: Aplicación con simulador activo mostrando los tres sensores y el gráfico en tiempo real.

Caso de uso 2 — Seleccionar un sensor: Al hacer clic en la tarjeta "Proceso", el sistema respondió correctamente: la tarjeta se resaltó con borde verde, el gráfico se restableció y comenzó a mostrar los valores del sensor Proceso en color verde. Las estadísticas se reiniciaron y comenzaron a acumularse con los nuevos datos. El mismo comportamiento se verificó con el sensor "Crítico" (borde rojo).

Sensor Proceso seleccionado

Figura 7: Sensor "Proceso" seleccionado, con gráfico verde y estadísticas actualizadas.

Dificultades encontradas y soluciónes

#DificultadSolución
1 Configuración de Qt6 en Windows con los módulos Charts y SerialPort. Se utilizó el Maintenance Tool de Qt para agregar los módulos faltantes después de una instalación inicial incompleta.
2 El archivo .ui no se utilizó correctamente ya que la interfaz se construyó en código. Se mantuvo el archivo .ui con la estructura básica de QMainWindow y se construyó el layout completamente en C++ para tener mayor control sobre el estilo visual (tema oscuro).
3 Indentación inconsistente en serialsource.h con espacios adicionales. Se corrigió manualmente la indentación para mantener consistencia con el resto del proyecto.
4 Gestión de memoria en SensorCard y referencias a SensorChannel. Se verificó que DataSimulator y SerialSource mantuvieran sus vectores de sensores estables y que los punteros a SensorCard se gestionaran correctamente en MainWindow.

Bugs conocidos

6. Entregable

La presente fue descrita en texto plano, en HTML y CSS. La codificación del archivo es UTF-8.

La documentación del código fuente se generó utilizando Doxygen, empleando comentarios en formato /** @brief */ para describir clases y métodos públicos, y /// para atributos, slots y señales. Esta documentación se encuentra embebida directamente en los archivos de código fuente (.h y .cpp), y puede generarse ejecutando doxygen desde la raíz del proyecto si se desea obtener la documentación. Para generar la documentación de forma independiente, instale Doxygen y ejecute "doxygen -g Doxyfile" desde la raíz del proyecto para crear el archivo de configuración, luego edite el campo INPUT para que apunte al directorio actual y ejecute "doxygen Doxyfile".

El proyecto fue desarrollado utilizando Qt 6.11.1 con el compilador MinGW 13.1.0 sobre el sistema operativo Windows. La herramienta de build utilizada fue CMake 3.19+ con el generador Ninja.

DESCARGAR PROYECTO (.tar)

El archivo comprimido contiene los archivos fuente del proyecto (headers, fuentes C++, CMakeLists.txt y mainwindow.ui).