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.

La explicación del funcionamiento de este tipo de motores la tienes en el siguiente enlace:
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:
Este sensor funciona a 5 voltios (dos pines de alimentación (Vcc y Gnd) y otros dos pines trigger y echo.


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.

El funcionamiento de este servo lo tienes en el siguiente enlace:
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.

Es conveniente que veas el funcionamiento de esta placa ya que al poner este escudo no podremos usar ciertos pines de Arduino Uno.
[naaa asin=»B07S82NLYK»]
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.

Esquema de conexión del 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); }