Saltar a contenido

Problemas Conocidos

Fecha de análisis: 2026-06-11 Última actualización: 2026-08-25 Total: 64 issues — 10 críticos, 24 moderados, 30 leves

Última revisión: 2026-08-25 (commits aa1e633..2bbbe13) Issues nuevos: 17 (HW-01..HW-05, SW-01..SW-03, SP-01..SP-09) Issues corregidos: 0 Issues actualizados: 0


Correcciones Recientes ✅

ID Fecha Descripción
SS-01 2026-06-11 Desbordamiento de tabla LUT — añadido bounds checking
SS-02 2026-06-11 Análisis de timing: margen 97x, fallo improbable
SS-03 2026-06-11 Filtro mediana N=3 + EMA adaptativo (α=0.2/0.6, umbral 10mm)
SS-07 2026-06-11 Threshold raw corregido con ley 1/d² (factor 1.5× distancia)
SS-15 2026-06-11 Checksum aditivo (complemento a 2) en EEPROM + warning_eeprom

🔴 Críticos (10 issues)

Floodfill

FF-01 — Estado insuficiente en el BFS para modo TIME_BASED

Archivosfloodfill.c:340
DescripciónEl floodfill almacena un único float por celda. En TIME_BASED, el coste de transición depende del estado (dirección + count). Un camino con tiempo ligeramente superior pero mejor dirección se descarta.
ImpactoAlto — puede no encontrar la ruta óptima global.
MitigaciónCondición >= permite caminos con mismo tiempo pero distinto estado.
SoluciónAmpliar estado a floodfill[celda][direccion] o usar A*.

FF-02 — Desbordamiento de la cola de prioridad ✅ CORREGIDO

Archivosfloodfill.h:64-68, floodfill.c:358-387
DescripciónLa cola tenía capacidad fija de MAZE_CELLS (256 slots) con head/tail acumulativos. Con la relajación >= de los modos no-BASIC, un mismo update_floodfill() puede encolar bastante más de 256 veces (medido: TIME hasta ~624; DIAGONAL hasta ~14 000 en exploración de laberinto vacío). El push #257 escribía sobre head/tail (offset 4096) → SIGSEGV o floodfill incompleto.
ImpactoAlto — corrupción de memoria y caída del simulador. En robot normalmente no se disparaba porque el laberinto cargado de EEPROM reduce los reencolados, pero era UB latente.
SoluciónCapacidad ampliada a MAZE_CELLS × 8 (2048 slots, 32 KB) mediante CELLS_QUEUE_CAPACITY y guardas de capacidad en queue_push()/queue_pop(). Se conserva la condición >= (necesaria para estados con distinta orientación en diagonales encadenadas). TIME queda con ~3× de margen; DIAGONAL puede saturar la cola en exploración de laberinto vacío, pero la guarda evita la corrupción y el floodfill sigue siendo completo.

FF-03 — Penalización de giro ausente en transición ortogonal→ortogonal

Archivosfloodfill.c:515-520
DescripciónEl caso from_orthogonal && to_orthogonal no verifica si la dirección cambió.
ImpactoBajo en práctica (cubierto por otros casos del switch).

Sensores

SS-01 — Desbordamiento de tabla LUT ✅ CORREGIDO

SoluciónAñadido bounds checking: if (ln_index >= LOG_LINEARIZATION_TABLE_SIZE) ln_index = LOG_LINEARIZATION_TABLE_SIZE − 1.

SS-02 — Pérdida de conversiones ADC ✅ CORREGIDO

SoluciónAnálisis de timing confirmó margen 97x. Sin riesgo real.

SS-03 — Sin filtrado de lecturas ADC ✅ CORREGIDO

SoluciónAñadido: mediana N=3 + EMA adaptativo.

Movimiento

MV-01 — PID sin anti-windup (6 integradores)

Archivoscontrol.c:392-451
DescripciónLos 6 integradores acumulan error sin clamping. Tras saturación, overshoot masivo.
ImpactoAlto — inestabilidad severa.
SoluciónImplementar clamping condicional (back-calculation o conditional integration).

MV-02 — move_inplace_turn() siempre gira a la izquierda

Archivosmove.c:126-143
DescripciónMOVE_BACK, MOVE_BACK_WALL y MOVE_BACK_STOP tienen sign = −1 fijo.
ImpactoMedio-Alto — desviación sistemática en exploración.

MV-03 — lsm6dsr_read_gyro_z_raw() depende de auto-incremento SPI no verificado

Archivoslsm6dsr.c:66-73
DescripciónAsume que IF_INC está habilitado para leer ZL+ZH consecutivos.
ImpactoMedio — datos incorrectos si IF_INC no está configurado.

MV-04 — platform_write() y platform_read() ignoran parámetro len

Archivoslsm6dsr.c:48-59
DescripciónSolo transfieren 1 byte independientemente del parámetro len.
ImpactoMedio — frágil ante cambios de la librería LSM6DSR.

🟡 Moderados (24 issues)

Floodfill

FF-04 — total_time incorrecto en tabla de pesos

Descripcióntotal_time incorrecto en tabla de pesos (primera celda contada 2×).
ImpactoBajo.

FF-05 — Índice incorrecto en mmsim_get_estimated_time()

Descripciónmmsim_get_estimated_time() usa índice incorrecto (off-by-one).
ImpactoMedio.

FF-06 — Modelo de penalización de giro inexacto

DescripciónModelo de penalización de giro inexacto (asume deceleración completa).
ImpactoMedio.

FF-07 — Orientación inicial no considerada al planificar

DescripciónFloodfill no considera orientación inicial del robot al planificar.
ImpactoMedio.

Sensores

SS-04 — Fórmula con posible división por ~0

DescripciónFórmula con posible división por ~0.
EstadoNO APLICA.

SS-05 — Parámetro c negativo (mitigado)

DescripciónParámetro c negativo (mitigado).
EstadoNO APLICA.

SS-06 — Filtro EMA sustituido por adaptativo

DescripciónFiltro EMA sustituido por adaptativo en SS-03.
EstadoNO APLICA.

SS-07 — Umbral raw corregido con ley 1/d² ✅ CORREGIDO

DescripciónUmbral raw corregido con ley 1/d² (factor 1.5× distancia).

SS-08 — Crosstalk óptico potencial

DescripciónCrosstalk óptico potencial.
EstadoNO APLICA.

SS-09 — Umbrales cableados en get_side_sensors_error()

DescripciónUmbrales cableados en get_side_sensors_error().
EstadoNO APLICA.

SS-10 — Fórmula no validada contra datasheet

DescripciónFórmula no validada contra datasheet (validada empíricamente).
EstadoNO APLICA.

SS-15 — Sin validación de datos EEPROM ✅ CORREGIDO

DescripciónSin validación de datos EEPROM. Corregido con checksum aditivo (complemento a 2) + warning_eeprom.

Movimiento

MV-05 — Distancia de frenada usa velocidad ideal

DescripciónDistancia de frenada usa velocidad ideal, no real.
ImpactoMedio.

MV-06 — Filtros independientes en velocidad angular

DescripciónVelocidad angular con filtros independientes (desfase entre canales).
ImpactoBajo-Medio.

MV-07 — PI con 4 decimales

DescripciónPI con 4 decimales (error 0.003%).
ImpactoBajo.

MV-08 — Fórmulas de move_inplace_turn() no cinemáticamente exactas

DescripciónFórmulas move_inplace_turn() no cinemáticamente exactas.
ImpactoMedio.

MV-09 — Degradación de giro solo hacia abajo

DescripciónDegradación de giro solo hacia abajo.
ImpactoMedio.

MV-10 — Posible inconsistencia de signos en control angular

DescripciónPosible inconsistencia de signos en control angular.
ImpactoAlto potencial.

MV-11 — move_straight() negativo no comprueba wall loss

Descripciónmove_straight() negativo no comprueba wall loss.
ImpactoBajo.

Hardware

HW-01 — Esquemático y PCB desincronizados

Archivospcb_files/kicad_project/ZoroBot3.kicad_sch, pcb_files/kicad_project/ZoroBot3.kicad_pcb
DescripciónEl commit ced009d añade la SRAM 23AA04M al esquemático (SRAM1 + RRAM1 + CSRAM1 + net NSS_SRAM) y elimina los amplificadores de corriente AD8418, pero el PCB no se ha actualizado: la SRAM no está colocada y los footprints AD8418AWBZ_1/_2 siguen presentes. El diff del PCB en ese commit es solo migración de formato KiCad 8→10 (198 footprints idénticos).
ImpactoMedio-Alto — fabricar la placa en este estado produciría un PCB sin SRAM y con amplificadores sin función; riesgo de olvido si no se sincroniza antes de fabricar.
MitigaciónNinguna — el desfase es silencioso hasta exportar gerbers.
SoluciónEjecutar Update PCB from Schematic y recolocar/rutear las piezas nuevas y huérfanas antes de la próxima fabricación.

HW-02 — Lectura de corriente sin amplificador front-end

Archivospcb_files/kicad_project/ZoroBot3.kicad_sch (nets CURR_SEN_MI/CURR_SEN_MD)
DescripciónEl commit ced009d anunciaba "añadir lectura de corriente" pero elimina los amplificadores AD8418 y los shunts (SHUNT_MI/SHUNT_MD). Los canales ADC CH14/CH15 (PC4/PC5) quedan conectados sin shunt ni etapa de ganancia, por lo que no miden corriente utilizable.
ImpactoMedio — la lectura de corriente de motores queda inoperativa; los canales ADC quedan sin señal útil.
MitigaciónNinguna — el firmware no usa estos canales actualmente.
SoluciónRediseñar el front-end (p. ej. reinsertar AD8418 con shunt, o un amplificador de nueva generación) o eliminar los canales y su documentación.

HW-03 — Diodo de protección del ventilador de succión ausente

Archivospcb_files/kicad_project/ZoroBot3.kicad_sch, ZoroBot3.kicad_pro
DescripciónEl commit ced009d menciona un "diodo en succión" pero ningún fichero guardado contiene ese diodo: D14 solo existe como designador fantasma en used_designators del proyecto KiCad. El ventilador queda sin diodo de libre circulación/protección.
ImpactoMedio — picos de tensión inducidos por el motor del ventilador pueden dañar el MOSFET de control (Q1).
MitigaciónNinguna en el diseño actual.
SoluciónAñadir el diodo al esquemático (en paralelo con el ventilador, cátodo a positivo) y propagar a PCB/BOM.

Scripts Python

SP-01 — Dependencias de los scripts sin declarar

Archivosscripts/turn-profiles/*.py, scripts/turn-profiles/*.ipynb, scripts/sensors-profiles/sensors-profiles.ipynb
DescripciónLos scripts importan numpy, matplotlib y pandas (y scipy.optimize en sensors-profiles) sin que exista ninguna declaración de dependencias en el repo: no hay requirements.txt ni pyproject.toml en la raíz ni en scripts/ (los únicos requirements son de docs y solo contienen mkdocs). Un entorno limpio falla con ModuleNotFoundError y no queda registro del contrato de runtime.
ImpactoMedio — los scripts no son reproducibles en una máquina nueva.
SoluciónAñadir un requirements.txt (numpy, pandas, matplotlib, scipy) en scripts/ o en la raíz y referenciarlo en los README de los scripts.

SP-02 — Imports dependientes del directorio de trabajo

Archivosscripts/turn-profiles/aux/verify_profiles.py:9, aux/deep_analysis.py:7, aux/analyze_all_pairs.py:10, aux/test_new_exit.py:14, turn-profiles.ipynb (celda 2)
DescripciónLos cuatro scripts auxiliares hacen sys.path.insert(0, '.') e importan la biblioteca principal: solo funciona si el CWD es exactamente scripts/turn-profiles/. El notebook tiene la misma dependencia oculta (importa el módulo sin manipular el path). Desde cualquier otro directorio falla con ModuleNotFoundError sin diagnóstico útil.
ImpactoMedio — scripts frágiles ante la forma de invocación.
SoluciónDerivar la ruta del módulo desde __file__ (p. ej. sys.path.insert(0, str(Path(__file__).resolve().parent.parent))) o empaquetar el módulo; documentar el requisito de CWD en el notebook.

🟢 Leves (30 issues)

Floodfill

FF-08 — Código inalcanzable tras return en switches

DescripciónCódigo inalcanzable tras return en switches.

FF-09 — #pragma GCC diagnostic ignora -Wswitch

Descripción#pragma GCC diagnostic ignora -Wswitch.

FF-10 — time_penalty retorna 0 si init_speed >= speed

Descripcióntime_penalty retorna 0 si init_speed >= speed.

FF-11 — get_direction_value() devuelve 0 para diagonales

Descripciónget_direction_value() devuelve 0 para diagonales.

FF-12 — Sesgo direccional en floodfill_run()

DescripciónSesgo direccional en floodfill_run() (NORTH siempre gana empates).

FF-13 — cells_to_max_speed puede exceder el buffer de pesos

Descripcióncells_to_max_speed puede exceder FLOODFILL_MAX_WEIGHTS_COUNT.

Sensores

SS-11 — update_side_sensors_leds() con código repetitivo

Descripciónupdate_side_sensors_leds() con código repetitivo.
EstadoNO APLICA.

SS-12 — all_sensors_take_values() bucle infinito (debug)

Descripciónall_sensors_take_values() bucle infinito (debug).
EstadoNO APLICA.

SS-13 — Flag sensors_taking_values nunca a false

DescripciónFlag sensors_taking_values nunca a false.
EstadoNO APLICA.

SS-14 — División entera en calibración

DescripciónDivisión entera en calibración (error ±1 sobre ~2000).
EstadoNO APLICA.

Movimiento

MV-12 — avg_micrometers/avg_millimeters nunca actualizadas

Descripciónavg_micrometers/avg_millimeters nunca actualizadas (código muerto).

MV-13 — volatile innecesario en variables de control PID

Descripciónvolatile innecesario en variables de control PID.

MV-14 — Expresión redundante true && en move_arc_turn()

DescripciónExpresión redundante true && en move_arc_turn().

MV-15 — Número mágico 1.75f en move_back()

DescripciónNúmero mágico 1.75f en move_back().

MV-16 — Parámetros start/end negativos sin validación de rango

DescripciónParámetros start/end negativos sin validación de rango.

MV-17 — check_wall_loss_correction() solo paredes laterales

Descripcióncheck_wall_loss_correction() solo paredes laterales.

MV-18 — Frecuencia acoplada rígidamente a SysTick = 16 kHz

DescripciónFrecuencia acoplada rígidamente a SysTick = 16 kHz.

MV-19 — Wrap-around de timer de encoders (verificado correcto ✅)

DescripciónWrap-around de timer de encoders (verificado correcto ✅).

Hardware

HW-04 — BOM desactualizado

Archivospcb_files/gerbers/bom.csv (+ designators.csv, positions.csv)
DescripciónEl BOM generado es anterior al rango revisado: lista los AD8418 eliminados del esquemático y no incluye SRAM1/RRAM1/CSRAM1 (23AA04M, 10 kΩ, 100 nF).
ImpactoBajo — pedido de componentes incorrecto si se usa el BOM sin regenerar.
SoluciónRegenerar el BOM desde el esquemático actual (export BOM de KiCad) cuando el diseño se estabilice.

HW-05 — SRAM sin soporte en firmware

Archivossource_code/ (sin driver); pcb_files/kicad_project/ZoroBot3.kicad_sch (SRAM1)
DescripciónLa SRAM 23AA04M-I/ST (4 Mbit) está conectada al bus SPI3 compartido con CS dedicado en PB12 (pull-up 10 kΩ), pero no existe driver ni inicialización en el firmware. PB12 está libre en el código actual.
ImpactoBajo — la SRAM no es utilizable hasta añadir el driver.
SoluciónImplementar driver SPI (modo byte) con CS en PB12 e integrar el uso previsto de la SRAM.

Arquitectura Software

SW-01 — Comentarios de setup_spi() incorrectos

Archivossetup.c:328-332
DescripciónEl comentario documenta CPHA 0 ("los datos de entrada se capturan en el flanco ascendente") pero el código usa SPI_CR1_CPHA_CLK_TRANSITION_1 (CPHA 1, captura en el segundo flanco). Además los comentarios de frecuencia mezclan PCLK1 = 36 MHz con 84 MHz para el cálculo del divisor SPI.
ImpactoBajo — riesgo de configuraciones erróneas en cambios futuros guiados por el comentario.
SoluciónCorregir el comentario al valor real del registro (CPHA 1) y unificar las frecuencias de reloj citadas.

SW-02 — setup_spi_low_speed() código muerto

Archivossetup.c:375-378
DescripciónLa función setup_spi_low_speed() está definida pero nunca se llama en todo el firmware.
ImpactoBajo — mantenibilidad.
SoluciónEliminarla o usarla donde corresponda.

SW-03 — openocd_reset.cfg referencia STM32F401

Archivosopenocd_reset.cfg
DescripciónEl comentario sobre flash de banco único menciona "STM32F401"; el target real es un STM32F405 (también de banco único, por lo que el comportamiento descrito es correcto).
ImpactoBajo — confusión al leer la configuración.
SoluciónCambiar el comentario a STM32F405.

Scripts Python

SP-03 — ValueError sin mensaje en perfiles slalom infeasibles

Archivosscripts/turn-profiles/micromouse_sinusoidal_turn_profiles_aux.py:299, aux/test_new_exit.py:199-200
DescripciónCuando un perfil slalom es infeasible, se lanza raise ValueError sin mensaje. El capturador en test_new_exit.py imprime turn_shift failed (lines parallel) - {e} con mensaje vacío, atribuyendo la causa a líneas paralelas cuando en realidad es la comprobación de velocidad angular de la transición.
ImpactoBajo — diagnóstico engañoso.
Soluciónraise ValueError(f'transition-only angular velocity {max_angular_velocity_transition:.3f} < required {max_angular_velocity:.3f}').

SP-04 — except Exception genérico oculta bugs como fallos de estrategia

Archivosscripts/turn-profiles/aux/test_new_exit.py:232
DescripciónEl except Exception as e exterior del bucle de estrategias imprime ERROR - {e} y hace continue. Cualquier error de programación real (KeyError, NaN, typo) dentro del try se reporta como fallo de la estrategia de shift, sin traceback ni re-raise. El except ValueError interno (líneas 194-201) ya cubre el caso esperado.
ImpactoBajo — bugs reales se ocultan como resultados legítimos del análisis.
SoluciónEliminar el except Exception exterior, o re-lanzar tras imprimir con traceback.print_exc().

SP-05 — Código muerto y comentado sin explicación

Archivosscripts/turn-profiles/aux/test_new_exit.py:82, micromouse_sinusoidal_turn_profiles_aux.py:288
DescripciónLínea muerta errónea en test_new_exit.py:82 (usa la columna y en vez de x, marcada como "wrong, let me recalc", nunca usada — el cálculo correcto sigue en 85-86) y fórmula comentada en la biblioteca (línea 288) sin explicación de por qué se sustituyó.
ImpactoBajo — mantenibilidad; la línea errónea induciría a error si se reactivara.
SoluciónEliminar la línea 82 y el comentario de la 288 (o documentar el motivo de la sustitución).

SP-06 — Encoding corrupto en verify_profiles.py

Archivosscripts/turn-profiles/aux/verify_profiles.py
DescripciónEl archivo contiene 1428 bytes de ? literales donde debería haber ✓/✗/═/acentos: "Script de verificaci??n", separadores "????????", y los marcadores pass/fail muestran "???" en ambas ramas. El veredicto del script — su función principal — queda ilegible.
ImpactoBajo — el lector debe inferir el resultado de los ratios numéricos.
SoluciónReescribir los caracteres (✓/✗, ═, verificación) y verificar la codificación UTF-8 al guardar.

SP-07 — Clasificación "PERPENDICULAR" errónea en analyze_all_pairs.py

Archivosscripts/turn-profiles/aux/analyze_all_pairs.py:297-306
DescripciónTras normalizar los ángulos a [0, π/2], el código clasifica como perpendiculares los pares con abs(angle_between - π/4) < 0.01. Las líneas perpendiculares difieren π/2 (90°), no π/4: pares a 45° se etiquetan "PERPENDICULAR", alimentando el razonamiento de PART 4 sobre qué pares de giro necesitan tramo recto intermedio.
ImpactoBajo — decisiones de diseño basadas en salida incorrecta.
Soluciónis_perpendicular = abs(angle_between - π/2) < 0.01.

SP-08 — Notebook de turn-profiles con 3 MB de figuras y títulos con mojibake

Archivosscripts/turn-profiles/turn-profiles.ipynb (celdas 7, 9, 11, 13, 15, 17)
Descripción42 figuras PNG de 1600×1600 embebidas en el notebook (3.06 MB total) y 36 títulos con la secuencia "º" (mojibake del carácter °): p. ej. plot_trajectory(title = "90º NORMAL"). El notebook pesa 3.1 MB, renderiza lento y los títulos guardados están corruptos.
ImpactoBajo — repo inflado y salida degradada.
SoluciónReducir a dpi=80-100 o guardar figuras en images/ y referenciarlas; reemplazar º por °.

SP-09 — Structs de calibración solo en stdout, sin artefacto diffable

Archivosscripts/sensors-profiles/sensors-profiles.ipynb (celda 8)
DescripciónLos coeficientes a/b/c que deben aterrizar en sensors.c se emiten solo como salida impresa de la celda 8. No existe artefacto en fichero ni comprobación contra los valores commitados en el firmware: cambiar ACTIVE_DATASETS o los rangos de ajuste modifica silenciosamente los structs emitidos sin dejar rastro diffable.
ImpactoBajo — las constantes del firmware pueden derivar del análisis sin detectarse.
SoluciónHacer que la celda 8 escriba a un fichero (p. ej. generated/sensors_calibration.h) o afirme igualdad con los valores del firmware; añadir nota de orden de ejecución.

Resumen por Prioridades

Prioridad Cantidad Issues
🔴 Críticos 10 FF-01..03, SS-01..03, MV-01..04
🟡 Moderados 24 FF-04..07, SS-04..10/15, MV-05..11, HW-01..03, SP-01..02
🟢 Leves 30 FF-08..13, SS-11..14, MV-12..19, HW-04..05, SW-01..03, SP-03..09
TOTAL 64

Documento actualizado el 2026-08-25. El registro de issues se mantiene en este mismo documento, con anchors estables (#xx-NN) para referencias cruzadas desde el resto de la documentación.