Descripción del robot esquiva obstáculos

En este post vamos a hacer un robot esquiva obstáculos para adentrarnos en el mundillo de la robótica.

Este robot tiene tracción a las cuatro ruedas, usaremos un sensor de ultrasonido para medir la distancia al objeto, un servo para medir distancias al frente y a ambos lados.

El robot comenzara a rodar hacia adelante al poner el interruptor en la posición continuamente estará midiendo la distancia a un posible obstáculo.

En el momento que la distancia al obstáculo sea inferior a 15cm el robot se parará y retrocederá un segundo para evitar atascos en zonas debido al tiempo que transcurre desde la detección hasta la parada efectiva del robot.

A continuación el robot mediante el servo situado en la parte delantera, este servo tendrá solidario a el la placa de ultrasonidos, con lo que en primer lugar daremos la orden al servo de girar a la derecha y tomar la distancia a la derecha, seguidamente daremos la orden al servo de girar a la izquierda para que mida la distancia libre que tenemos.

Una vez recuperada la posición central y original del servo el robot evalúa que distancia es mayor sin obstáculos en función del resultado daremos la orden al robot para que gire en hacia un lado o a otro, para ello ordenaremos que las ruedas delantera y trasera izquierda giren hacia adelante y las ruedas de la derecha giren hacia atrás en caso de que la distancia a la derecha sea mayor en caso contrario procederemos de manera contraria es decir ruedas delantera y trasera izquierdas hacia atrás, ruedas delantera y trasera derecha hacia adelante. Una vez haya terminado daremos la orden al robot de avanzar en línea recta hasta vuelva a detectar otro obstáculo en el que volverá a realizar de nuevo las mediciones a ambos lados .

Componentes del robot esquiva obstáculos

Motores del robot esquiva obstáculos

En este caso he usado 4 motores de corriente continua con reductora como los de la imagen.

motor dc reductora
motor dc reductora

La explicación del funcionamiento de este tipo de motores la tienes en el siguiente enlace:

Motores dc con reductora

La tensión de alimentación está entre 3-6 voltios

La designación de los motores es:

1 Motor 1 motorDi (motor rueda delantera izquierda)

2 Motor 2 motorDd (motor rueda delantera derecha)

3 Motor 3 motorTi (motor rueda trasera izquierda)

4 Motor 4 motorTd (motor rueda trasera derecha)

*Los motores, ruedas y plataforma de metacrilato del robot se pueden comprar juntas o por separado.

Sensor de ultrasonidos

El sensor usado para medir la distancia a los posibles obstáculos en un sensor de ultrasonidos HC-SR04

El funcionamiento del sensor de ultrasonidos lo tienes en el siguiente enlace:

Sensor de ultrasonidos HC SR-04

Este sensor funciona a 5 voltios (dos pines de alimentación (Vcc y Gnd) y otros dos pines trigger y echo.

sensor de ultrasonidos
curso arduino
Curso de Arduino

Si quieres convertirte en un experto en Arduino pincha en el siguiente botón

El fabricante nos recomienda para realizar una medición debemos poner trigger 4ms en OFF 10ms a ON y luego vuelta a OFF, en ese momento el sensor emite una señal ultrasónica que rebotará en el objeto y volverá al sensor, durante este tiempo denominado tiempo de vuelo la patilla echo estará a nivel alto.

Mediante software mediremos cuanto tiempo ha estado a nivel alto y realizando unos cálculos que veremos en el programa de Arduino como es convertir tiempo en distancia en función de la velocidad del sonido obtendremos la distancia en centímetros.

Servomotor

Para poder medir la distancia al obstáculo tanto al frente como a derecha e izquierda necesitamos orientar el sensor de ultrasonidos en las tres direcciones para ello montamos en el servo el sensor ultrasónico en un soporte plástico que puedes comprar o hacer casero de cualquier caja de plástico que tengas por casa.

El servo utilizado es un micro servo 9g de la marca TowerPro ya que el peso del sensor es muy pequeño por lo que es suficiente el uso de este servo.

servomotor
servomotor

El funcionamiento de este servo lo tienes en el siguiente enlace:

servomotor

Básicamente el servo tiene dos pines de alimentación Vcc +5v y masa y un tercer pin de señal o datos.

Dependiendo del tiempo en milisegundos que pongamos este pin a nivel alto girará un cierto número de grados, este servo girá 180º.

Motor shield

Como ya comente en varios post, debído al alto consumo de corriente de los motores, y dado que las salidas de arduino no dan más de 40mA, se plantea el problema de como interconectar Arduino con los motores.

Para ello usamos un motor Shield, que no es ni mas ni menos que una placa de circuito impreso que conectamos a Arduino Uno en este caso a modo de escudo mediante los pines de conexión, esta placa dispone de unos drivers o circuitos de potencia que nos permiten por un lado recibir las señales de control provenientes de Arduino y por otro lado gobernar los motores conectados a esta.

motor shield
motor shield

Es conveniente que veas el funcionamiento de esta placa ya que al poner este escudo no podremos usar ciertos pines de Arduino Uno.

Motor shield

Alimentación del robot esquiva obstáculos

La alimentación del robot plantea el problema que no podemos alimentar directamente de una fuente de alimentación conectada a la red por motivos obvios ya que el robot al ser móvil no podríamos alimentarlo de esta manera.

Hay varias maneras de alimentarlo, yo he optado por hacerlo con dos portapilas de 4 pilas cada uno tipo AA de 1,5 voltios con lo cual cada grupo de 4 pilas me dará 6 voltios los dos portapilas los he puesto en paralelo para obtener la misma tensión de 6 voltios pero ahora dispongo del doble de corriente, recuerda que la mayor parte del consumo es de los motores con esta solución tengo más autonomía.

En principio use un solo portapilas pero va bastante justo y en cuanto se empiezan un poco a gastar las pilas el robot comienza a comportarse de forma errática.

Hay que tener en cuenta una consideración bastante importante.

Es posible que los motores introduzcan ruidos hacia Arduino, con lo que es posible que nuestro robot esquiva obstáculos no funcione correctamente, si fuera este el caso podemos optar por quitar el jumper de color amarillo poner de la placa motor-shield, este jumper al quitarlo nos permite alimentar de forma independiente el motor shield y Arduino evitando así que los ruidos se filtren a la placa de control Arduino Uno en este caso.

En mi caso como funcionaba correctamente he usado una sola fuente de alimentación (jumper puesto) para alimentar a ambas placas, la alimentación llega a Arduino Uno por Vin esta entrada admite entre 6-12v lo único a tener en cuenta es la polaridad ya que en esta entrada no tenemos protección por inversión de polaridad.

Jumper motor shield

Esquema de conexión del robot esquiva obstáculos

Esquema de conexión robot esquiva obstáculos

Programa de Arduino

/*AUTOR: JOSE ANTONIO RIVERA MORALES
 *FECHA: 20-7-2020
 *www.pasionelectronica.com
 * Este programa muestra controla un robot  
 * esquiva obstaculos tracción a las cuatro ruedas
 * mide la distancia a traves de un sensor de
 * ultrasonidos
 */
#include <AFMotor.h>//libreria del motor shield  
#include <Servo.h>//libreria para el servomotor 

int trigger=14;//trigger del ultrasonidos conectado a Pin A0=pin14
int echo=15;//echo del ultrasonidos conectado a pin A1=pin15
float vSonido=0.0343;//velocidad del sonido en cm/us
int distDcha=0;//variables que almacenan la distancia a derecha o izquierda
int distIzda=0; 
AF_DCMotor motorDi(1, MOTOR12_1KHZ); //instancias para los motores
AF_DCMotor motorDd(2, MOTOR12_1KHZ);
AF_DCMotor motorTi(3, MOTOR34_1KHZ);
AF_DCMotor motorTd(4, MOTOR34_1KHZ);
Servo servoUltra;//servo que controla giro del servomotor que lleva el ulrasonidos  



void setup() {
pinMode(trigger,OUTPUT);//como debemos dar la orden de realizar medición estó sera salida
pinMode(echo,INPUT);//leemos el tiempo que esta echo a nivel alto por lo tanto será una entrada
pinMode(9,OUTPUT);//pin donde conectaremos la señal del servo conector serv2=pin9
servoUltra.attach(9);//indicamos en que pin esta conectado el servo


 motorDi.setSpeed(150);//velocidad motor Di valores entre 0 y 255
 motorDi.run(RELEASE);//iniciamos con motor parado
 motorDd.setSpeed(150);//velocidad motor Dd
 motorDd.run(RELEASE);//iniciamos con motor parado
 motorTi.setSpeed(150);//velocidad motor Ti
 motorTi.run(RELEASE);//iniciamos con motor parado
 motorTd.setSpeed(150);//velocidad motor Td
 motorTd.run(RELEASE);//iniciamos con motor parado
}

void loop() {
int ddistDcha=0;//inicializamos las variables de distancia
int ddistIzda=0;
int distFront=0; 
adelante();//comienza hacia adelante 
distFront=medir_distancia();//llamamos a la función medir distancia para saber la distancia
//al obstaculo

if (distFront<=15){//si el obstaculo esta a menos de 15 cm
  parar();//para
  atras();//retrocede para facilitar maniobras
  delay(500);
  parar();//para
  ddistDcha=miraDcha();//llamamos a la función para girar-mirar el servo a la dcha 
  delay(1000);
  ddistIzda=miraIzda();//llamamos a la función para girar-mirar el servo a la izda
  delay(1000);
    if (ddistDcha>=ddistIzda){//si la distancia de la dcha es mayor o igual a izda
    giraDcha();//gira a la derecha
    
     
    }
    else{//si no gira a la izda
    giraIzda();
   
    }
  }
else
 {
  adelante();
 }
}


int miraIzda()//función gira servo izda
 {
 servoUltra.write(179);//90 grados izda
 delay(1000);  
 distIzda=medir_distancia();//función mide distancia
 servoUltra.write(90);//recupera posición inicial
 delay(1000);
 return distIzda;//retornamos distancia del obstaculo en la izda
 }

int miraDcha()//función gira servo dcha
 {
 servoUltra.write(0);//90 grados dcha  
 delay(1000);  
 distDcha=medir_distancia();//función mide distancia
 servoUltra.write(90);//recupera posición inicial
 delay(1000);  
 return distDcha;//retornamos distancia del obstaculo en la dcha
 }
  
int medir_distancia(){//función que realiza la medición de la distancia
 
  digitalWrite(trigger,LOW);//para hacer una lectura el fabricante nos dice que tenemos que poner
  delayMicroseconds(4);//trigger 4ms a OFF y luego 10ms a ON
  digitalWrite(trigger,HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger,LOW);
  int tdvuelo=pulseIn(echo,HIGH);//pulseIn función que nos devuelve el tiempo en HIGH de un pin
  int talobjeto=tdvuelo/2;//el tiempo al objeto es la mitad de lo que tarda la señal en ir y volver
  int resultado=vSonido*talobjeto;//obtenemos la distancia multiplicando la vSonido x tiempo que transcurre hasta al objeto
  return resultado;//variable o parámetro que devuelve la función en este caso el valor de resultado
  //se asignara a distancia que es la variable que se indico en la llamada de origen
  
 }
 void parar(){//detiene las cuatro ruedas
  motorDi.run(RELEASE); 
  motorDd.run(RELEASE);
  motorTi.run(RELEASE);
  motorTd.run(RELEASE);
 }
 void adelante(){//gira hacia adelante las cuatro ruedas
 motorDi.run(FORWARD); 
 motorDd.run(FORWARD);
 motorTi.run(FORWARD);
 motorTd.run(FORWARD); 
 }
 void giraIzda(){//ruedas izquierdas hacia atras y dchas hacia adelante
  motorDi.run(BACKWARD); 
  motorDd.run(FORWARD);
  motorTi.run(BACKWARD);
  motorTd.run(FORWARD);
  delay(750);//tiempo girando
  motorDi.run(FORWARD);//despues continua hacia adelante 
  motorDd.run(FORWARD);
  motorTi.run(FORWARD);
  motorTd.run(FORWARD); 
 
 }
 void giraDcha(){//ruedas izquierdas hacia atras y dchas hacia adelante 
  motorDi.run(FORWARD); 
  motorDd.run(BACKWARD);
  motorTi.run(FORWARD);
  motorTd.run(BACKWARD);
  delay(750);//tiempo girando
  motorDi.run(FORWARD);//despues continua hacia adelante  
  motorDd.run(FORWARD);
  motorTi.run(FORWARD);
  motorTd.run(FORWARD); 
  
 }
 void atras(){//cuatro ruedas giran hacia atras
  motorDi.run(BACKWARD); 
  motorDd.run(BACKWARD);
  motorTi.run(BACKWARD);
  motorTd.run(BACKWARD);
 }