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);
  }
}

miércoles, 5 de mayo de 2010

Localizador de aviones

El pasado fin de semana (1 y 2 de mayo de 2010) me lo pasé en grande con la apliación http://www.localizatodo.com. En esta pagina, se pueden localizar los aviones que surcan en estos momentos nuestras cabezas. Ruido de avión que oía, avión que veía en la pantalla.

jueves, 26 de noviembre de 2009

Vía teleobjetivo.org me entero que Intel ha liberado los planos del primer microprocesador de la historia, el 4004.

viernes, 13 de noviembre de 2009

En este blog he encontrado una forma muy interesante que explican con vacas los diferentes modelos económicos.

martes, 28 de abril de 2009

Otra distribución de Asterisk

Vía Sinologic me entero de un script para montar Asterisk sobre debian.

lunes, 17 de noviembre de 2008

Youtube como democratizador del conocimiento

Vía Enrique Dans, he encontrado esta referencia

http://www.enriquedans.com/2008/11/youtube-como-buscador.html

del uso alternativo al repositorio de videos on-line Youtube como buscador de información.



En este bitácora ya hablé de ello aquí por ejemplo.

Las propiedades educativas de este tipo de servicios son inmensas. La imagen entra mejor que el texto, y más aún si es imagen en movimiento.

miércoles, 12 de noviembre de 2008

La moral innata

La semana pasada ví otro programa de Redes de TVE en el cual Punset entrevista a Marc Hauser (Universidad de Harvard) sobre un tema que me pareció fascinante: ¿nacemos con una moral innata?

Cuando se habla de moral se piensa principalmente en temas religiosos, pero este psicobiólogo apunta a que debido a nuestra condición de individuos sociales y a la necesidad de supervivencia, todo ser humano siente que debe de ayudar a los demás, que al fin y al cabo es ayudar a la sociedad y por tanto a nosotros mismos.

El enlace aquí.