Translate

jueves, 5 de julio de 2012

Segundo robot autónomo con Arduino

Hola otra vez.

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


En este caso he decidido prescindir del servo para la dirección y realizar un montaje con dos ruedas accionada cada una con su propio motor-reductor, y una rueda libre como tercer punto de apoyo. El escaneado del entorno lo realizaremos con los mismos sensores de ultrasonidos que en el montaje anterior, que según el fabricante tienen un ángulo de visión de 15º. Lo demás, como la batería o el estabilizador a 5V es idéntico al primer robot.



Como en el modelo anterior, lleva luz de posición-freno y luz de marcha atrás. Y mi intención es nuevamente utilizar un Arduino. Pero en lugar de un Arduino Uno, decidí adquirir algo más pequeño, un Arduino Nano, que podéis encontrar a muy buenos precios en ebay.



Para controlar los motores, he utilizado el mismo módulo que en la versión anterior, equipado con un L298N y dos puentes en H. La única diferencia en este caso ha sido la forma de utilizarlo.



Este controlador utiliza para cada motor, dos pines para el sentido y uno para la velocidad, en PWM. Para que vaya adelante, hay que darle la configuración HIGH y LOW respectivamente a las dos patillas de control, y para que vaya marcha atrás, hay que darle LOW y HIGH respectivamente. En caso de recibir LOW y LOW, o HIGH y HIGH el motor se para. Y eso también podemos conseguirlo indicando en el pin de la velocidad voltaje 0V. De modo que para manejar el motor nos basta con HIGH y LOW, o LOW y HIGH. La primera parte de la parte contratante será considerada como la parte contratante de la primera parte.... :P

Esta tabla lo ilustra mejor:



En el robot anterior, habia que conectar dos salidas de Arduino para cada motor, y antes de indicar HIGH en una de ellas, debías cambiar a LOW la otra. Esta vez he decidido intercalar un inversor entre el Arduino y el controlador, de modo que en el Arduino solo utilizamos una salida por motor, y el inversor se encarga de "crear" la otra salida. Así cuando le indiquemos un HIGH, la otra salida automáticamente cambiará a LOW, y viceversa.

Este es el sencillo esquema del inversor, que tendremos que realizar por partida doble, uno por cada motor.



Y aquí os pego el extenso código. Esta vez he realizado varias funciones para reducir el código y he guardado en dos variables el sentido de giro de cada rueda para en el siguiente loop continuar moviéndose, o en caso de cambiar de sentido, empezar acelerando, más que nada para suavizar el movimiento y reducir el consumo.

autonomous3

#include <Ultrasonic.h>

/*
Este modesto 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

*/

Ultrasonic ultraright(10,11); // (Trig PIN,Echo PIN) DERECHA
Ultrasonic ultraleft(12,8); // (Trig PIN,Echo PIN) IZQUIERDA

int r = 0; //distancia derecha
int l = 0; //distancia izquierda
byte antr = LOW; //variable que guarda el sentido de giro de la rueda derecha en el loop anterior
byte antl = LOW; //variable que guarda el sentido de giro de la rueda izquierda en el loop anterior
int ledoutput1 = 7; //luz marcha atras
int ledfreno = 6; //luz freno
int direccionderecha = 4; //sentido de giro de la rueda derecha (HIGH adelante, LOW atras)
int direccionizquierda = 2; //sentido de giro de la rueda izquierda (HIGH adelante, LOW atras)
int vderecha = 5; //velocidad rueda derecha con PWM
int vizquierda = 3; //velocidad rueda izquierda con PWM
int lederror = 13; //led de error cuando se de el caso "else" en comparaciones de lecturas

void movimiento(int right, int left, int vright, int vleft) //movimiento b�sico
 {
 analogWrite(vderecha, vright); //velocidad derecha
 analogWrite(vizquierda, vleft); //velocidad izquierda
 digitalWrite(direccionderecha, right); //direcci�n derecha
 digitalWrite(direccionizquierda, left); //direcci�n izquierda
 }

void acelerar(int right, int left, int vright, int vleft) //si cambia el sentido de giro, 
             //realizaremos una aceleraci�n
 {
        int i; 
        movimiento(LOW,LOW,0,0); //paramos
        digitalWrite(direccionderecha, right);
 digitalWrite(direccionizquierda, left);
 for(i=4; i>=1; i--) //acelera progresivamente hasta las velocidades m�ximas indicadas
  {
                analogWrite(vderecha, (vright/i));
  analogWrite(vizquierda, (vleft/i));
  delay(25);
  }  
        
 }
 
void frenar()
 {
  movimiento(LOW, LOW, 0, 0); //paramos
  analogWrite(ledfreno, 250);
  delay(200);
  analogWrite(ledfreno, 70);
 } 

void error() //en caso desconocido
{
 digitalWrite(lederror, HIGH);
 delay(200);
 digitalWrite(lederror, LOW);
 delay(200);
}

void setup()
{
  pinMode (ledoutput1, OUTPUT); //luz marcha atras
  pinMode (ledfreno, OUTPUT); //luz marcha atras
  pinMode (direccionderecha, OUTPUT); //direccion de giro de la rueda derecha
  pinMode (direccionizquierda, OUTPUT); //direccion de giro de la rueda izquierda
  pinMode (lederror, OUTPUT); 
}

void loop()
{
  analogWrite(ledfreno, 70);
  delay(100); //Retardo entre lecturas de ultrasonidos para evitar interferencias.
  r=ultraright.Ranging(CM); // lectura derecha en CM
  delay(100);
  l=ultraleft.Ranging(CM); // lectura izquierda en CM
  
  if(r>60 || l>60) //v�a libre
  {
 digitalWrite(ledoutput1, LOW); //luz marcha atr�s apagada
    if(antr==HIGH && antl==HIGH) //si ya iban hacia adelante ambas
 {
  movimiento(HIGH, HIGH, 250, 235); //por cuestiones de hardware, una rueda 
                                    //tiene m�s velocidad que la otra
 }
 else
 {
  frenar();
  acelerar(HIGH, HIGH, 250, 235);
 }
 
 antr=HIGH; //guardamos sentido
 antl=HIGH; //guardamos sentido
  }
  else if(r<20 || l<20) //al menos una distancia menor de 20cm
  {
 digitalWrite(ledoutput1, HIGH); //luz marcha atras encendida
 if(r<20 && l<20) 
 {
  if(antr==LOW && antl==LOW)
  {
   movimiento(LOW, LOW, 200, 180);
  }
  else
  {
   frenar();
   acelerar(LOW, LOW, 200, 180);
  }
         delay(500); 
 }
  
 //inicio fragmento rotaci�n sobre eje central
   else if(r<20 && l>40)
   {
    frenar();
    acelerar(HIGH, LOW, 200, 180);
    delay(500);
   }
   else if(r>40 && l<20)
   {
    frenar();
    acelerar(LOW, HIGH, 200, 180);
    delay(500);
   }
 //final fragmento rotaci�n sobre eje central
  
 else if(r<20 && l>20)
 {
  if(antr==LOW && antl==LOW)
  {
   movimiento(LOW, LOW, 0, 200);
  }
  else
  {
   frenar();
   acelerar(LOW, LOW, 0, 200);
  }
          delay(1000);
 }
 else if(r>20 && l<20)
 {
  if(antr==LOW && antl==LOW)
  {
   movimiento(LOW, LOW, 200, 0);
  }
  else
  {
   frenar();
   acelerar(LOW, LOW, 200, 0);
  }
          delay(1000);
 }
 else
 {
  error();
 }
 antr=LOW; //guardamos sentido
 antl=LOW; //guardamos sentido
  }
  
  else if(r<40 || l<40) //almenos una distancia menor de 40cm
  {
 digitalWrite(ledoutput1, LOW); //luz marcha atr�s apagada
 if(antr==HIGH && antl==HIGH)
 {
  if(r<40 && l<40)
  {
   if(r>l)
   {
    movimiento(HIGH, HIGH, 150, 200);
   }
   else
   {
    movimiento(HIGH, HIGH, 200, 150);
   }
  }
  else if(r<40 && l>40)
  {
   movimiento(HIGH, HIGH, 250, 100);
  }
  
  else if(r>40 && l<40)
  {
   movimiento(HIGH, HIGH, 100, 250);
  }
  
  else
  {
   error();
  }
 }
 else
 {
  frenar();
  if(r<40 && l<40)
  {
   if(r>l)
   {
    acelerar(HIGH, HIGH, 150, 200);
   }
   else
   {
    acelerar(HIGH, HIGH, 200, 150);
   }
  }
  else if(r<40 && l>40)
  {
   acelerar(HIGH, HIGH, 250, 100);
  }
  
  else if(r>40 && l<40)
  {
   acelerar(HIGH, HIGH, 100, 250);
  }
  
  else
  {
   error();
  }
 

 }
   antr=HIGH; //guardamos sentido
 antl=HIGH; //guardamos sentido
  }
  else
  {
 error();
  }

}


Estoy abierto a todo tipo de críticas constructivas, todo código es mejorable. Esta librería, como en el caso anterior, os hará falta para controlar los sensores de ultrasonidos de 4 pines y está arreglada para el IDE 1.x de Arduino.

Ultrasonic rev3.h

Esta vez sí funciona la luz de freno y posición. Y su comportamiento es bastante bueno, salvo porque algunas veces, cuando avanza recto, parece que está unos segundos sin realizar lecturas de ultrasonidos. Tengo mis dudas de si el problema es debido a la función acelerar. Quizás por algún motivo no termina el bucle for.

Os cuelgo algunos vídeos de su comportamiento. Mientras los véis, yo iré pensando en el tercer prototipo...











Hasta pronto!

English translation

8 comentarios:

  1. [...] Ros] wrote in to show off the latest version of his Arduino powered autonomous rover (translated). You may remember seeing the first version of the build back in June. It started with [...]

    ResponderEliminar
  2. [...] Ros] wrote in to show off the latest version of his Arduino powered autonomous rover (translated). You may remember seeing the first version of the build back in June. It started with [...]

    ResponderEliminar
  3. Me dá uma tristeza quando vejo essas coisas sabendo que eu tenho elas em casa e não sei fazer, me ajuda cara! Eu tenho um nano entre outras coisas aqui, me ajuda com um passo a passo pelo amor de Deus, eu só quero fazer meu robô mexer a cabeça com o movimento de pessoas ou mais alguma coisa que possa acrescentar como LEDs, mais usando o nano. Agradeço!

    ResponderEliminar
  4. Amigo saludos me interesa mucho tu proyecto soy nuevo en esto así que si pudieras detallar mas el armado te lo agradecería mucho o mandarme en un correo un paso a paso mas o menos te lo agradecería enormemente.

    ResponderEliminar
  5. José Manuel García3 de diciembre de 2013, 15:22

    int direccionderecha = 4; //sentido de giro de la rueda derecha (HIGH adelante, LOW atras)
    int direccionizquierda = 2; //sentido de giro de la rueda izquierda (HIGH adelante, LOW atras)
    int vderecha = 5; //velocidad rueda derecha con PWM
    int vizquierda = 3; //velocidad rueda izquierda con PWM

    Yo he conectado el pin 4 del arduino al IN3 del controlador y a través del transistor invertida a la IN4. Y el pin2 del arduino al IN1 del controlador y a través del transistor invertida a la IN2. Pero no se donde conectar en el controlador el pin 5 y el 3 para variar la velocidad de la rueda.

    ResponderEliminar
  6. Hola.

    Hace tiempo que tengo desmontado el robot y me he tenido que mirar las fotos para acordarme. Van a A Enable y a B Enable. Cada uno a su motor. Sigue los cables en las fotos, amarillo y azul.

    Suerte.

    ResponderEliminar
  7. PODRIA ENVIARME EL ESQUEMA DEL CIRCUITO QUE USO PARA SU PROYECTO POR FAVOR. renault1601@gmail.com

    ResponderEliminar