1. El Octavo Bit
  2. / Arduino
  3. / Proyectos para Arduino
  4. / Robot esquiva obstáculos con Arduino y un sensor de ultrasonidos

Robot esquiva obstáculos con Arduino y un sensor de ultrasonidos

| Actualizado:
Comentarios: 2

Robot esquiva obstáculos con Arduino y un sensor de ultrasonidos
Robot esquiva obstáculos con Arduino y un sensor de ultrasonidos

En este proyecto nos marcamos el objetivo de desarrollar un robot capaz de esquivar objetos. Un robot que avanzará en línea recta mientras que no detecte ningún obstáculo; en caso de detectar algún estorbo, girará sobre sí mismo hasta que esquive el objeto. Vamos a utilizar para ello una placa de Arduino UNO, un controlador de motores y un sensor de distancia. Una vez terminado el montaje, le añadiremos avisos luminosos.

Material necesario:

  • Placa Arduino o similar.
  • Módulo controlador de motores L298N.
  • Módulo HC-SR04,
  • sensor de ultrasonido y soporte.
  • Chasis robot Arduino 2WD.
  • 2 ruedas.
  • Rueda loca.
  • 2 motores reductores TT de doble eje.
  • Interruptor ON/OF de 2 pines.
  • Portapilas para la alimentación de la placa y 4 pilas AA.
  • Pila de 9 Voltios para el controlador y motores.
  • Cables y tornillos.
  • Protoboard pequeño.
Material necesario para el proyecto de robot Arduino evita obstáculos

Montaje del robot autónomo esquiva obstáculos.

Comenzamos montando los motores y añadiéndolos con sus soportes en forma de T al chasis del coche.

Colocamos los dos motores en el chasis

Nos fijaremos que en la imagen los motores están colocados en la misma dirección a ambos lados del chasis y la rueda pequeña del velocímetro, está colocada por la parte interior del motor.

Montamos la rueda loca. Utilizamos para ello las 4 tuercas de extensión, que se deben colocar por la parte inferior del chasis.

La rueda loca se coloca en el chasis del robot

A continuación, montaremos el soporte para las pilas y las ruedas.

Ponemos el portapilas en la zona inferior del chasis

Colocaremos el soporte para pilas en la zona inferior del chasis, no hay un lugar predefinido donde colocarlo, las fijaciones que proponemos en la imagen pueden cambiarse por otra colocación mejor si no coinciden los agujeros del chasis.

Colocamos seguidamente el interruptor.

El interruptor se coloca en el agujero central preparado para el

Hemos colocado el interruptor en el hueco central del chasis.

Montaje de la placa Arduino y el controlador L298N.

Fijamos la placa Arduino y la placa controladora de los motores L298N al chasis buscando la mejor colocación posible en el espacio del que disponemos, y algún agujero que coincida con los de las placas para utilizar tornillos que las sujeten. En nuestro caso, hemos sujetado la placa de Arduino con 2 tuercas de extensión, y el controlador L298N, con solo un tornillo.

Para que las placas tengan un mejor apoyo, deberemos usar alguna arandela, tuerca o alargador por la parte inferior de la placa para que haga de soporte y mantenga fijos los elementos entre el chasis y las placas.

Colocación de la placa Arduino y el modulo controlador de los motores

En este paso conectaremos la placa Arduino con el controlador:

Los conectores INA e INB se utilizarán para controlar la velocidad de cada uno de los motores, realizaremos la conexión usando los pines PWM (Pulse-Width Modulation) que aparecen etiquetados con el símbolo ~ (son los pines digitales 11, 10, 9, 6, 5, y 3).

  • ENA con el pin 6
  • IN1 con el pin 2
  • IN2 con el pin 7
  • IN3 con el pin 4
  • IN4 con el pin 3
  • ENB con el pin 5

A continuación, conectaremos los motores con el módulo L298N, podemos encontrar 4 conexiones etiquetadas como OUT1, OUT2, OUT3 y OUT4. En este montaje se han conectado los cables del motor derecho en las conexiones OUT1 (negro) y OUT2 (rojo). Los cables del motor izquierdo se han colocado en OUT3 (rojo) y OUT4 (negro).

El interruptor que se colocó en la parte central se va a utilizar para cortar la alimentación que suministra la pila de 9V a los motores y al controlador. Por tanto, tendremos que conectar el cable rojo al interruptor. Unimos ese cable al interruptor y desde la otra patilla del interuptor pasaremos un cable rojo a la alimentación del controlador. El cable negro, de toma de tierra, debe introducirse en el conector central de los 3 conectores de alimentación del controlador. Pero además, hay que tener en cuenta que la toma de tierra de controlador L298N debe conectarse también a una de las conexiones de toma de tierra (GND) de la placa Arduino.

Para alimentar la placa Arduino utilizaremos el portapilas.

Ya tenemos todo listo para que funcionen los motores, probemos:

// MOTOR 1
int IN1 = 2;
int IN2 = 7;
int ENA = 6;
// MOTOR 2
int IN3 = 4;
int IN4 = 3;
int ENB = 5;

void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);
}

void loop() {
  //avanza();
  //retrocede();
  //derecha();
  izquierda();
}
void parada(uint16_t tiempo) {
  parar();
  delay(tiempo);
}
void avanza(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  // MOTOR 2
  analogWrite(ENB, 150);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void retrocede(){
 // MOTOR 1 
  digitalWrite(ENA, HIGH);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  digitalWrite(ENB, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void derecha(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  analogWrite (ENB, 150);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void izquierda(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  // MOTOR 2
  analogWrite (ENB, 150);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void parar(){
 // MOTOR 1 
  digitalWrite(ENA, 0);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  digitalWrite(ENB, 0);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

Testamos las funciones avanza, retrocede, derecha e izquierda. Si el giro de las ruedas es el correcto lo dejamos como está, si no es el deseado, debemos cambiar el código. Tened en cuenta que IN1 e IN2 son los responsables del giro del motor, cambiando HIGH y LOW podemos cambiar el sentido de giro.

Colocar el sensor de ultrasonido.

En la parte frontal del chasis sujetaremos el sensor de distancia ayudándonos de un soporte para el sensor ultrasónico. Si no tenemos soporte, podemos utilizar la misma miniprotoboard para sujetar el sensor.

Añadimos el sensor para medir las distancias y su cableado.

Para el cableado nos ayudaremos de un protoboard, el sensor dipone de 4 pines: GND que conectaremos al GND de la placa Arduino a través del protoboard, Vcc que conectaremos al pin de 5V de Arduino, también a través del protoboard, uniremos Echo al pin 8 de la placa y, por último, Trig, al pin digital 12 de Arduino. Pasamos a escribir el código para el funcionamiento del sensor de distancia. Al principio del código añadiremos:

#include "NewPing.h"
#define PIN_TRIG 12
#define PIN_ECHO 8
#define MAX_DISTANCIA 100
NewPing sonar(PIN_TRIG, PIN_ECHO, MAX_DISTANCIA);

En la primera línea del código se incluye la biblioteca NewPing.h, definimos seguidamente qué pines digitales van conectados a Trig y Echo en el sensor. En la cuarta línea, definimos la distancia máxima de medida para el sensor. Y, por último, creamos el objeto sonar, de la clase NewPing.

En la función setup(), inicializamos la comunicación serial:

Serial.begin(9600);

En la función loop(), comprobamos la distancia que mide:

delay(1000);
int tiempo = sonar.ping_median();
int distancia = tiempo / US_ROUNDTRIP_CM;
// Imprimir el tiempo medido en la consola
Serial.print("Tiempo: ");
Serial.print(tiempo);
Serial.println(" microsegundos");
// Imprimir la distancia medida en la consola
Serial.print("Distancia: ");
// US_ROUNDTRIP_CM constante para determinar la distancia. Convertir el tiempo en distancia (0 = indica fuera de rango)
Serial.print(distancia);
Serial.println(" cm");

Si subimos el código y comprobamos en el monitor serial:

Captura del monitor serial

Tenemos el siguiente esquema montado y hemos comprobado que los motores funcionan y el sensor de distancia mide correctamente.

Esquema del robot para Arduino, el controlador de motores y el sensor de distancia

Comenzamos a programar nuestro robot esquiva obstáculos: el sensor de distancia nos está midiendo continuamente el tiempo que tarda en volver la onda, si esta no vuelve, es que no hay ningun objeto delante, por lo tanto podemos pensar que puede avanzar libremente (fuera de rango es igual a 0).

if (distancia > 0){

}else{
  avanza();
}

Si hay una medida de tiempo, es que detecta algún objeto. Y, por lo tanto, nos calculará una distancia. Si se encuentra a menos de 30 cm de un objeto haremos que gire hacia la derecha, o que retroceda si se acerca a menos de 20 cm de un obstáculo. Si la distancia es igual o mayor de 30 cm, significa que tenemos camino libre hacia delante.

if (distancia > 0){
  if(distancia < 30){
    if(distancia > 20){
      retrocede();
      delay(200);
      parada(100);
    }else{
      derecha();
      delay(400);
      parada(500);
    }
  }else{
    avanza();
  }
 }else{
  avanza();
}

Si probamos este código comprobaremos que siempre retrocede y gira hacia la derecha cuando encuentra algún obstáculo.

Podemos hacer que gire también hacia la izquierda aleatoriamente lo que hará que le resulte más fácil salir de algún atolladero. ¿Cómo lo vamos a realizar? Primero crearemos una variable para guardar el número aleatorio.

long randomNumber;

Seguidamente, haremos que escoja entre 1 y 2, para ello añadiremos en el código:

if (distancia > 0){
  if(distancia < 30){
    if(distancia > 20){
      retrocede();
      delay(200);
      parada(100);
    }else{
      randomNumber = random(1,3);
      Serial.print("El numero aleatorio es = ");
      Serial.println(randomNumber);
      if (randomNumber == 1){
        izquierda();
        delay(400);
        parada(500);
      }else{
        derecha();
        delay(400);
        parada(500);
      }
    }
  }else{
    avanza();
  }
 }else{
  avanza();
}

Si probamos este nuevo código, veremos que unas veces girará hacia la derecha y otras a la izuierda, dando la posibilidad de escaparse y poder seguir avanzando en situaciones más dificiles.

¿Y si creamos un sistema de luces que nos avise hacia dónde avanza?

Un Led RGB nos avisará de la dirección del robot: rojo al retroceder, verde al avanzar y azul cuando gire.

El nuevo esquema sería:

Esquema del robot para Arduino, el controlador de motores, sensor de distancia y modulo Led RGB

En la imagen inferior hemos añadido el módulo Led RGB sobre la protoboard y hemos conectado los pines PWM de la placa Arduino:

  • Pin R al pin 11 de la placa
  • Pin G al pin 10 de la placa
  • Pin B al pin 9 de la placa
  • Y el GND al protoboard, que enlaza con el pin GND de Arduino.
Se añade el modulo Led RGB y su cableado

Añadiremos al código las instrucciones necesarias para el funcionamiento de los avisos luminosos. Primero, crearemos unas constantes para indicar los pines correspondientes:

const int PinLedRojo = 11;
const int PinLedVerde = 10;
const int PinLedAzul = 9;

En la función setup() indicaremos que van a funcionar como salida:

pinMode(PinLedVerde, OUTPUT);
pinMode(PinLedRojo, OUTPUT);
pinMode(PinLedAzul, OUTPUT);

Creamos las funciones para los colores:

void verde(){
  Serial.println("¡Verde!");
  digitalWrite(PinLedRojo, LOW);
  digitalWrite(PinLedVerde, HIGH);
  digitalWrite(PinLedAzul, LOW);
}
void rojo(){
  Serial.println("¡Rojo!");
  digitalWrite(PinLedRojo, HIGH);
  digitalWrite(PinLedVerde, LOW);
  digitalWrite(PinLedAzul, LOW);
}
void azul(){
  Serial.println("¡Azul!");
  digitalWrite(PinLedRojo, LOW);
  digitalWrite(PinLedVerde, LOW);
  digitalWrite(PinLedAzul, HIGH);
}

Y en la función loop(), indicaremos qué color se enciende. Antes de la llamada a la función avanza(), indicamos que se encienda la luz verde; para la función retrocede(), la luz roja; y para las funciones derecha() e izquierda(), la luz azul.

El código completo quedaría como sigue:

#include "NewPing.h"
#define PIN_TRIG 12   // Pin del Arduino conectado al pin Trigger del sensor de ultrasonidos
#define PIN_ECHO 8   // Pin del Arduino conectado al pin Echo del sensor de ultrasonidos
#define MAX_DISTANCIA 100  // Distancia máxima a detectar en cm.
NewPing sonar(PIN_TRIG, PIN_ECHO, MAX_DISTANCIA);
// MOTOR 1
int IN1 = 2;
int IN2 = 7;
int ENA = 6;
// MOTOR 2
int IN3 = 4;
int IN4 = 3;
int ENB = 5;
long randomNumber;
const int PinLedRojo = 11;
const int PinLedVerde = 10;
const int PinLedAzul = 9;

void setup() {
  Serial.begin(9600);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(PinLedVerde, OUTPUT);
  pinMode(PinLedRojo, OUTPUT);
  pinMode(PinLedAzul, OUTPUT);
  randomSeed(analogRead(A0));  
}

void loop() {
  delay(1000);
  int tiempo = sonar.ping_median();
  int distancia = tiempo / US_ROUNDTRIP_CM;
  // Imprimir el tiempo medido en la consola
  Serial.print("Tiempo: ");
  Serial.print(tiempo);
  Serial.println(" microsegundos");
  // Imprimir la distancia medida en la consola
  Serial.print("Distancia: ");
  // US_ROUNDTRIP_CM constante para determinar la distancia. Convertir el tiempo en distancia (0 = indica fuera de rango)
  Serial.print(distancia);
  Serial.println(" cm");
  /*  */
  if (distancia > 0){  // hay espacio
    if(distancia < 30){
      //parar();
      if(distancia > 20){
        rojo();
        retrocede();
        delay(200);
        parada(100);
      }else{
        randomNumber = random(1,3);
        Serial.print("El numero aleatorio es = ");
        Serial.println(randomNumber);
        if (randomNumber == 1){
          azul();
          izquierda();
          delay(400);
          parada(500);
        }else{
          azul();
          derecha();
          delay(400);
          parada(500);
        }
      }
    }else{
      verde();
      avanza();
      //delay(200);
      //parada(500);
    }
  }else{
    verde();
    avanza();
  }
}
void parada(uint16_t tiempo) {
  parar();  // Para los motores
  delay(tiempo);        // Espera el tiempo que se le indique.
}

void avanza(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  // MOTOR 2
  analogWrite(ENB, 150);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void retrocede(){
 // MOTOR 1 
  digitalWrite(ENA, HIGH);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  digitalWrite(ENB, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void derecha(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  analogWrite (ENB, 150);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void izquierda(){
 // MOTOR 1 
  analogWrite (ENA, 150);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  // MOTOR 2
  analogWrite (ENB, 150);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void parar(){
 // MOTOR 1 
  digitalWrite(ENA, 0);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  // MOTOR 2
  digitalWrite(ENB, 0);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

void verde(){
  Serial.println("¡Verde!");
  digitalWrite(PinLedRojo, LOW);
  digitalWrite(PinLedVerde, HIGH);
  digitalWrite(PinLedAzul, LOW);
}
void rojo(){
  Serial.println("¡Rojo!");
  digitalWrite(PinLedRojo, HIGH);
  digitalWrite(PinLedVerde, LOW);
  digitalWrite(PinLedAzul, LOW);
}
void azul(){
  Serial.println("¡Azul!");
  digitalWrite(PinLedRojo, LOW);
  digitalWrite(PinLedVerde, LOW);
  digitalWrite(PinLedAzul, HIGH);
}

Artículos que te pueden interesar

Detector de incendios con Arduino
Detector de incendios con Arduino y el sensor KY-026

Detector de incendios con Arduino y el sensor KY-026

| Actualizado:
Comentarios: 0

El módulo KY-026 es un sensor de llama que permite detectar un fuego gracias a un sensor óptico sensible a la radiación emitida por la llama. El sensor puede detectar fuentes de luz en el rango de una longitud de…

Medir la temperatura con Arduino
Medir la temperatura con el sensor LM35 y Arduino

Medir la temperatura con el sensor LM35 y Arduino

| Actualizado:
Comentarios: 5

Veremos cómo medir la temperatura con el sensor analógico LM35 y mostrar el valor de la temperatura en el monitor serial de Arduino o en un display de 4 dígitos y 7 segmentos. El LM35 es uno de los sensores…

Crear una alarma con el módulo KY-008, una fotoresistencia y un buzzer
Alarma con Arduino

Crear una alarma con el módulo KY-008, una fotoresistencia y un buzzer

| Actualizado:
Comentarios: 0

En esta práctica haremos una alarma que se conectará en el momento en que el haz de luz del puntero no llegue a la fotorresistencia. Haremos que la señal de alarma nos avise por el monitor serial y nos de un aviso sonoro

Medir el voltaje de una pila con Arduino

Medir el voltaje de una pila con Arduino

| Actualizado:
Comentarios: 1

Es habitual que tengamos por casa un montón de pilas que, en ocasiones, no sabemos si están cargadas o se han gastado. Vamos a realizar un medidor de carga utilizando la placa de Arduino. El máximo que podemos medir es…

Comentarios - 2

Deja un comentario

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

Francisco
16 February, 2021

(gracias! Me parece una entrada muy bien explicada.


Alejandra sánchez
19 March, 2021

Está increible tu post! paso a paso super bien explicado, pero yo creo que algo estoy haciendo mal y nadie puede resolverme esa duda. Mi sensor está indicandome 46 cms, 60 cms, pero son 6 o 4.5 cms… sabes cual puede ser el problema?