01 · Punto de partida
Cerrar el lazo
Un seguidor de línea es un lazo cerrado clásico (tema 40): la referencia es «la línea en el centro», la medición es la posición p que estima el arreglo de sensores (tema 30, positiva hacia la izquierda), el error es directamente p (porque la referencia es 0) y el actuador es la diferencia de velocidad entre las ruedas (tema 26).
En el control todo o nada, el robot corrige con la misma fuerza sin importar cuánto se desvió, y zigzaguea. En el control proporcional, la corrección es proporcional al error: pequeña cerca del centro, grande lejos. Se obtiene una trayectoria suave, y se pueden usar velocidades mayores.
Este tema anticipa ideas que el tema 41 en adelante desarrolla con más generalidad (respuesta de un sistema, control PID). Aquí las vemos en un caso concreto, con un simulador, antes de la teoría.
02 · De la medición a las ruedas
La ley proporcional y las ruedas
La ley de control más directa le pide al robot una velocidad angular proporcional al error:
La primera ecuación es el control; las otras dos son la cinemática inversa del tema 26. Con la convención de signos de los temas 20 y 30, si la línea está a la izquierda (p > 0) el robot debe girar a la izquierda (ω > 0): la rueda derecha acelera y la izquierda frena. La velocidad media v se mantiene: la corrección reparte velocidad entre las ruedas.
La ganancia K tiene unidades de rad/s por mm: cuántos rad/s de giro se piden por cada milímetro de error. Con K = 0,1 rad/s/mm, v = 200 mm/s y b = 150 mm, una línea a 12 mm a la izquierda da ω = 1,2 rad/s, vL = 200 − 90 = 110 mm/s y vR = 290 mm/s.
En muchos robots pequeños se escribe de forma equivalente en unidades de PWM: PWMizq = base − Kp·p y PWMder = base + Kp·p. Es la misma idea con otra escala; así lo hace el sketch de este tema. La forma con ω y v tiene la ventaja de que la ganancia tiene un significado físico y es independiente de las unidades del driver.
03 · Entender antes de ajustar
Qué pasa en el lazo: un modelo
Un modelo simple explica la mayor parte del comportamiento. Sea y el desplazamiento lateral del robot respecto de una línea recta, ψ el ángulo entre el robot y la línea, y L la distancia del arreglo al eje de las ruedas. Para ángulos pequeños, el robot avanza lateralmente ẏ = v·ψ, gira ψ̇ = ω, y el arreglo, que está adelantado, ve la línea en:
(el signo menos aparece porque si el robot está a la izquierda de la línea, y > 0, la línea queda a su derecha). Con la ley ω = K·p:
Es un oscilador amortiguado. La frecuencia natural ωn dice qué tan rápido responde; el amortiguamiento ζ dice si oscila (ζ < 1) o no. Se leen cuatro conclusiones que se confirman en el simulador:
- Subir
Khace al robot más rápido (ωn ∝ √K) y más amortiguado (ζ ∝ √K), en el modelo ideal. - Un arreglo más adelantado (
Lmayor) amortigua más: «ve venir» el error y corrige antes. Un arreglo pegado al eje (Lchico) oscila con facilidad. - Ir más rápido (
vmayor) reduce el amortiguamiento: el robot se aleja más antes de que la corrección actúe. - Con
ζmayor que 1 no hay oscilación, pero hay una respuesta lenta siKes chico.
Este modelo no incluye tres cosas reales que lo limitan: el retardo del motor (la velocidad angular no responde de inmediato), el muestreo (se mide cada 10 o 20 ms) y la saturación (las ruedas tienen una velocidad máxima). Son las que ponen un techo a la ganancia.
04 · El ajuste
Elegir la ganancia
Con la simulación del lazo (retardo del motor de 80 ms, ciclo de 20 ms, v = 200 mm/s, L = 60 mm, desvío inicial de 15 mm) se observan los siguientes comportamientos:
| K (rad/s/mm) | ζ | ωn (rad/s) | Qué se observa |
|---|---|---|---|
| 0,01 | 0,21 | 1,4 | Lento y oscilatorio: no se asienta en 6 s |
| 0,03 | 0,37 | 2,4 | Oscila cinco veces; se asienta en 2,7 s |
| 0,10 | 0,67 | 4,5 | Casi sin oscilar; se asienta en 0,76 s |
| 0,30 | 1,16 | 7,7 | Sin oscilación; 0,48 s |
| 2,0 | 3,0 | 20 | Rápido, pero «tiembla»: ciclo límite de unos 1 mm |
El patrón es el esperado: una ganancia demasiado baja es lenta y se queda oscilando; una media es buena; una muy alta responde rápido pero amplifica el ruido y el retardo y produce un temblor permanente (un ciclo límite, porque la saturación de las ruedas impide que diverja). Más allá de cierto punto, subir K ya no mejora nada y solo desgasta mecánica y consume energía.
El retardo del motor es el enemigo de una ganancia alta. Con K = 0,5: sin retardo se asienta en 0,14 s; con 80 ms, en 0,59 s; con 200 ms tarda 5,2 s y oscila 2 mm; con 300 ms, el robot pierde la línea. La ganancia máxima útil la fija el retardo, no el sensor.
Y el arreglo cercano al eje oscila: con L = 20 mm y K = 0,1, el amortiguamiento cae a 0,22 y queda una oscilación de 10 mm de amplitud que nunca se apaga; con L = 100 mm, se asienta en 0,5 s. Para pasar de una ganancia que funciona a una buena, se sube K hasta que empiece a temblar y se la baja un 30 a 50 %.
05 · Un límite del proporcional puro
Curvas: el error permanente
En una curva de radio R (curvatura κ = 1/R), el robot necesita girar a ω = v·κ para acompañarla. Pero con la ley proporcional ω = K·p solo gira si p ≠ 0. El equilibrio se alcanza cuando:
Es decir, el robot sigue la curva pero con la línea desplazada del centro. Con v = 200 mm/s y R = 500 mm, v·κ = 0,4 rad/s: con K = 0,05 el error es de 8 mm; con 0,1, 4 mm; con 0,2, 2 mm (el simulador lo confirma). En una curva de 300 mm de radio, v·κ = 0,67 rad/s y los errores son 13,3; 6,7 y 3,3 mm.
Y hay un peligro: si ese error permanente supera la semi-cobertura del arreglo (24 mm), la línea se pierde. Con K = 0,02 el robot pierde la línea a los pocos instantes en ambas curvas. La ganancia mínima para sostener una curva es K ≥ v·κ / h: con h = 24 mm, v = 200 mm/s y R = 300 mm, K ≥ 0,028, y en la práctica el doble o más.
Dos formas de reducir ese error:
- Subir K, con las limitaciones de la sección anterior.
- Ir más lento en las curvas. El error es proporcional a la velocidad. Una velocidad adaptativa, que baja cuando el error crece, ayuda: en la curva de 300 mm con
K = 0,1, el error pasa de 6,7 a 5,7 mm bajando la velocidad hasta el 40 % cuando la línea se acerca al borde del arreglo.
La solución de fondo es agregar un término que acumule el error (integral) o uno que anticipe la curva (avance). Eso es el control PID del tema 43. Por ahora, basta saber que un proporcional puro siempre deja un error en curva.
06 · Hasta dónde se puede apurar
Velocidad base y saturación
La corrección depende de que las ruedas puedan alcanzar v ± ω·b/2. Si la rueda exterior llega a su máximo Vmáx, el giro disponible se limita:
Con Vmáx = 300 mm/s, b = 150 mm y v = 200 mm/s, el giro máximo es 1,33 rad/s. Con v = 280 mm/s, solo 0,27 rad/s: el robot va casi a tope y casi no puede doblar. Es un compromiso entre velocidad y capacidad de corrección. En el simulador, con v = 280 mm/s el mismo desvío de 15 mm tarda 1,85 s en corregirse, contra 0,76 s a 200 mm/s.
Por eso se deja margen: la velocidad base se elige por debajo del máximo de los motores, para conservar autoridad de dirección. Las políticas de saturación del tema 26 se aplican igual: escalar conserva la curva, recortar rueda por rueda la deforma.
Otra práctica útil, que mencionamos en el tema 30: bajar la velocidad según el error. Cuando la línea se aparta del centro, el robot ya se está saliendo y necesita más tiempo y más autoridad; con la línea centrada, puede ir más rápido. Un esquema simple es v = v0·(1 − 0,6·mín(1, |p|/h)).
07 · Cuando el lazo no alcanza
Línea perdida y otros casos
El controlador proporcional solo sabe qué hacer si ve la línea. Los casos de borde del tema 30 —línea perdida, cruces, curvas cerradas— quedan fuera de su alcance y se resuelven con una máquina de estados alrededor del lazo:
- SIGUIENDO: hay línea, se aplica el control proporcional y se recuerda el último lado visto.
- BUSCANDO: no hay línea; se gira en el lugar hacia el último lado con un tiempo máximo. Si la línea reaparece, vuelve a SIGUIENDO.
- DETENIDO: se agotó el tiempo de búsqueda, o hubo un comando de parada.
Un lazo bien ajustado pierde menos la línea, pero ninguno la pierde nunca: el esquema de búsqueda es parte del diseño. Agregarle estados para cruces, marcas y curvas de ángulo recto da un comportamiento más completo; la forma de organizar muchos comportamientos es el tema de la arquitectura de subsunción (tema 33).
Y siempre un comando de parada y un tope de PWM: el seguidor es un sistema en movimiento y un error de signo o una ganancia mal puesta lo lanza fuera de la pista.
08 · Código para la placa
Seguidor proporcional en Arduino
Supuestos que debés verificar: UNO R3; arreglo de cinco sensores en A0 a A4 como en el tema 30; un driver con entradas de PWM y de sentido por lado (izquierdo: PWM en D5 y sentido en D7; derecho: PWM en D6 y sentido en D8); alimentación de motores adecuada. Los valores de PWM_BASE y KP son un punto de partida: dependen de tus motores y baterías.
// Seguidor de línea con control proporcional. Sensores: 5 reflectivos en A0..A4 (A0 = izquierda extrema).
// Motores: driver con entradas PWM y sentido por lado. ¡Probalo primero con las ruedas en el aire!
const byte N = 5;
const byte PIN_SENSOR[N] = {A0, A1, A2, A3, A4};
const float SEPARACION = 10.0; // mm entre sensores
const bool LINEA_OSCURA = true; // invertir si la lectura sube sobre la línea
const int COMPUERTA = 100; // lecturas normalizadas menores se ignoran (ruido)
const byte PIN_PWM_IZQ = 5, PIN_DIR_IZQ = 7, PIN_PWM_DER = 6, PIN_DIR_DER = 8;
const int PWM_BASE = 110; // velocidad de crucero (unidades de PWM)
const float KP = 3.0; // PWM por mm de error: empezar bajo y subir de a poco
const int PWM_MAX = 200; // tope de seguridad por rueda
const int PWM_BUSQUEDA = 90; // giro en el lugar al buscar la línea
const unsigned long BUSQUEDA_MAX_MS = 800; // tiempo máximo de búsqueda antes de detenerse
const unsigned long PERIODO_MS = 10, IMPRESION_MS = 250, CALIBRACION_MS = 3000;
enum Estado { DETENIDO, SIGUIENDO, BUSCANDO };
Estado estado = DETENIDO;
int minimo[N], maximo[N], q[N];
int ultimoLado = 1; // +1 = la línea se vio por la izquierda, -1 = por la derecha
bool calibrado = false;
unsigned long ultimo = 0, ultimaImpresion = 0, inicioBusqueda = 0;
void mover(int izq, int der) { // valores de -255 a 255; el signo da el sentido
izq = constrain(izq, -PWM_MAX, PWM_MAX);
der = constrain(der, -PWM_MAX, PWM_MAX);
digitalWrite(PIN_DIR_IZQ, izq >= 0 ? HIGH : LOW);
digitalWrite(PIN_DIR_DER, der >= 0 ? HIGH : LOW);
analogWrite(PIN_PWM_IZQ, abs(izq));
analogWrite(PIN_PWM_DER, abs(der));
}
void detener() { mover(0, 0); estado = DETENIDO; }
void calibrar() {
detener();
for (byte i = 0; i < N; i++) { minimo[i] = 1023; maximo[i] = 0; }
Serial.println("Calibrando 3 s: pasá el arreglo sobre la línea y el fondo");
const unsigned long inicio = millis();
while (millis() - inicio < CALIBRACION_MS) {
for (byte i = 0; i < N; i++) {
const int v = analogRead(PIN_SENSOR[i]);
minimo[i] = min(minimo[i], v);
maximo[i] = max(maximo[i], v);
}
}
calibrado = true;
for (byte i = 0; i < N; i++) if (maximo[i] - minimo[i] < 100) { calibrado = false; Serial.println("Contraste bajo: revisá altura, luz y cableado"); break; }
}
void leer() { // q[i]: 0 = fondo, 1000 = línea
for (byte i = 0; i < N; i++) {
const long rango = max(1, maximo[i] - minimo[i]);
const long v = analogRead(PIN_SENSOR[i]);
q[i] = constrain(LINEA_OSCURA ? (maximo[i] - v) * 1000L / rango : (v - minimo[i]) * 1000L / rango, 0, 1000);
}
}
bool posicion(float &mm) { // promedio ponderado, positivo hacia la izquierda
long suma = 0;
float acumulado = 0;
for (byte i = 0; i < N; i++) {
if (q[i] < COMPUERTA) continue;
suma += q[i];
acumulado += ((N - 1) / 2.0 - i) * SEPARACION * q[i];
}
if (suma == 0) return false;
mm = acumulado / suma;
return true;
}
void setup() {
const byte pines[] = {PIN_PWM_IZQ, PIN_DIR_IZQ, PIN_PWM_DER, PIN_DIR_DER};
for (byte i = 0; i < 4; i++) { digitalWrite(pines[i], LOW); pinMode(pines[i], OUTPUT); }
Serial.begin(115200);
Serial.println("C: calibrar; G: seguir la línea; S: detener");
calibrar();
}
void loop() {
if (Serial.available() > 0) {
const char cmd = toupper(Serial.read());
if (cmd == 'S') detener();
else if (cmd == 'C') calibrar();
else if (cmd == 'G') {
if (calibrado) estado = SIGUIENDO; else Serial.println("Primero calibrá (C)");
}
}
const unsigned long ahora = millis();
if (ahora - ultimo < PERIODO_MS) return;
ultimo = ahora;
leer();
float p = 0;
const bool hayLinea = posicion(p);
int izq = 0, der = 0;
if (estado == SIGUIENDO) {
if (hayLinea) {
ultimoLado = (p >= 0) ? 1 : -1;
const int u = (int)(KP * p); // línea a la izquierda (p > 0): izquierda más lenta, derecha más rápida
izq = PWM_BASE - u;
der = PWM_BASE + u;
} else {
estado = BUSCANDO;
inicioBusqueda = ahora;
}
}
if (estado == BUSCANDO) {
if (hayLinea) estado = SIGUIENDO;
else if (ahora - inicioBusqueda > BUSQUEDA_MAX_MS) { detener(); Serial.println("Linea perdida: detenido"); }
else { izq = -ultimoLado * PWM_BUSQUEDA; der = ultimoLado * PWM_BUSQUEDA; } // girar hacia donde se vio la línea
}
if (estado != DETENIDO) mover(izq, der);
if (ahora - ultimaImpresion >= IMPRESION_MS) {
ultimaImpresion = ahora;
Serial.print(estado == SIGUIENDO ? "SIGUIENDO" : estado == BUSCANDO ? "BUSCANDO" : "DETENIDO");
Serial.print(" p="); if (hayLinea) Serial.print(p, 1); else Serial.print("--");
Serial.print(" mm izq="); Serial.print(izq); Serial.print(" der="); Serial.println(der);
}
}
Cómo se usa: abrí el monitor serie, dejá que calibre pasando el arreglo sobre la línea y el fondo, y apoyá el robot sobre la pista. Con G empieza a seguir; con S se detiene; con C recalibra. Cada 250 ms imprime el estado, la posición y las órdenes a las ruedas, por ejemplo SIGUIENDO p=8.0 mm izq=86 der=134: la línea está a la izquierda y la rueda derecha va más rápido.
Procedimiento de ajuste, con el robot sobre la pista y la mano cerca del interruptor: empezá con KP bajo (por ejemplo 1), subilo de a poco hasta que el robot empiece a oscilar o a temblar sobre la línea, y bajalo entre un 30 y un 50 %. Después probá PWM_BASE más alto y repetí el ajuste, porque a mayor velocidad hace falta más amortiguamiento. Los motores tienen zona muerta (tema 13): valores de PWM muy bajos no mueven la rueda.
Notas: el control es de lazo abierto en velocidad (la corrección es en PWM); si tenés encoders y lazos de velocidad (tema 18), podés comandar vL y vR con la ley de este tema y obtener un comportamiento más repetible con la batería y la carga. El sketch trata como línea perdida la ausencia de lecturas sobre la compuerta; no distingue cruces ni curvas cerradas (tema 30).
09 · Exploración interactiva
Laboratorios: seguir una línea y repartir velocidad
1. El lazo en acción
Se simula el robot con la ley proporcional durante 6 s, con motor de primer orden, ciclo de control de 20 ms y las ruedas limitadas a 300 mm/s. La curva lima es la posición de la línea vista por el arreglo (lo que el controlador intenta llevar a cero). Las líneas punteadas violetas marcan el límite del arreglo (±24 mm). Si la curva lo cruza, el robot pierde la línea (marca roja).
Elegí los parámetros.
Con los valores iniciales (K = 0,1, recta) el robot corrige el desvío de 15 mm y se asienta en 0,76 s sin oscilar. Bajá K a 0,01: oscila y no termina de asentarse en 6 s. Subila a 2: rápido pero tiembla un milímetro. Poné L = 20 mm: oscilación sostenida de unos 10 mm. Poné el retardo en 0,3 s con K = 0,5 (índice 7): pierde la línea. En la curva de 500 mm, K = 0,1 deja 4 mm de error permanente; con K = 0,02, pierde la línea. En la de 300 mm con K = 0,1, 6,7 mm, y con velocidad adaptativa, 5,7 mm.
2. De la posición a las ruedas
Elegí una posición de la línea, la ganancia y la velocidad base. El laboratorio calcula la velocidad angular pedida, las velocidades de cada rueda (b = 150 mm, máximo 300 mm/s por rueda) y el radio de la curva que describe.
Elegí la posición de la línea.
Con p = +12 mm, K = 0,1 y v = 200 mm/s: ω = 1,2 rad/s, ruedas a 110 y 290 mm/s, radio de unos 167 mm. Con p = +20 mm, la corrección pedida (2 rad/s) supera el máximo permitido (1,33 rad/s): ω se limita, las ruedas quedan en 100 y 300 mm/s y la corrección es menor que la deseada. Con v = 280 mm/s casi no hay margen de giro. Cambiá el signo de p: las ruedas se intercambian.
10 · Código ejecutable
Simular el lazo en Python
Replicamos el simulador del laboratorio: el modelo del lazo con retardo de motor, muestreo y saturación, métricas de asentamiento y oscilación, el error en curvas y el efecto de la velocidad adaptativa. Sirve para probar combinaciones de parámetros antes de llevarlas al robot.
Probalo en el navegador. Python se descarga con Pyodide la primera vez y requiere conexión. El código es editable y no controla ningún robot.
import math
B, V_RUEDA_MAX, H = 150.0, 300.0, 24.0 # mm, mm/s, semi-cobertura del arreglo (mm)
DT, CICLO = 0.005, 4 # paso de simulación y pasos por ciclo de control (20 ms)
def simular(K, v0=200.0, L=60.0, tau_m=0.08, kappa=0.0, adaptativa=False, y0=-15.0, psi0=0.0, duracion=6.0):
y, psi, w_real, w_cmd, v = y0, psi0, 0.0, 0.0, v0
serie = []
for k in range(round(duracion / DT)):
p = -(y + L * math.sin(psi))
if k % CICLO == 0:
if abs(p) > H:
return serie, True
v = v0 * (1 - 0.6 * min(1.0, abs(p) / H)) if adaptativa else v0
w_max = max(0.0, 2 * (V_RUEDA_MAX - v) / B)
w_cmd = max(-w_max, min(w_max, K * p))
w_real += (w_cmd - w_real) * DT / tau_m if tau_m > 0 else (w_cmd - w_real)
y += v * math.sin(psi) * DT
psi += (w_real - v * kappa * math.cos(psi)) * DT
serie.append(p)
return serie, False
def metricas(serie, perdio):
if perdio:
return "pierde la linea", max((abs(p) for p in serie), default=0.0), None, None
maximo = max(abs(p) for p in serie)
asent = next((i for i in range(len(serie) - 1, -1, -1) if abs(serie[i]) > 2.0), -1)
final = sum(serie[-200:]) / 200
cruces = sum(1 for a, b in zip(serie[40:], serie[41:]) if a * b < 0)
return "sigue", maximo, (asent + 1) * DT, (final, cruces)
v0, L = 200.0, 60.0
print("Modelo lineal: wn = sqrt(v*K), zeta = (L/2)*sqrt(K/v)")
for K in (0.01, 0.03, 0.1, 0.3, 1.0):
wn, zeta = math.sqrt(v0 * K), L / 2 * math.sqrt(K / v0)
serie, perdio = simular(K)
estado, maximo, asent, extra = metricas(serie, perdio)
if perdio:
print(f"K={K:5.2f}: wn={wn:4.2f} rad/s zeta={zeta:4.2f} -> {estado} (error maximo {maximo:.1f} mm)")
else:
print(f"K={K:5.2f}: wn={wn:4.2f} rad/s zeta={zeta:4.2f} -> {estado}; error maximo={maximo:5.1f} mm; "
f"asentamiento={asent:4.2f} s; cruces por cero={extra[1]}; error final={extra[0]:.2f} mm")
print("Curva de radio 500 mm a 200 mm/s (vk = 0,4 rad/s):")
for K in (0.05, 0.1, 0.2):
serie, perdio = simular(K, kappa=1 / 500, y0=0.0)
estado, maximo, asent, extra = metricas(serie, perdio)
teorico = v0 / 500 / K
print(f"K={K:4.2f}: error teorico v*k/K={teorico:5.1f} mm -> {estado}" + ("" if perdio else f"; error final={extra[0]:.1f} mm"))
print("Velocidad adaptativa en la curva con K=0,1:", end=" ")
serie, perdio = simular(0.1, kappa=1 / 300, y0=0.0, adaptativa=False)
serie2, perdio2 = simular(0.1, kappa=1 / 300, y0=0.0, adaptativa=True)
print("sin adaptar:", "pierde la linea" if perdio else f"error final {sum(serie[-200:]) / 200:.1f} mm", "| adaptativa:",
"pierde la linea" if perdio2 else f"error final {sum(serie2[-200:]) / 200:.1f} mm")Con K de 0,01 a 1,0 el modelo da ζ de 0,21 a 2,12; el desvío de 15 mm se asienta en más de 6 s con K = 0,01, en 2,69 s con 0,03 y en 0,76 s con 0,1. En la curva de 500 mm, el error permanente medido es 8,0; 4,0 y 2,0 mm para K de 0,05; 0,10 y 0,20, igual que v·κ/K. En la de 300 mm con K = 0,1, la velocidad adaptativa baja el error de 6,7 a 5,7 mm.
Probá tau_m = 0.3 con K = 0,5 y mirá cómo se pierde la línea; L = 20 y la oscilación sostenida; y v0 = 280 con una curva. Agregá un tercer valor de velocidad adaptativa o ruido en p y observá qué ganancia aguanta.
11 · Método y diagnóstico
Ajuste en la pista y diagnóstico
- Verificá primero los signos: con la línea a la izquierda, el robot debe girar a la izquierda. Probalo con las ruedas en el aire, acercando la línea a un lado del arreglo.
- Empezá con ganancia baja y velocidad baja, y verificá que el robot sigue una recta larga.
- Subí la ganancia hasta que empiece a oscilar; bajala un 30 a 50 %. Anotá el valor.
- Subí la velocidad de a poco y repetí el ajuste de la ganancia en cada paso.
- Probá curvas de radio decreciente y anotá el radio mínimo que sigue; compará con
v·κ/K. - Probá con la batería cargada y casi descargada: la velocidad de los motores cambia y el ajuste con ella.
- Provocá la pérdida de la línea (levantando el arreglo) y verificá la búsqueda y el tiempo máximo de parada.
«Cuanto más alta la ganancia, mejor sigue»
Hasta un punto. Con retardo de motor y muestreo, una ganancia alta produce temblor permanente y desgasta la mecánica. Hay un valor útil, no un máximo.
«Si oscila, bajo la velocidad y listo»
Ayuda (el amortiguamiento crece al bajar v), pero la causa puede ser un arreglo demasiado cerca del eje o un motor lento. Conviene entender cuál.
«En las curvas el robot va descentrado: hay un sensor mal»
Es el error permanente del control proporcional: v·κ/K. No es un fallo, es un límite del método.
«Se sale de la pista en las curvas cerradas»
Posibles causas: velocidad alta para ese radio, ganancia baja (error permanente mayor que la cobertura), saturación de las ruedas o arreglo demasiado angosto. Bajá la velocidad y revisá los números.
«Cambié la batería y ya no sigue igual»
La velocidad de los motores depende de la tensión. Sin lazo de velocidad (tema 18), el ajuste cambia con la batería; con él, es más repetible.
«El robot oscila aunque la ganancia es baja»
Revisá L (arreglo muy pegado al eje), el retardo (un driver o un filtro lentos), el signo de uno de los motores, o holguras mecánicas.
12 · Práctica guiada
Predecí antes de comprobar
1. De posición a ruedas
Con K = 0,1 rad/s/mm, v = 200 mm/s, b = 150 mm y la línea 12 mm a la izquierda, ¿cuánto valen ω y las velocidades de rueda? ¿Hay saturación?
Ver solución
ω = 0,1 × 12 = 1,2 rad/s. vL = 200 − 1,2·75 = 110 mm/s, vR = 290 mm/s. El máximo de giro es 2(300 − 200)/150 = 1,33: no satura.
2. Saturación
Con los mismos datos y la línea a 20 mm, ¿qué ocurre?
Ver solución
Se pediría ω = 2 rad/s, pero el máximo es 1,33. Se aplica 1,33: vL = 100 mm/s y vR = 300 mm/s. La corrección es menor que la deseada.
3. Amortiguamiento
Con v = 200 mm/s, L = 60 mm y K = 0,03, ¿cuánto valen ωn y ζ? ¿Oscila?
Ver solución
ωn = √(200·0,03) ≈ 2,45 rad/s; ζ = 30·√(0,03/200) ≈ 0,37. Es subamortiguado: oscila.
4. Error en curva
Con v = 150 mm/s, curva de 400 mm de radio y K = 0,05, ¿qué error permanente se espera? ¿Y con K = 0,01?
Ver solución
v·κ = 150/400 = 0,375 rad/s. Con 0,05: 0,375/0,05 = 7,5 mm. Con 0,01: 37,5 mm, mayor que 24 mm: pierde la línea.
5. Ganancia mínima
Para seguir una curva de 300 mm a 200 mm/s sin perder la línea (semi-cobertura 24 mm), ¿qué ganancia mínima hace falta?
Ver solución
K ≥ v·κ/h = (200/300)/24 ≈ 0,028. En la práctica el doble o más, para tener margen.
6. En unidades de PWM
Con PWM base 110 y Kp = 3 PWM/mm, la línea está a 10 mm a la derecha (p = −10). ¿Cuáles son los PWM de cada rueda?
Ver solución
u = 3·(−10) = −30. izq = 110 − (−30) = 140; der = 110 + (−30) = 80. La izquierda va más rápido: el robot gira a la derecha.
7. Arreglo adelantado
Con K = 0,1 y v = 200 mm/s, compará ζ para L = 20 mm y L = 60 mm. ¿Qué esperás en cada caso?
Ver solución
ζ = (L/2)√(K/v): con 20 mm, 10·0,0224 = 0,22 (oscila mucho); con 60 mm, 30·0,0224 = 0,67 (casi sin oscilar).
13 · Síntesis
Ideas para recordar
- Un seguidor proporcional pide
ω = K·py reparte velocidad entre las ruedas con la cinemática inversa:vL,R = v ∓ ω·b/2. - El modelo del lazo es un oscilador:
ωn = √(v·K)yζ = (L/2)·√(K/v). - Un arreglo más adelantado amortigua más; ir más rápido amortigua menos.
- La ganancia útil tiene techo: lo fijan el retardo del motor, el muestreo y la saturación; por encima, solo hay temblor.
- En curva, el proporcional puro deja un error permanente
v·κ/K; si supera la cobertura del arreglo, se pierde la línea. - La saturación limita el giro:
|ω| ≤ 2(Vmáx − v)/b. Hay que reservar margen de dirección. - Se necesita una máquina de estados alrededor del lazo: seguir, buscar con tiempo máximo y detener.
- El ajuste se hace en la pista: subir la ganancia hasta que tiemble, bajarla un 30 a 50 % y repetir al subir la velocidad.
¿Listo para el tema 32?
Antes de avanzar, ajustá tu seguidor (o el simulador) para una pista con una curva de radio conocido: calculá el error permanente esperado, la ganancia mínima y la velocidad máxima que admite. Anotá qué cambiarías para ir más rápido.
En el próximo tema cambiamos de entorno: la detección y evasión de obstáculos, con umbrales de distancia, giro de escape y recuperación.