Seguidor de Lineas
El robot seguidor de lineas mecánicamente consiste en una estructura con dos ruedas para realizar tracción diferencial, y una rueda de giro libre (rueda loca) que sirve solo como apoyo. Para seguir una linea (negra sobre un piso blanco) se detecta el rebote-infrarrojo a corta distancia del piso. Pueden usarse distintas cantidad de sensores infrarrojos, dando lugar a distintos programaciones del robot, en este caso se usaron 3 sensores infrarrojos.
El armado se realizó con bloques plásticos Rasti, usando dos motores DC y cajas reductoras. Se hizo de forma desmontable, para poder reemplazar fácilmente las pilas. Se usaron 5 pilas recargables de 1.2 V, que juntas nos dan 6 V cuando están plenamente cargadas. En la Fig. 1 se puede ver el armazón con los dos motores y ruedas, la caja portapilas realizadas también con ladrillos, y el conjunto de una Arduino UNO R3 con dos shields encima: una Direct y una Motor.
En la Fig. 2 se muestra el detalle de los tres sensores infrarrojos (en bloques azules) y delante de los mismos se colocó un led blanco que se usó para probar iluminar la pista para mejorar la respuesta ante distintas condiciones de iluminación ambiente. La utilidad de ese led blanco es dependiente del grado de iluminación ambiente. En la parte trasera se puede ver el apoyo utilizado, que finalmente fue un tornillo de cabeza esférica que se comportó mejor que las ruedas locas anteriormente usadas.
En la Fig. 3 se puede ver el conjunto con el porta-pilas colocado, y en la Fig. 4 el conjunto completo armado listo para funcionar. El sensor de toque de la parte posterior sirve para arrancar y para pausar el movimiento de los motores.
Finalmente en la Fig. 5 se puede ver al robot al comienzo de la vuelta, y en la Fig. 6 trabajando. El led verde en el frente se programó para que se encendiera cuando ambas ruedas iban hacia adelante, y que se apagara en todos los otros casos.
Fig. 1
Fig. 2
Fig. 3
Fig. 5
Fig. 6
Fig. 4
PROGRAMA
PROGRAMA
/*
Actividad FreeSensors: Seguidor de linea
Usa tres módulos de rebote infrarrojo (TCRT5000) y 2 motores Rasti 6V conectados
a una shield FSmotor (pueden tener distintas velocidades relativas).
La entrada de boton sirve para detener y rearrancar el robot, un led verde indica
cuando se mueve hacia adelante, y un led blanco ilumina el camino cerca de los
sensores.
*/
#include <FreeSensors.h>
FSdirect P1;
FSmotor P2;
// Lecturas analogicas sensores infrarrojos
int sensDer;
int sensCen;
int sensIzq;
int umbral = 800;
// Variables booleanas sensores infrarrojos
boolean blancoDer;
boolean negroCen;
boolean blancoIzq;
// Variables auxiliares
boolean boton;
boolean parado;
boolean inicio;
boolean final;
boolean retrocediendo;
// Motor1 es el de la derecha, M2 es el de la izquierda
byte velocM1 = 200;
byte velocM2 = 200;
void setup() {
P1.begin();
P1.pinMode(DIO1, OUTPUT); // LED verde
P1.pinMode(DIO2, OUTPUT); // LED blanco
P1.pinMode(DIO4, INPUT); // Boton
P1.digitalWrite(DIO1, LOW); // LED verde empieza apagado
P1.digitalWrite(DIO2, HIGH); // LED blanco empieza y queda prendido
P2.begin(PCF_010);
P2.m1.stop();
P2.m2.stop();
parado = true;
inicio = true;
final = false;
retrocediendo = false;
}
void loop() {
sensDer = P1.analogRead(AI1);
delay(10);
sensCen = P1.analogRead(AI2);
delay(10);
sensIzq = P1.analogRead(AI3);
delay(10);
blancoDer = sensDer > umbral;
negroCen = sensCen < umbral;
blancoIzq = sensIzq > umbral;
boton = (P1.digitalRead(DIO4)==HIGH);
if (boton) {
delay(300);
if (parado) {
parado = false;
} else {
P2.m1.stop();
P2.m2.stop();
P1.digitalWrite(DIO1, LOW);
parado = true;
}
}
if (parado) return;
if (retrocediendo) {
delay(750);
P2.m1.stop();
P2.m2.stop();
retrocediendo = false;
}
if (!blancoIzq && negroCen && !blancoDer) {
if (inicio) {
// Todos en negro sobre la linea de inicio: Arrancar
P2.m1.forward(velocM1);
P2.m2.forward(velocM2);
P1.digitalWrite(DIO1, HIGH);
delay(1000);
inicio = false;
} else {
// Todos en negro sobre la linea de final: Detenerse
if (final) {
P2.m1.stop();
P2.m2.stop();
} else {
delay(200);
final = true;
}
}
}
if (blancoIzq && !negroCen && blancoDer) {
// Todos en blanco: Retroceder 0.75 seg. y detenerse
if (!retrocediendo) {
P2.m1.backward(150);
P2.m2.backward(150);
retrocediendo = true;
}
P1.digitalWrite(DIO1, LOW);
inicio = false;
final = false;
}
if (blancoIzq && negroCen && blancoDer) {
// Sobre la linea: Continuar
P2.m1.forward(velocM1);
P2.m2.forward(velocM2);
P1.digitalWrite(DIO1, HIGH);
inicio = false;
final = false;
}
if (!blancoIzq && !negroCen && blancoDer) {
// Se sale para la derecha: girar a la izquierda
P2.m1.forward(velocM1);
P2.m2.backward(velocM2);
P1.digitalWrite(DIO1, LOW);
inicio = false;
final = false;
}
if (blancoIzq && !negroCen && !blancoDer) {
// Se sale para la izquierda: girar a la derecha
P2.m1.backward(velocM1);
P2.m2.forward(velocM2);
P1.digitalWrite(DIO1, LOW);
inicio = false;
final = false;
}
}