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

Esta entrada fue publicada en Arduino. Guarda el enlace permanente.

3 respuestas a Segundo robot autónomo con Arduino

  1. Pingback: Arduino rover evolves to a trike design - Hack a Day

  2. Pingback: Vehículo autónomo con Arduino | Ros Hardware

  3. Pingback: Arduino rover evolves to a trike design / Cooking Hacks Blog

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>