Search (Don't Edit)

miércoles, 26 de junio de 2013

Robot seguidor de líneas con control de velocidad para Arduino

Actualización: el proyecto también lo podéis encontrar en github.

Ahora estoy con Arduino aplicado a la robótica y he empezado con lo que se considera el "Hola mundo" de la programación de robots autónomos: un seguidor de líneas.

La idea es un simple chasis con tres ruedas, dos de ellas motrices mediante sendos motores que controlamos mediante un driver en puente con el L298 (en mi caso he utilizado este). Controlando cada motor independientemente, podemos dirigir la dirección.

He utilizado también tres fotosensores cuyo cometido es saber cuando estamos centrados sobre la línea, nos hemos desviado a la derecha o a la izquierda, obrando en consecuencia para mantener el rumbo.

Cuando ninguno de ellos detecta la línea (en mis pruebas utilicé cinta aislante pegada directamente al suelo que es más o menos blanco) el robot interpreta que o bien ha finalizado el recorrido, o que está perdido, pero está programado que se detenga.

Para el cerebro utilizo un simple Arduino Duemilenove. El programa aparece más abajo y es autoexplicativo.

En mi caso aproveché las salidas PWM para ajustar la velocidad para, por ejemplo, evitar que, por inercia, en los giros perdiese la línea.

Este es el resultado de la primera versión:
Y el código utilizado a continuación:
/*Robot seguidor de líneas con control de velocidad para
Arduino Duemilanove w/ ATmega 328 y controlador de motor
Keyes L298.

José Pablo Hernández (condestable2000 at gmail.com)
23 de junio de 2013
*/
int SensorI = 8;//Pin del sensor izquierda
int SensorC = 7;//Pin del sensor centro
int SensorD = 6;//Pin del sensor derecha
int ValI = 0;//Valor sensor izquierda
int ValC = 0;//Valor sensor centro
int ValD = 0;//Valor sensor derecha
int Val = 0;//Valor combinado de los sensores
//Motor izquierda
int EnB = 10;//PWM motor izquierda
int In4 = 5;
int In3 = 4;
//Motor derecha
int EnA = 9;//PWM motor derecha
int In2 = 3;
int In1 = 2;
//Velocidades
int VMax = 180;
int VMin = 180;
//Sentido marcha
int adelante = 1;
int atras = 0;

void setup()
{
  //Serial.begin(9600);
  //Configuramos los pines de los sensores
  pinMode(SensorI, INPUT);
  pinMode(SensorC, INPUT);
  pinMode(SensorD, INPUT);
  //Configuramos los pines de los motores
  pinMode(In4, OUTPUT);
  pinMode(In3, OUTPUT);
  pinMode(In2, OUTPUT);
  pinMode(In1, OUTPUT);
}

void loop()
{
  //Los motores en principio adelante
    digitalWrite(In1, HIGH);
    digitalWrite(In2, LOW);
    digitalWrite(In3, HIGH);
    digitalWrite(In4, LOW);
  //Leemos los valores de cada uno de los tres sensores
  //1=blanco (no línea), 0=negro (línea)
    ValI = digitalRead(SensorI);
    ValC = digitalRead(SensorC);
    ValD = digitalRead(SensorD);
   //Combinamos los valores para que sea más fácil la comprobación
    Val = (ValI * 100) + (ValC * 10) + (ValD);
   //Actuamos en los motores según la lectura 
    switch (Val) 
    {
       case 10:
         //Estamos sobre la línea
         //Los dos motores hacia adelante
         marchaMotorD(adelante);
         marchaMotorI(adelante);
         //Los dos motores al 100%
         analogWrite(EnA, VMax);
         analogWrite(EnB, VMax);
         break;
        case 11:
         //Nos hemos deviado algo a la izquierda
         //Los dos motores hacia adelante
         marchaMotorD(adelante);
         marchaMotorI(adelante);
         //Reducimos motor derecha al 50%
         analogWrite(EnA, VMin);
         //Motor izquierda al 100%
         analogWrite(EnB, VMax);
         break;
        case 110:
         //Nos hemos desviado algo a la derecha
         //Los dos motores hacia adelante
         marchaMotorD(adelante);
         marchaMotorI(adelante);
         //Reducimos motor izquierda al 50%
         analogWrite(EnB, VMin);
         //Motor derecha al 100%
         analogWrite(EnA, VMax);
         break;
        case 100:
         //Nos hemos desviado mucho a la derecha
         //Los dos motores hacia adelante
         marchaMotorD(adelante);
         marchaMotorI(atras);
         //Reducimos motor izquierda al 50%
         analogWrite(EnB, VMin);
         //Motor derecha al 100%
         analogWrite(EnA, VMax);
         break;
        case 1:
         //Nos hemos desviado mucho a la izquierda
         //Los dos motores hacia adelante
         marchaMotorD(atras);
         marchaMotorI(adelante);
         //Reducimos motor derecha al 50%
         analogWrite(EnA, VMin);
         //Motor izquierda al 100%
         analogWrite(EnB, VMax);
         break;         
        default:
         //Hemos perdido la línea.
         //Paramos ambos motores
         analogWrite(EnA, 0);
         analogWrite(EnB, 0);
    }
}

void marchaMotorD (int sentidoMotor)
{
 if (sentidoMotor==adelante)
  { //Adelante
    digitalWrite(In1, HIGH);
    digitalWrite(In2, LOW);
  } 
  else
  { //Atrás
    digitalWrite(In1, LOW);
    digitalWrite(In2, HIGH);
  }
}

void marchaMotorI (int sentidoMotor)
{
 if (sentidoMotor==adelante)
  { //Adelante
    digitalWrite(In3, HIGH);
    digitalWrite(In4, LOW);
  } 
  else
  { //Atrás
    digitalWrite(In3, LOW);
    digitalWrite(In4, HIGH);
  }
}