ROOMBAKAR

Autores

  • Santiago Rivas Martín
  • Álvaro Lafarga García
  • Juan de la Torre Melero
  • Fernando Rubio Moreno

Objetivo

Nuestro proyecto final de de la asignatura de SEyTR, es el Roombakar, es un coche autónomo fabricado a partir de un Arduino Uno, cartón para el chasis, un par de ruedas, motores, tanto para las ruedas como para el aspirador, sensores de ultrasonidos, un servo y muchos cables.

La funcionalidad del mismo, es localizar obstáculos con un sensor de ultrasonidos para así poder evitarlos y tomar una ruta alternativa que le permita seguir avanzando mientras aspira con una manguera. Además,  hicimos que el Roombakar emitiera sonidos cuando detectaba un objeto delante.

Materiales

MaterialCantidad
Arduino UNO2
Componente de ultrasonido1
Fuente de alimentación USB tipo C1
Arduino Sensor Shield1
Motor Drive Controller Board Module L298N1
Buzzer/Speaker1
Resistencia 550 Ω1
Componentes empleados para el chasis (cartón, material reciclado..)***
Interruptor1
9V Battery
Modulo 4 baterías (1.5V)
1
1
Motores Makeblock 6V 200rpm2
CABLES PROTOBOARD M-M 6525

Planificación y reparto de tareas

A lo largo de la asignatura se han realizado entorno a 5 sesiones de trabajo destinadas a la búsqueda de materiales y al propio desarrollo del proyecto. Debido a las restricciones horarias, nos hemos visto obligados a reducir estas reuniones y trabajar tambien de forma remota en el proyecto. Por lo que las tareas quedaron repartidas de la siguiente forma:

  • En base al servomotor y el zumbador el trabajo lo realizaron Álvaro Lafarga García y Juan de la la Torre Melero
  • El sistema formado por los motores del propio vehículo junto al sistema de recogida formó parte del trabajo realizado por Santiago Rivas Martín y Fernando Rubio Moreno

Una vez el grupo disponía de los materiales necesarios nos reunimos para realizar el ensamblado y poner a prueba el proyecto.

Explicación del código

En cuanto al código, vemos que predomina la simplicidad.

Cuenta con 8 subprogramas, además del loop() y del setup(),

Podemos dividirlos en 2 tipos, los que están relacionados con los motores, y los que están relacionados con el servo y el sensor.

Los del servo y sensor, son 3, leer(), que devuelve el valor medido por el sonar, medida en centímetros, y pone un valor estándar si la distancia es muy grande y no detecta nada el sensor.

Los otros 2 métodos orientan el servo hacia la izquierda o la derecha y llaman a leer() para conseguir el valor.

Los otros 5, relacionados con el movimiento de los motores también son muy sencillos, tenemos un método llamado parada(), que como su nombre indica, para el coche, pero además, como funcionalidad extra, reutilizamos el circuito de la primera práctica para hacer que cuando sea llamado este método, que haga un pitido. Los subprogramas continuar() y atras(), ponen en HIGH los pines que controlan el movimiento de los motores en cada orientación haciendo que giren hacia delante y hacia detras respectivamente. Los 2 restantes,  giro_derecha() y giro_izquierda(), son para girar, haciendo que el Roombakar gire sobre sí mismo, hacia uno de los 2 lados, con un delay de 300ms para rotar en torno a 90º sobre la posición original y después haciendo que las ruedas giren hacia delante otra vez, pero con su nueva orientación.

Finalmente, en setup(), configuramos los pines de salida, orientamos el servo hacia delante, y leemos los valores de distancia iniciales para estar seguros que no hay obstáculos delante.

En loop(), ajustamos valores iniciales, y constantemente, checkeamos la distancia a la que se encuentra el obstáculo, y llamamos a los métodos anteriormente descritos, para parar el coche y reproducir un pitido que avisa que hemos encontrado un objeto, y mirar cual de los 2 lados está más despejado de obstáculos y elegir ese, en caso de que la distancia actual sea menor que 25.

#include <Servo.h>          //Libreria servomotor
#include <NewPing.h>        //Libreria sensor ultrasonidos. Descaragada
#include <TimerFreeTone.h>  //Libreria para el uso de zumbador. Descaragada



//L298N pines de control
const int MotorIzqDelante = 4;
const int MotorIzqDetras = 5;
const int MotorDerDelante = 3;
const int MotorDerDetras = 2;


//Pines del sensor
#define trig_pin A1
#define echo_pin A3

#define maximum_distance 450

boolean continua_hacia_delante = false;
int dist = 100;
NewPing sonar(trig_pin, echo_pin, maximum_distance);
Servo servo_motor;

//Zumbador
#define TONE_PIN 8
int melodia[] = {900};
int duracion[] = {250};


void setup() {
  pinMode(MotorIzqDelante, OUTPUT);
  pinMode(MotorIzqDetras, OUTPUT);
  pinMode(MotorDerDelante, OUTPUT);
  pinMode(MotorDerDetras, OUTPUT);
  pinMode(TONE_PIN, OUTPUT);
  servo_motor.attach(12);
  //Orientarlo hacia delante
  servo_motor.write(90);
  delay(2000);
  dist = leer();
  delay(100);
  dist = leer();
  delay(100);
  dist = leer();
  delay(100);
  dist = leer();
  delay(100);
  //Leer valores distancia
}

void loop() {
  //distancia a la derecha
  int distDer = 0;
  //distancia a la izquierda
  int distIzq = 0;
  delay(50);
  //distancia a la que se encuentra el objeto
  if (dist <= 25) {
    parada();
    delay(300);
    atras();
    delay(400);
    parada();
    delay(300);
    distDer = miraDerecha();
    delay(300);
    distIzq = miraIzquierda();
    delay(300);
    //si puede girar a derecha
    if (dist >= distIzq) {
      giro_derecha();
      parada();
    }
    //si no, gira izquierda
    else {
      giro_izquierda();
      parada();
    }
  }
  //si la distancia al objeto es mayor
  else {
    continuar();
  }
  dist = leer();
}

void parada() {
  digitalWrite(MotorIzqDetras, LOW);
  digitalWrite(MotorIzqDelante, LOW);
  digitalWrite(MotorDerDelante, LOW);
  digitalWrite(MotorDerDetras, LOW);
  //Hacemos sonar el zumbador al detectar algo
  TimerFreeTone(TONE_PIN, melodia[0], duracion[0]);
  delay(50);
}

void continuar() {
  if (!continua_hacia_delante) {
    continua_hacia_delante = true;
    digitalWrite(MotorIzqDelante, HIGH);
    digitalWrite(MotorDerDelante, HIGH);
    digitalWrite(MotorIzqDetras, LOW);
    digitalWrite(MotorDerDetras, LOW);
  }
}

void atras() {
  continua_hacia_delante = false;
  digitalWrite(MotorIzqDetras, HIGH);
  digitalWrite(MotorDerDetras, HIGH);
  digitalWrite(MotorIzqDelante, LOW);
  digitalWrite(MotorDerDelante, LOW);
}

void giro_derecha() {
  //rotar sobre si mismo
  digitalWrite(MotorIzqDelante, HIGH);
  digitalWrite(MotorDerDetras, HIGH);
  digitalWrite(MotorIzqDetras, LOW);
  digitalWrite(MotorDerDelante, LOW);
  delay(300);
  //continuar hacia delante
  digitalWrite(MotorIzqDelante, HIGH);
  digitalWrite(MotorDerDelante, HIGH);
  digitalWrite(MotorIzqDetras, LOW);
  digitalWrite(MotorDerDetras, LOW);
}

void giro_izquierda() {
  //rotar sobre si mismo
  digitalWrite(MotorIzqDetras, HIGH);
  digitalWrite(MotorDerDelante, HIGH);
  digitalWrite(MotorIzqDelante, LOW);
  digitalWrite(MotorDerDetras, LOW);
  delay(300);
  //continuar hacia delante
  digitalWrite(MotorIzqDelante, HIGH);
  digitalWrite(MotorDerDelante, HIGH);
  digitalWrite(MotorIzqDetras, LOW);
  digitalWrite(MotorDerDetras, LOW);
}

int miraDerecha() {
  //giramos sensor hacia la derecha
  servo_motor.write(10);
  delay(500);
  int dist = leer();
  delay(100);
  servo_motor.write(90);
  return dist;
}

int miraIzquierda() {
  //giramos sensor hacia la izquierda
  servo_motor.write(170);
  delay(500);
  int dist = leer();
  delay(100);
  servo_motor.write(90);
  return dist;
  delay(100);
}

int leer() {
  delay(70);
  int cm = sonar.ping_cm();
  if (cm == 0) {
    //si la distancia al objeto es mayor que lo que lee
    //ponemos una distancia estandar
    cm = 250;
  }
  return cm;
}

Montaje del proyecto

El proyecto está formado por una carcasa la cual hemos fabricado a partir de cartón y componentes de plastico reutilizados. El Arduino junto al resto de componentes vendría dentro de la caja entregada a principio de la asignatura o comprado mas tarde por el grupo de trabajo.

Se compone de un servomotor se conecta a un lector de ultrasonidos el cual nos permite reconocer el entorno, no es perfecto ya que necesitábamos hacer modificaciones en el sistema para que el arco del servomotor no llegara a identificar al propio vehículo como obstáculo.

Implementado el circuito y ya puesto a prueba, tanto motores como sensor de ultrasonidos, decidimos añadir un zumbador para incluirle un sonido al detectar con el sensor un obstáculo. Este está conectado a GND y comparte la señal del sensor de ultrasonidos (La conexiones se muestran en la segunda fotografía, donde el lector de ultrasonidos ocupa el pin 8 y el zumbador el pin 9), también se le ha añadido a esa parte del circuito una resistencia de 550 ohmios como incluimos en la Practica obligatoria entregada anteriormente en la asignatura.

A partir de aquí, en la misma proto placa conectaremos la batería y las entradas del motor y concluimos conectandola batería externa a la placa de Arduino

Problemas y soluciones

Uno de los principales problemas que hemos tenido, es el funcionamiento de las ruedas.

Al contar solamente con 2 motores, el peso del chasis hacia que se redujera su velocidad notablemente. También, hemos notado que algunas veces, en el lateral más pesado, la rueda no giraba del todo bien, haciendo que o bien gire sobre sí mismo o gire más hacia ese lado.

En cuanto a la otra rueda, la que no lleva motor, hemos notado también, que no se pone recta después de hacer giros, haciendo que cuando vuelva a ir en línea recta, la trayectoria del Roombakar sea orientada hacia ese lado.

Otro de los problemas que hemos tenido, no tiene que ver con la parte Hardware, si no con el Software, y Arduino.

En nuestro caso, hicimos que el Roombakar emitiera sonidos cuando detectaba un objeto delante. Al parecer, al contar con un sensor de ultrasonidos, el código usaba un Timer para controlar el valor medido, y cuando incluímos el zumbador, al realizar la operación tone(), nos saltaba un fallo por que al parecer, tone usa el mismo Timer y no es compatible el uso con el mismo Timer. La solución, después de buscar y leer información relativa a este fallo, en los foros de Arduino, encontramos una solución en la que una persona que realizó una librería para hacer la operación tone(), pero, sin el uso de Timers, por lo que descargándola y añadiéndola mediante .ZIP pudimos implementar dicha funcionalidad.

Además de estos problemas, también llegamos a implementar la idea de reducir  la velocidad del motor para que el Roombakar pudiese recoger la basura mejor, sin embargo, acabamos descartando esta opción ya que cuando le pusimos la botella y la batería externa para que funcionase, esto objetos produjeron un peso extra que daba a lugar a que ya fuera a una velocidad deseada y no tuviese problemas al limpiar 

Pese a esto, dejamos por aquí el código y una explicación de esta funcionalidad por si alguien en el futuro quisiera utilizarla. Este código habría que añadirlo al que ya está para su correcto funcionamiento.

// ENA y ENB para controlar la velocidad de los motores
const int ENA = 13;
const int ENB = 11;
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);

void parada() {
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}
void continuar() {
    analogWrite(ENA, 120);
    analogWrite(ENB, 120);
  }
}

void atras() {
  analogWrite(ENA, 120);
  analogWrite(ENB, 120);
}

void giro_derecha() {
  analogWrite(ENA, 120);
  analogWrite(ENB, 0);
  delay(500);
  analogWrite(ENA, 120);
  analogWrite(ENB, 120);
}

void giro_izquierda() {
  analogWrite(ENA, 0);
  analogWrite(ENB, 120);
  delay(500);
  analogWrite(ENA, 120);
  analogWrite(ENB, 120);
}

Esta implementación básicamente consiste en ponerle un ENB y ENA los cuales determinarán a qué velocidad girará nuestras ruedas. Es por esto que nos ayudaremos del analogWrite para meterle un valor exacto en vez de un valor máximo o mínimo como High o Low.

También te podría gustar...

Deja una respuesta

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