Saltar a contenido
← Volver a OPRobots.org

Problemas Conocidos

Fecha de análisis: 2026-06-29 Última actualización: 2026-06-29 Total: 14 issues — 4 críticos, 7 moderados, 3 leves


Correcciones Recientes ✅

ID Fecha Descripción

🔴 Críticos

HW-01 — digitalWrite(8, ...) en ISR corrompe SPI del display {#hw-01}

  • Archivo: rc5.cpp:134
  • Descripción: La ISR rc5_isr() escribe al pin 8 (digitalWrite(8, digitalRead(IR_PIN))), que es TFT_MOSI (SPI MOSI del display). Cualquier escritura a MOSI durante una transacción SPI activa corromperá los datos enviados al display, causando artefactos visuales o bloques de píxeles incorrectos.
  • Impacto: Alto — corrupción visual del display cada vez que se recibe una señal RC5.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Eliminar digitalWrite(8, ...). Es código de debug residual. Si se necesita monitorizar el pin IR, usar un pin GPIO libre o Serial.

HW-02 — delayMicroseconds(100) en ISR bloquea el sistema {#hw-02}

  • Archivo: rc5.cpp:123
  • Descripción: rc5_register() (llamada desde la ISR) ejecuta delayMicroseconds(100). Esto bloquea el core durante 100 µs en contexto de interrupción. Con la ISR disparándose a ~2-3 kHz (flanco CHANGE del receptor RC5), el overhead es ~20-30% del tiempo de CPU solo en el delay.
  • Impacto: Alto — pérdida de rendimiento, posibles pérdidas de interrupciones, latencia añadida al bucle principal.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Eliminar el delay o usar ets_delay_us() si es absolutamente necesario. Considerar refactorizar la decodificación RC5 para usar RMT (hardware) en lugar de GPIO interrupt.

CM-01 — Bucle infinito en client_start() si ESP-NOW falla {#cm-01}

  • Archivo: aux_module/client.cpp:68-71
  • Descripción: client_start() reintenta esp_now_send() en un bucle while sin timeout. Si el módulo principal no está encendido, está fuera de rango, o el buffer ESP-NOW está lleno, el módulo auxiliar se cuelga permanentemente.
  • Impacto: Alto — el módulo auxiliar deja de responder, no se puede recuperar sin reset físico.
  • Mitigación actual: Ninguna (el callback data_sent intenta reenviar también).
  • Solución propuesta: Añadir un timeout (ej. 100 reintentos o 500 ms) y salir con log de error. También valorar añadir un contador de reintentos máximo en data_sent.

SW-01 — pending_event sin volatile — race condition ISR↔main loop {#sw-01}

  • Archivo: control.cpp:10
  • Descripción: pending_event es modificado por control_set_pending_event() (llamada desde la cadena ISR de RC5) y leído en control_manage_pending_event() (bucle principal). Sin volatile, el compilador puede cachear el valor en un registro y no ver actualizaciones de la ISR.
  • Impacto: Alto — eventos RC5 (STOP, RESET) pueden perderse o procesarse con latencia indeterminada.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Declarar static volatile enum RC5_EVENTS pending_event.

🟡 Moderados

HW-03 — MAC addresses hardcodeadas en el módulo auxiliar {#hw-03}

  • Archivo: aux_module/config.cpp:12-16, aux_module/client.cpp:40
  • Descripción: Las MACs de los módulos (64:E8:33:87:CB:AC para START, 34:B7:DA:F8:C9:9C para FINISH) y del módulo principal (40:4C:CA:F5:75:74) están hardcodeadas en el código fuente. Cambiar de hardware requiere recompilar y reflashear.
  • Impacto: Medio — requiere modificar código fuente para nuevo hardware.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Usar un archivo de configuración en SPIFFS/LittleFS, o EEPROM, o pines de configuración por hardware.

SW-02 — long signed para valores de millis() — overflow a los ~24.8 días {#sw-02}

  • Archivo: stopwatch.cpp:8-16, screen.cpp:221
  • Descripción: Variables de tiempo como start_ms, last_time_ms, best_lap_ms, y parámetros de screen_update_timmings() usan long (int32_t) en lugar de unsigned long (uint32_t). Cuando millis() supera 2^31 (~24.8 días de uptime), estos valores se vuelven negativos al asignarse a long.
  • Impacto: Medio — no crítico para competición (uptime < horas), pero es frágil.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Cambiar todas las variables de tiempo a unsigned long. La aritmética millis() - start ya es correcta con unsigned.

SW-03 — time_ms > 1000 congela el display el primer segundo de vuelta {#sw-03}

  • Archivo: screen.cpp:225
  • Descripción: La condición if (time_ms == 0 || time_ms > 1000 || last_lap_ms == 0) impide actualizar el display cuando 0 < time_ms <= 1000 y last_lap_ms != 0. Durante el primer segundo de cada vuelta, la pantalla muestra el tiempo de la vuelta anterior en lugar del cronómetro en marcha.
  • Impacto: Medio — el display muestra información incorrecta durante 1 segundo tras cada inicio de vuelta.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Cambiar la condición a time_ms > 0 para que el display se actualice siempre que el cronómetro esté corriendo.

CM-02 — web_stop() sin rate-limit — posible flood SSE {#cm-02}

  • Archivo: web.cpp:348-351
  • Descripción: web_start(), web_lap(), y web_reset() tienen rate-limit de 1 evento/segundo, pero web_stop() tiene el rate-limit comentado. Si web_stop() se llama múltiples veces en rápida sucesión, puede inundar la conexión SSE.
  • Impacto: Medio — posible flood de eventos al navegador.
  • Mitigación actual: Ninguna (rate-limit comentado).
  • Solución propuesta: Descomentar el rate-limit en web_stop() para que coincida con las otras funciones.

MN-01 — Bucles busy-wait en botones sin timeout {#mn-01}

  • Archivo: control.cpp:69,81,90,98,104
  • Descripción: Los 5 bucles while (digitalRead(BTN)) para debounce de botones no tienen timeout. Si un botón se queda atascado mecánicamente, el sistema se congela.
  • Impacto: Medio — sistema no responsivo si un botón falla.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Añadir timeout (ej. 500 ms) con millis() y salir del bucle aunque el botón siga pulsado.

SS-01 — Bucle busy-wait en stopwatch_check() del módulo auxiliar {#ss-01}

  • Archivo: aux_module/stopwatch.cpp:22-27
  • Descripción: El bucle while (!digitalRead(SENSOR_PIN)) espera indefinidamente a que el sensor se libere. Si un robot se para justo delante del sensor, el módulo se bloquea.
  • Impacto: Medio — módulo auxiliar no responde si el sensor está bloqueado.
  • Mitigación actual: Si can_start == false y pasan 1000 ms, can_start se restaura, pero el bucle sigue ejecutándose.
  • Solución propuesta: Añadir un timeout máximo al bucle (ej. 5 segundos). Superado ese tiempo, salir y registrar el evento como anómalo.

🟢 Leves

CM-03 — RC5 pairing no persiste (EEPROM comentado)

  • Archivo: rc5.cpp:114-115
  • Descripción: rc5_init() tiene el cuerpo comentado. La lectura/escritura de EEPROM para almacenar los comandos RC5 emparejados no se ejecuta. Al reiniciar, los comandos emparejados se pierden.
  • Impacto: Bajo — el pairing funciona durante la sesión, pero se pierde al reiniciar.
  • Mitigación actual: Las constantes DATA_STOP = 0 y DATA_START = 1 con rc5_stored_data[] inicializado a cero en BSS permiten funcionamiento básico.
  • Solución propuesta: Implementar persistencia en NVS (Non-Volatile Storage) del ESP32, más adecuado que EEPROM para ESP32-C3.
  • Archivo: control.cpp:8
  • Descripción: La variable estática battey_blink_ms tiene un typo (falta una 'r').
  • Impacto: Bajo — cosmético, no afecta al funcionamiento.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Renombrar a battery_blink_ms.

DB-01 — Typo en nombre de función screen_update_timmings

  • Archivo: screen.h:31, screen.cpp:221
  • Descripción: La función se llama screen_update_timmings en lugar de screen_update_timings (doble 'm').
  • Impacto: Bajo — cosmético, no afecta al funcionamiento.
  • Mitigación actual: Ninguna.
  • Solución propuesta: Renombrar a screen_update_timings y actualizar todas las referencias.

Documento generado el 2026-06-29. Los issues se añaden y actualizan mediante /doc-review al auditar el código fuente.