Translate

lunes, 4 de junio de 2012

Vehículo autónomo con Arduino

Hola.

Como os he ido avanzando estas semanas, he estado trabajando en un sencillo robot, con el que intentar darle autonomía de movimiento utilizando una placa Arduino.



Recordar antes que nada que este es mi primer proyecto con Arduino y mi primera experiencia programando estos "cacharros". Simplemente lo indico porque cualquiera que tenga más experiencia que yo seguro que puede sacarle más jugo a mi montaje y seguro que consigue una mejor programación. Eso sí, acepto críticas constructivas para mejorarlo.

Mi idea inicial era utilizar un viejo coche RC y añadirle un servo en la dirección con un recorrido útil de 60º, una controladora de motores con un L298N para el movimiento y un par de sensores de ultrasonidos. Estos sensores tendrían la misión de detectar obstáculos y el suelo, pero después del primer test me di cuenta de que el suelo, a menos que fuera muy irregular, era imposible que lo detectaran, tendrían que estar prácticamente perpendiculares, puesto que tal y como los he montado no pueden recibir la señal reflejada, ésta tiene un ángulo demasiado grande.

El vehículo de partida llevaba una batería compuesta por cinco pilas recargables de Ni-Cd que teóricamente otorgan 6V, pero que finalmente cargada da 6.8V, por lo que tuve que añadir un regulador a 5V para alimentar el Arduino y los servos, excepto los motores que se alimentan directamente de la batería.

En la transmisión añadí un eslabón más en la reductora, consiguiendo una velocidad menor y mayor fuerza, y atacado por un motor Ninco NC-7 de Slot. Como rodamientos para este eslabón de más utilicé la estructura del motor original, sin el bobinado, pasando un eje por su interior.

Decidí que el vehículo iría marcha atrás, con la dirección en el eje trasero, y en lo que sería la parte delantera le añadí unos leds, haciendo las veces de luz delantera, directamente al ON de la batería, y en la parte trasera un led rojo que haría las veces de luz de posición y luz de freno, y un led blanco como luz de marcha atrás. Estos dos controlados por el Arduino.

El montaje ha quedado así:



La placa Arduino la adquirí en ebay, concretamente el modelo Arduino Uno R3. Si realizáis una búsqueda internacional encontraréis muy buenos precios.



El resto de componentes también los adquirí en ebay, el servo pequeñito costó alrededor de 2€, la controladora de motores unos 4.50€ y los sensores de ultrasonidos alrededor de 3€ cada uno. Precios muy económicos.

Antes de empezar a programar hay que pensar muy bien cómo lo vamos a controlar. Decidí separar las diferentes reacciones con rangos de distancias, de menor a mayor distancia, es decir, primero si alguno mide menos de 20cm, sinó mirar si alguno mide menos de 40cm, porque si empezamos por el más alejado, siempre se cumple...

Tan solo hay un detalle y que quizás alguno de vosotros me pueda solucionar, y es la luz de posición y freno. Está conectada en una salida analógica (pin 9), pero no consigo que se ilumine. Si convierto la salida en digital sí funciona. Seguramente será una tontería, pero no consigo verla :P .

Os adjunto el código:

autonomous2.ino


#include <Ultrasonic.h>
#include <Servo.h>

Ultrasonic ultraright(7,6); // (Trig PIN,Echo PIN) DERECHA
Ultrasonic ultraleft(12,11); // (Trig PIN,Echo PIN) DERECHA

/*
Este codigo pertenece a RosHardware. Se autoriza el uso parcial 
o total del mismo siempre y cuando se indique la procedencia 
del mismo. 

http://www.entremaqueros.com/bitacoras/roshardware

*/

Servo myservo;

int f;
int g;
int ledoutput1 = 8;
int ledoutput2 = 9;
int adelante = 4;
int atras = 2;
int velocidad = 3;
int lederror = 13;


void setup() 
{
  pinMode (ledoutput1, OUTPUT); //luz marcha atras
  pinMode (ledoutput2, OUTPUT); //luz de freno-posicion trasera
  pinMode (adelante, OUTPUT); 
  pinMode (atras, OUTPUT);
  pinMode (lederror, OUTPUT); 
  myservo.attach(10);
  
}

void loop()
{
  delay(100); //Retardo entre lecturas de ultrasonidos para evitar interferencias.
  g=ultraright.Ranging(CM); // lectura derecha en CM
  delay(100);
  f=ultraleft.Ranging(CM); // lectura izquierda en CM
  
   if(f<20 || g<20) //si una de las dos distancias es menor de 20cm
  {
    if(f<20 && g<20) // si lo son ambas
    {
      analogWrite(ledoutput2, 250); // luz de freno
      analogWrite(velocidad, 0); // frenamos
      delay(500); // aguantamos frenados 0,5s
      myservo.write(30); // recto
      analogWrite(ledoutput2, 150); // quitamos luz de freno
      digitalWrite(adelante, LOW); //  quitamos marcha adelante
      digitalWrite(ledoutput1, HIGH); // encendemos luz de marcha atras.
      digitalWrite(atras, HIGH); // ira atras 
      analogWrite(velocidad, 200); //velocidad trasera
      delay(1500); //tiempo que va marcha atras hasta siguiente lectura
      digitalWrite(ledoutput1, LOW);
    }
    
    else if(f<20 && g>=20)
    {
      
      analogWrite(ledoutput2, 250); // luz de freno
      analogWrite(velocidad, 0); // frenamos
      delay(500); // aguantamos frenados 0,5s
      myservo.write(60); // giramos a la izquierda
      
      analogWrite(ledoutput2, 150); // quitamos luz de freno
      digitalWrite(adelante, LOW); //  quitamos marcha adelante
      digitalWrite(ledoutput1, HIGH); // encendemos luz de marcha atras.
      digitalWrite(atras, HIGH); // ira atras 
      analogWrite(velocidad, 200); //velocidad trasera
      delay(1500); //tiempo que va marcha atras hasta siguiente lectura
      digitalWrite(ledoutput1, LOW);
    }
    else if(f>=20 && g<20) 
    {
      
      analogWrite(ledoutput2, 250); // luz de freno
      analogWrite(velocidad, 0); // frenamos
      delay(500); // aguantamos frenados 0,5s
      myservo.write(0); // giramos a la derecha
      
      analogWrite(ledoutput2, 150); // quitamos luz de freno
      digitalWrite(adelante, LOW); //  quitamos marcha adelante
      digitalWrite(ledoutput1, HIGH); // encendemos luz de marcha atras.
      digitalWrite(atras, HIGH); // ira atras 
      analogWrite(velocidad, 200); //velocidad trasera
      delay(1500); //tiempo que va marcha atras hasta siguiente lectura
      digitalWrite(ledoutput1, LOW);
    }
    else //error
    {
      digitalWrite(lederror, HIGH);
      delay(150);
      digitalWrite(lederror, LOW);
      delay(150);
    }
    
    
  }
  else if(f<40 || g<40) //alguna distancia es menor de 50
  {
    if(f<40 && g<40)
    {    
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
        if(f>g) //elegimos direccion de giro
        {
          myservo.write(50);
        }
        else
        {
          myservo.write(10);
        }
      digitalWrite(velocidad, 150);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    } 
    else if(f>=40 && g<40)
    {
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
      myservo.write(40);
      digitalWrite(velocidad, 200);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
    
    else if(f<40 && g>=40)
    {
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
      myservo.write(10);
      digitalWrite(velocidad, 150);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
    else //error
    {
      digitalWrite(lederror, HIGH);
      delay(150);
      digitalWrite(lederror, LOW);
      delay(150);
    }
  }
  else if(f<60 || g<60) //alguna distancia es menor de 60cm
  {
    if(f<60 && g<60)
    {    
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
        if(f>g) //elegimos direccion de giro
        {
          myservo.write(40);
        }
        else
        {
          myservo.write(20);
        }
      digitalWrite(velocidad, 200);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
    else if(f<60 && g>=60)
    {
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
      myservo.write(20);
      digitalWrite(velocidad, 200);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
    else if(f>=60 && g<60)
    {
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
      myservo.write(40);
      digitalWrite(velocidad, 200);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
     else //error
    {
      digitalWrite(lederror, HIGH);
      delay(150);
      digitalWrite(lederror, LOW);
      delay(150);
    }
  }
    else if(f>60 && g>60) //sin obstaculos
    {
      myservo.write(30);
      digitalWrite(ledoutput1, LOW);
      
      analogWrite(ledoutput2, 150); // luz de posicion trasera
      digitalWrite(velocidad, 250);
      digitalWrite(atras, LOW); // quitamos marcha atras 
      digitalWrite(adelante, HIGH); //  ponemos marcha adelante
    }
    else //error
    {
      digitalWrite(lederror, HIGH);
      delay(150);
      digitalWrite(lederror, LOW);
      delay(150);
    }
}


Y también os adjunto la librería para los sensores de ultrasonidos de cuatro pines que os faltará, modificada para funcionar con la versión 1.0 del software de Arduino.

Ultrasonic_rev3

Espero haber sido suficientemente claro en la programación.

Y como muestra, algunos videos de poca calidad, pero para que sirvan de ejemplo. Espero que os gusten.







Hasta pronto!!

Segunda versión.

English translation.

5 comentarios:

  1. [...] Ros] wrote in show off his first attempt at building an autonomous rover (translated). As with many of these projects, he started with the base of a remote control toy [...]

    ResponderEliminar
  2. [...] Ros] wrote in show off his first attempt at building an autonomous rover (translated). As with many of these projects, he started with the base of a remote control toy [...]

    ResponderEliminar
  3. [...] Ros] wrote in show off his first attempt at building an autonomous rover (translated). As with many of these projects, he started with the base of a remote control toy [...]

    ResponderEliminar
  4. [...] del primer intento de realizar un robot autónomo con más o menos éxito, he decidido mejorar ligeramente su estructura y su [...]

    ResponderEliminar
  5. Excelente tutorial, felicitaciones muchas gracias, lo voy a intentar y te aviso, ya compre todos los componentes, saludos desde Venezuela

    ResponderEliminar