Scripts: Calibración de Sensores IR
Herramienta offline para calibrar los sensores infrarrojos del robot. Calcula las
constantes (a, b, c) del modelo logarítmico empírico que convierte lecturas
ADC en distancia real (mm).
| Característica | Detalle |
|---|---|
| Script | scripts/sensors-profiles/sensors-profiles.ipynb |
| Tipo | Jupyter Notebook |
| Dependencias | numpy, pandas, matplotlib, scipy |
| Salida | Constantes (a, b, c) para cada sensor → se copian a sensors.c |
Modelo Matemático
Ecuación
distance (m) = a / ln(raw + c) - b
| Parámetro | Descripción |
|---|---|
raw |
Valor ADC (0–4095), lectura diferencial: sensor ON − sensor OFF |
a |
Factor de escala — controla la forma de la curva logarítmica |
b |
Offset vertical — desplaza la curva en distancia |
c |
Offset horizontal — compensa el offset del sensor, evita colapso del logaritmo |
Justificación física
Los sensores IR de reflectancia siguen aproximadamente la ley de la inversa del
cuadrado: raw ∝ 1/d², o equivalentemente d ∝ 1/√raw. El modelo
a/ln(raw+c) - b es una aproximación empírica con asíntotas similares pero
mejor comportamiento en los extremos del rango.
Conversión en el firmware
// sensors.c:505-509
int16_t ln_index = (raw_filtered + calib.c) / 4;
float ln = get_ln_value(ln_index);
int16_t distance_mm = (int16_t)((calib.a / ln - calib.b) * 1000.0f);
El firmware usa una LUT de 1024 entradas que almacena ln(index × 4). La
división entera por 4 introduce un error de cuantificación < 0.5% en distancia.
El notebook simula esta cuantificación y reporta el error introducido.
Estructura del Notebook
| Celda | Contenido |
|---|---|
| 0 | Imports: numpy, pandas, matplotlib, scipy.optimize.curve_fit |
| 1 | Datos de calibración: arrays de 26 valores raw por sensor, ACTIVE_DATASETS, PLOT_MODE |
| 2 | Grid 2×2 con valores raw de todos los robots superpuestos |
| 3 | Funciones: raw_to_distance(), raw_to_distance_firmware(), estimate_p0(), compute_metrics() |
| 4 | Selección de rangos de ajuste frontales y laterales |
| 5 | Ajuste de curvas con curve_fit (Levenberg-Marquardt), imprime a,b,c ± incertidumbre + R²/RMSE |
| 6 | Análisis de error: .describe(), RMSE por rangos, error de cuantificación LUT |
| 7 | Gráficas de error y curvas ajustadas |
| 8 | Structs C para copiar al firmware, agrupados por robot |
Flujo de Trabajo
flowchart TD
A[Tomar medidas: raw vs distancia] --> B[Añadir datos al notebook]
B --> C[Ajustar rangos de interés]
C --> D[Ejecutar curve_fit]
D --> E{¿RMSE < 5 mm?}
E -->|Sí| F[Validar error de LUT]
E -->|No| G[Revisar datos o p0]
G --> D
F --> H{¿Error LUT < 3 mm?}
H -->|Sí| I[Copiar structs C a sensors.c]
H -->|No| J[Reajustar con modelo firmware]
J --> D
Rangos de ajuste
| Sensor | Rangos de ajuste | Rango excluido |
|---|---|---|
| Frontales | 20–70 mm y 100–150 mm | 70–100 mm |
| Laterales | 5–90 mm y 100–170 mm | 90–100 mm |
Los rangos excluidos son distancias de transición donde la precisión es menos crítica para la navegación.
Ajuste de curvas
Se usa scipy.optimize.curve_fit con Levenberg-Marquardt. estimate_p0()
calcula valores iniciales a partir de los extremos del rango. Cada sensor se
ajusta independientemente con bounds específicos:
| Tipo | Bounds a |
Bounds b |
Bounds c |
|---|---|---|---|
| Frontales | [−10, 10] | [−1, 1] | [−200, 200] |
| Laterales | [−5, 5] | [−2, 2] | [−300, 300] |
Integración con el Firmware
Dónde se copian las constantes
source_code/src/sensors.c — función
set_sensors_robot_calibration() (línea 67).
Las constantes se almacenan por versión de robot (ZOROBOT3_A, ZOROBOT3_B,
ZOROBOT3_C). La celda 8 del notebook imprime los structs C listos para copiar.
Procesamiento en tiempo real
En update_sensors_magics(), cada ciclo:
- Cálculo de
raw_filtered(mediana de 3 lecturas) ln_index = (raw_filtered + c) / 4- Búsqueda en LUT:
ln = get_ln_value(ln_index) distance_mm = (a / ln - b) × 1000- Aplicación de offsets geométricos (
ROBOT_FRONT_LENGTH,ROBOT_MIDDLE_WIDTH) - Filtro paso-bajo con α adaptativo (0.2 normal, 0.6 para cambios grandes)
- Aplicación del offset de calibración de EEPROM (
sensors_distance_offset)
Guía de Uso
Requisitos
pip install numpy pandas matplotlib scipy
Procedimiento para un robot nuevo
- Tomar medidas: colocar el robot a distancias conocidas (0–250 mm, pasos de 10 mm) y registrar el raw de cada sensor
- Añadir datos: nueva entrada en
DATASETS(celda 1) con arrays de 26 valores (orden: 250 mm → 0 mm) - Ajustar rangos en celda 4 si es necesario
- Ejecutar
Cell > Run All - Verificar: RMSE < 5 mm en rangos ajustados,
ano negativo, error LUT < 3 mm - Copiar al firmware: salida de la celda 8 →
set_sensors_robot_calibration()
Solución de problemas
| Síntoma | Causa probable | Solución |
|---|---|---|
a negativo |
Datos no siguen el modelo logarítmico | Revisar mediciones, verificar que raw decrece con la distancia |
| Error grande en rangos excluidos | Curva no extrapola bien | Ampliar rangos de ajuste en celda 4 |
| RMSE > 10 mm todos los sensores | Datos ruidosos o mal tomados | Repetir mediciones, verificar iluminación ambiental |
| LUT da resultados distintos | Error de cuantificación | Si > 3 mm, usar raw_to_distance_firmware() en curve_fit |
Documento generado el 2026-06-25. Ver también Sensores, Calibración, EEPROM.