Saltar a contenido
← Volver a OPRobots.org

Problemas Conocidos

Fecha de análisis: 2026-06-30 Última actualización: 2026-06-30 Total: 13 issues — 1 crítico, 4 moderados, 8 leves


Resumen por Prioridades

Prioridad Cantidad Issues
🔴 Críticos 1 SW-01
🟡 Moderados 4 HW-01, HW-03, CT-01, CT-02, EG-02
🟢 Leves 8 HW-02, SW-02, SW-03, EG-01, MV-01, MV-02, MV-03
TOTAL 13

Correcciones Recientes ✅

ID Fecha Descripción

🔴 Críticos

Software / Arquitectura

SW-01 — Buffer overflow en ISR de USART

Archivossetup.c:98
DescripciónEl buffer de comandos static char command[8] se llena sin comprobación de límites en command[i++]. Si se envían más de 7 caracteres antes del \n, el buffer desborda y corrompe la pila (variables locales, dirección de retorno de la ISR).
ImpactoAlto — Puede causar crashes, comportamiento errático, o vulnerabilidad de seguridad.
MitigaciónNinguna. Se asume que el host no envía comandos largos.
SoluciónAñadir if (i < sizeof(command) - 1) antes de almacenar cada carácter, o implementar un timeout que descarte comandos incompletos.

🟡 Moderados

Hardware

HW-01 — Discrepancia SYSCLK: 84 MHz vs 72 MHz real

Archivosconfig.h:7, setup.c:13
Descripciónconfig.h declara SYSCLK_FREQUENCY_HZ 84000000 y CYCLE_COUNTER_PER_MICROSECONDS 84, pero setup_clock() llama a rcc_clock_setup_in_hse_8mhz_out_72mhz() que configura el PLL a 72 MHz. Como resultado, delay_us() calcula mal los ciclos de espera: usa 84 ciclos/µs cuando debería usar 72. Los delays en microsegundos son un ~14% más cortos de lo esperado.
ImpactoMedio — Timing incorrecto en delay_us(). Las frecuencias de PWM y encoder se derivan del reloj real (72 MHz), por lo que los valores documentados en código (basados en 84 MHz) no coinciden.
MitigaciónNinguna. El código funciona porque 72 MHz es la frecuencia real.
SoluciónCambiar SYSCLK_FREQUENCY_HZ a 72000000 y CYCLE_COUNTER_PER_MICROSECONDS a 72.

HW-03 — Timer prescaler documentado para frecuencia incorrecta

Archivossetup.c:152
DescripciónEl prescaler de TIM1/TIM2 es 4 (división por 5). Con 72 MHz reales, la frecuencia PWM es 72 MHz / 5 / 512 = 28.125 kHz. Con 84 MHz (como declara config.h) sería 32.8 kHz. La documentación del código no aclara qué frecuencia se pretendía. 28 kHz es adecuado para motores BLDC pequeños (por encima del rango audible).
ImpactoMedio — La frecuencia real de PWM es correcta, pero la discrepancia con la documentación puede confundir.
MitigaciónNinguna necesaria.
SoluciónDocumentar la frecuencia real de PWM y ajustar las constantes de config.h para que coincidan.

Control PID

CT-01 — Término derivativo del PID comentado (solo PI)

Archivosmotors.c:65, motors.c:86
DescripciónMOTOR_SPEED_KD está definido como 0.0 y el cálculo del término derivativo (left_error - motor_left_last_error) * MOTOR_SPEED_KD está comentado. El controlador opera como PI en lugar de PID. En control de velocidad de motores, el término D puede ayudar a amortiguar oscilaciones y mejorar la respuesta a cambios bruscos de carga.
ImpactoMedio — Respuesta transitoria subóptima. Posibles overshoots en cambios bruscos de consigna.
MitigaciónEl término integral proporciona cierta capacidad de reacción, pero sin amortiguamiento.
SoluciónExperimentar con KD bajo (0.5-2.0) y evaluar si mejora la respuesta sin amplificar ruido del encoder.

CT-02 — Anti-windup asimétrico: integrador sin límite superior

Archivosmotors.c:75-80, motors.c:96-101
DescripciónLa condición if (motor_left_speed_factor < 100 || left_error < 0) permite acumular error integral cuando speed_factor == 100 y error < 0 (el motor va más rápido de lo pedido). Esto es correcto para reducir la integral cuando se necesita frenar. Pero cuando speed_factor == 100 y error > 0 se deja de acumular — correcto. Sin embargo, el integrador no tiene límite superior (solo inferior en 0) ni back-calculation, así que si se acumula un valor muy alto durante una aceleración, tarda en bajar cuando se reduce la consigna.
ImpactoMedio — Posible overshoot al reducir bruscamente la velocidad objetivo desde máxima velocidad.
MitigaciónEl clamping inferior (nunca < 0) evita windup negativo.
SoluciónAñadir clamping superior al integrador (ej. 100 / MOTOR_SPEED_KI) correspondiente al máximo speed factor alcanzable.

Encoders

EG-02 — Posible overflow en acumulador fixed-point del filtro de velocidad

Archivosencoders.c:164-167
DescripciónLa variable left_speed_smooth_fp (int32_t) acumula valores en formato fixed-point con el filtro IIR: speed_smooth_fp = (speed_smooth_fp << 4) - speed_smooth_fp + speed. Con 3 bits fraccionales, el rango efectivo es ±2²⁸ ≈ ±268M ticks/s. Aunque improbable en condiciones normales, con ruido extremo o spikes de encoder el acumulador podría desbordar silenciosamente.
ImpactoMedio — Overflow silencioso causaría lecturas de velocidad incorrectas. Poco probable en operación normal.
MitigaciónLos valores reales de velocidad están muy por debajo del límite de overflow (MAX_RPM = 900 genera ~150 ticks/diff).
SoluciónAñadir clamping del valor filtrado al rango esperado o usar int64_t para el acumulador fixed-point.

🟢 Leves

Hardware

HW-02 — Includes ADC/DMA no utilizados

Archivossetup.h:7-8
Descripciónsetup.h incluye <libopencm3/stm32/adc.h> y <libopencm3/stm32/dma.h>, pero no se configura ningún ADC ni DMA en setup.c. Código muerto que probablemente se añadió para una funcionalidad futura (sensor de corriente o tensión de batería).
ImpactoBajo — Solo afecta al tiempo de compilación y claridad del código.
MitigaciónNinguna necesaria.
SoluciónEliminar los includes o implementar la lectura de ADC.

Software / Arquitectura

SW-02 — motor_right_inited no declarado volatile

Archivosmotors.c:23
Descripciónmotor_right_inited se modifica en set_motor_right_inited(), llamada desde la ISR exti15_10_isr(). Sin embargo, no está declarado volatile, a diferencia de otras variables como motor_left_speed. El compilador podría optimizar lecturas si el flag llegara a usarse en el main loop.
ImpactoBajo — Actualmente el flag no se lee desde el main loop (ver SW-03). Si se implementara su lectura, podría fallar sin volatile.
MitigaciónEl flag no se usa, así que el bug está latente.
SoluciónDeclarar static volatile int motor_right_inited.

SW-03 — Flags de inicialización por motor nunca consultados

Archivosmotors.c:114-120
Descripciónset_motor_left_inited() y set_motor_right_inited() son llamadas desde las ISRs de índice Z para marcar cada motor como inicializado. Sin embargo, estos flags (motor_left_inited, motor_right_inited) no se leen en ninguna parte del código. motors_move() solo comprueba el flag global inited.
ImpactoBajo — Funcionalidad incompleta: no se puede saber si un encoder ha recibido su pulso de índice. Permitiría distinguir entre "encoder sin referencia de cero" y "encoder listo".
MitigaciónEl flag global inited es suficiente para la operación actual.
SoluciónUsar los flags para condicionar el modo de operación (open-loop hasta recibir índice, closed-loop después) o eliminar el código muerto.

Encoders

EG-01 — Offsets de calibración hardcodeados sin documentación

Archivosencoders.c:71, encoders.c:77
DescripciónLos valores left_total_ticks = 22 y right_total_ticks = -61 son offsets de calibración que corrigen la diferencia angular entre el pulso de índice Z y el cero eléctrico del motor. Estos valores son específicos del montaje mecánico de cada motor en UltiBot y no son reutilizables. No hay documentación sobre cómo se obtuvieron ni cómo recalibrar para otro robot.
ImpactoBajo — La funcionalidad es correcta para el hardware actual, pero la mantenibilidad es deficiente.
MitigaciónNinguna.
SoluciónMover los offsets a #defines con nombres descriptivos en config.h (ej. ENCODER_LEFT_INDEX_OFFSET, ENCODER_RIGHT_INDEX_OFFSET) y documentar el procedimiento de calibración.

Movimiento

MV-01 — Uso de round() (doble precisión) en lugar de roundf()

Archivosmotors.c:34
DescripciónEn fill_lookup(), se usa abs(round(value)) donde round() opera en double. En un Cortex-M3 sin FPU de doble precisión, esto implica emulación por software, añadiendo latencia significativa durante la inicialización. La LUT se genera una sola vez al arrancar.
ImpactoBajo — Solo afecta al tiempo de inicialización (~360 llamadas a round()).
MitigaciónNinguna. La inicialización ocurre una sola vez.
SoluciónCambiar a roundf() (float) o precalcular la LUT offline e incluirla como array constante en el código.

MV-02 — Orden de fases asimétrico entre motores sin documentar

Archivosmotors.c:161-163, motors.c:184-186
DescripciónEl motor izquierdo asigna fases en orden C→B→A a los canales PWM (CCR1/CCR2/CCR3), mientras que el motor derecho usa A→C→B. Además, los offsets de fase para velocidad positiva son +270° (izquierdo) y +90° (derecho). Esta asimetría es intencionada por la orientación física de los motores en UltiBot, pero no está documentada ni comentada en el código.
ImpactoBajo — Si se reutiliza este código con otra orientación de motores, el sentido de giro será incorrecto o el motor no arrancará.
MitigaciónNinguna.
SoluciónAñadir comentarios explicando la orientación esperada y la relación entre orden de fases y sentido de giro.

MV-03 — motor_right_speed inconsistente en tipo vs motor_left_speed

Archivosmotors.c:8, motors.c:19
Descripciónmotor_left_speed está declarado como static volatile int, mientras que motor_right_speed es static volatile int. Ambos son correctos, pero motor_right_inited es static int (no volatile, ver SW-02). La inconsistencia sugiere que los calificadores se aplicaron sin criterio uniforme.
ImpactoBajo — No causa bugs actualmente, pero indica falta de revisión sistemática.
MitigaciónNinguna.
SoluciónAuditar y unificar los calificadores de todas las variables compartidas con ISRs.

Documento generado el 2026-06-30 tras auditoría exhaustiva del código fuente. Ver también el resto de secciones de la documentación para contexto de cada subsistema.