Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos » Arduino y Raspberry Pi
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

10/06/2013 #1

Avatar de eumelvi

Arduino: Atasco con la programación de un bot de laberinto.
Hola a todos.
Estoy realizando un proyecto fin de curso que consiste en un robot resuelve laberinto, pero no doy con las ordenes adecuadas para que realice el método de girar siempre a la derecha. Si alguien con más conocimientos que yo (que serán la mayoría) me pudiese orientar se lo agradecería.
Dejo copiado el código y a la espera de vuestros buenos consejos.

Código:
// Ultrasonic - Library for HR-SC04 Ultrasonic Ranging Module.
// Proyecto fin de curso:
// PRADUINO_BOT_113
// BOT RESUELVE LABERINTO
// By: Eumelvi

//se incluye una librería para el control de los sensores SRF05, 
//(la librería es para los HR-SC04, pero es válida para los SRF05)
//cortesía de www.ardublog.com
#include <Ultrasonic.h> 

//definir variables globales:
Ultrasonic ultra(7,6);   // asignamos los pines del sensor delantero llamado ultra(pulso7,Eco6)
Ultrasonic ultraDer(9,8);  // y para el derecho (Trig PIN,Echo PIN)
int motor1_a = 3; //asignamos los pines de los motores
int motor1_b = 4; //motor1=derecho
int motor2_c = 11; //motor2=izquierdo
int motor2_d = 12; //a-c=adelante/b-d=atrás

//se definen las funciones de los movimientos de motores (direcciones de avance)

void adelante() //creamos función()
{
  digitalWrite(motor1_a,HIGH); //se ponen en alto las salidas
  digitalWrite(motor1_b,LOW);  //a-c y en bajo b-d
  digitalWrite (motor2_c, HIGH); 
  digitalWrite (motor2_d, LOW);
}

void atras()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,HIGH);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, HIGH);
}

void paro()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, LOW);
}

void derecha()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,HIGH);
  digitalWrite (motor2_c, HIGH);
  digitalWrite (motor2_d, LOW);
}

void izquierda()
{
  digitalWrite(motor1_a,HIGH);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, HIGH);
}

void corrDer()
{
  digitalWrite(motor1_a,HIGH);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, LOW);
}

void corrIzq()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, HIGH);
  digitalWrite (motor2_d, LOW);
}


void setup() 
{
  Serial.begin(9600); //inicializar las comunicaciones serie

  pinMode(motor1_a, OUTPUT); //pone en salida los pines de los motores
  pinMode(motor1_b, OUTPUT); 

  pinMode(motor2_c, OUTPUT); 
  pinMode(motor2_d, OUTPUT); 
}


void loop()
{
  Serial.print("delante: ");  //imprime en monitor
  Serial.print(ultra.Ranging(CM)); //escribe en CM or INC las medidas de los sensores
  Serial.print(" cm     " );  //imprime cm despues de los datos medidos
  delay(50); //espera hasta escribir la siguiente medicion

  Serial.print("derecha: ");
  Serial.print(ultraDer.Ranging(CM)); // CM or INC
  Serial.println(" cm" );
  delay(50);

  int cm, cm2; //declara las variables de las medidas de los sensores
  cm=ultra.Ranging(CM); //cm= a la medida en cm del sensor delantero
  cm2=ultraDer.Ranging(CM); //cm2= a la medida del derecho

  //aquí comienzan las órdenes y decisiones que tomará el bot.

if(cm2>5&&cm2<10)
{
  adelante();//avanza
  delay(10);//10ms
}

if(cm<8&&cm2>5)
{
  derecha();
  delay(1);
}

/*
if(cm2<9&&cm2>8)
  {
    adelante();   
    delay(1); 
    paro(); 
  }
  else 
  {
    if (cm2<8)  
    {  
      izquierda();   
      delay(1);
      paro();   
    }
    else
    {
      derecha();
      delay(1);
      paro();  
    }
  }*/
}
12/06/2013 #2


Hola, primero que nada ¿qué tipo de motores utilizas? ¿utilizas un puente H?

Bueno he revisado tu código y he notado algunos detalles:

Código:
if(cm<8&&cm2>5)
{
  derecha();  //Invoca al método corrDer(), es el que debería realizar el movimiento, según el código
  delay(1);    //dale más tiempo para que alcance a generar el movimiento 
}

Saludos!
12/06/2013 #3

Avatar de eumelvi

Bajager dijo: Ver Mensaje
Hola, primero que nada ¿qué tipo de motores utilizas? ¿utilizas un puente H?

Bueno he revisado tu código y he notado algunos detalles:

Código:
if(cm<8&&cm2>5)
{
  derecha();  //Invoca al método corrDer(), es el que debería realizar el movimiento, según el código
  delay(1);    //dale más tiempo para que alcance a generar el movimiento 
}
Saludos!
hola Bajager, utilizo dos motores DC, un puente H basado en el L298 y dos sensores HY-SFR05.
derecha(); //NO Invoca al método corrDer(), si no a derecha()
delay(1); //con ese tiempo me hace el giro bien, si le pongo más, no
Voy a pegar el código modificado, hasta ahora es el que mejor ha funcionado, aunque aun no está completo y no realiza bien su cometido.
Con este codigo avanza detectando la pared derecha y manteniéndose entre 8 y 10cm, cuando el sensor delantero (cm) <10, gira a la izquierda, si es mayor, a la derecha.
Código:
#include <Ultrasonic.h> 

//definir variables globales:
Ultrasonic ultra(7,6);   // asignamos los pines del sensor delantero llamado ultra(pulso5,Eco6)
Ultrasonic ultraright(9,8);  // y para el derecho (Trig PIN,Echo PIN)
int motor1_a = 3; //asignamos los pines de los motores
int motor1_b = 4; //motor1=derecho
int motor2_c = 11; //motor2=izquierdo
int motor2_d = 12; //a-c=adelante/b-d=atras

//se definen las funciones de los movimientos de motores (direcciones de avance)

void adelante() 
{
  digitalWrite(motor1_a,HIGH); //se ponen en alto las salidas
  digitalWrite(motor1_b,LOW);  //a-c y en bajo b-d
  digitalWrite (motor2_c, HIGH); 
  digitalWrite (motor2_d, LOW);
}

void atras()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,HIGH);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, HIGH);
}

void paro()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, LOW);
}

void derecha()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,HIGH);
  digitalWrite (motor2_c, HIGH);
  digitalWrite (motor2_d, LOW);
}

void izquierda()
{
  digitalWrite(motor1_a,HIGH);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, HIGH);
}
void corrDer()
{
  digitalWrite(motor1_a,LOW);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, HIGH);
  digitalWrite (motor2_d, LOW);
}
void corrIzq()
{
  digitalWrite(motor1_a,HIGH);
  digitalWrite(motor1_b,LOW);
  digitalWrite (motor2_c, LOW);
  digitalWrite (motor2_d, LOW);
}
void setup() 
{
  Serial.begin(9600); //inicializar las comunicaciones serie
  pinMode(motor1_a, OUTPUT); //pone en salida los pines de los motores
  pinMode(motor1_b, OUTPUT); 
  pinMode(motor2_c, OUTPUT); 
  pinMode(motor2_d, OUTPUT); 
}

void loop()
{
  long cm, cm2; //declara las variables de las medidas de los sensores
 
  cm=ultra.Ranging(CM); //cm= a la medida en cm del sensor delantero
  Serial.print("delante: ");  //imprime en monitor
  Serial.print(cm); //escribe en CM or INC las medidas de los sensores
  Serial.print(" cm     " );  //imprime cm despues de los datos medidos
  cm2=ultraright.Ranging(CM); //cm2= a la medida del derecho
  Serial.print("derecha: ");  //imprime en monitor
  Serial.print(cm2); //escribe en CM or INC las medidas de los sensores
  Serial.println(" cm     " );  //imprime cm despues de los datos medidos

  //aqui* comienzan las ordenes y decisiones que tomara el bot.

  //adelante();//avanza
  //delay(10);//10ms
  //paro();//y para

  if(cm2<10&&cm2>8)//si la distancia del sensor delantero es mayor de 10cm
    //o menor de 8cm y, ademas, la distancia del sensor derecho es menor de 8cm...
  {
    adelante();  //y avanza 
    delay(2);    //otro ms
  }
  else  
  {
    if(cm2>10)
    {
      corrDer();   //gira a la derecha
      delay(1);    //un ms
    }
    else
    {
      corrIzq();
      delay(1);
    }
  }
}
12/06/2013 #4

Avatar de eumelvi

Hay una errata en el comentario del codigo, en el primer if, donde dice sensor delantero hay que leer derecho (cm2)
12/06/2013 #5


Habría que cálcular bien las distancias del laberinto para que haga el giro sin atorarse

Código:
//si quieres que mientras no haya obstaculo enfrente siga hacia delante, entonces la condición seria:
if(cm>10) {
   adelante();
   delay(2);
} 
else { //Si hay obstaculo, paras y checas el sensor derecho 
   paro(); 
   delay(100); //hay que darles un tiempo a los motores para que se detengan
   if(cm2 < 10) {
      izquierda(); 
      delay(1);
   }
   else { 
      derecha();
      delay(1);
}
Saludos!
13/06/2013 #6

Avatar de eumelvi

Bajager dijo: Ver Mensaje
Habría que cálcular bien las distancias del laberinto para que haga el giro sin atorarse

Saludos!
Aquí dejo el enlace del objetivo de la prueba: http://www.madridbot.org/pruebas_2013.htm#Laberinto
El código hace lo que promete, gracias, pero aun no consigo definirlo.
Saludos.
13/06/2013 #7

Avatar de Sebastian1989

Si sabes a priori el mapa del laberinto me parece que el algoritmo de girar siempre a la derecha no es la mejor opción ya que esta es muy lenta, si se permite podrías agregar botones pre configurados con las soluciones dependiendo de donde partes.
14/06/2013 #8


eumelvi dijo: Ver Mensaje
Aquí dejo el enlace del objetivo de la prueba: http://www.madridbot.org/pruebas_2013.htm#Laberinto
El código hace lo que promete, gracias, pero aun no consigo definirlo.
Saludos.
A lo que veo, tu robot se queda girando en la parte central del laberinto.

Una solución seria:

- Crea un arreglo bidimensional de 9 x 9 y llénalo de puros ceros, éste indicaría cada cuadrito de tu laberinto. Por ejemplo el cero indica que no has pasado por ese cuadrito
- Dependiendo de las medidas de cada cuadrito y con ayuda del sensor ultrasónico puedes ir calculando en que cuadrito te encuentras e ir modificando el arreglo, ve incrementando en uno cada vez que pases por ese cuadrito, de esta manera llevarás un control del camino recorrido y sus respectivas repeticiones
- Una vez que se conozca si ya se ha pasado por ese camino podrías evitar repetirlo y entonces buscar una salida apoyandote en los ceros de tu arreglo.


Trata de implementarlo (podría funcionar), saludos!
14/06/2013 #9

Avatar de eumelvi

Gracias por responder.
Creo que he dado con algo, lo he probado y funciona, aunque hay que pulirlo un poco para que vaya mas fluido.
Saludos.

Código:
  
   if(cm2==12){
    adelante();//avanza
    delay(100);//100ms
    paro();//y para
    delay(100);
  }
  else  
  {
    if(cm2>12){
      corrDer();   //corrige a la derecha 
      delay(100);
      paro();
      delay(10);
      adelante();
      delay(10);
      paro();
      delay(10);
    }
    else{
      corrIzq();
      delay(50);
      paro();//y para
      delay(10);
    }
  }
    if(cm<10){
      izquierda();
      delay(100);
      paro();
      delay(10);
    }
22/06/2013 #10

Avatar de CarlGauss

Yo lo haría de esta forma, puede ser que no este bien hecha en lo que respecta al código. Pero podría asegurarte de que es funcional
Con respecto a la fluidez, eso nos lo indicas así lo vamos limpiando

Nota: Solo modifiqué los procedimientos 'setup' y 'loop':

Código:
//Estas variables mejor declararlas por fuera del procedimiento 'loop'
long cm, cm2; //Medidas de los sensores
//


void setup() 
{
  Serial.begin(9600); //inicializar las comunicaciones serie
  pinMode(motor1_a, OUTPUT); //pone en salida los pines de los motores
  pinMode(motor1_b, OUTPUT); 
  pinMode(motor2_c, OUTPUT); 
  pinMode(motor2_d, OUTPUT); 

  adelante(); //Empieza con el robot moviéndose hacia delante
}

void loop()
{
 
  cm=ultra.Ranging(CM); //cm= a la medida en cm del sensor delantero
  Serial.print("Delante: ");  //imprime en monitor
  Serial.print(cm); //escribe en CM or INC las medidas de los sensores
  Serial.print(" cm.     " );  //imprime cm despues de los datos medidos
  cm2=ultraright.Ranging(CM); //cm2= a la medida del derecho
  Serial.print("Derecha: ");  //imprime en monitor
  Serial.print(cm2); //escribe en CM or INC las medidas de los sensores
  Serial.println(" cm.     " );  //imprime cm despues de los datos medidos

  //MOVIMIENTO DEL ROBOT
  //Mientras no haya una pared delante (5cm aproximadamente), el robot no se detendrá a girar.
  //Y cuando haya una, el robot girará a la derecha o izquierda (dependiendo en si hay una pared).
  //El robot girará indefinidamente hasta que no encuentre pared por delante suyo,
  //cuando nuevamente volverá a moverse normalmente.


  if(cm<5) //Si hay una pared delante
  {
    if(cm2>5) //Si no hay una pared a la derecha
    {
      derecha(); //Giramos a la derecha
    }
    else //Si hay una pared a la derecha
    {
      izquierda(); //Giramos a la izquierda
    }
  }
  else //Si no hay una pared delante
  {
    adelante(); //Seguimos adelante
  }
}
01/07/2013 #11

Avatar de eumelvi

tfmtoto dijo: Ver Mensaje
Yo lo haría de esta forma, puede ser que no este bien hecha en lo que respecta al código. Pero podría asegurarte de que es funcional
Con respecto a la fluidez, eso nos lo indicas así lo vamos limpiando

Nota: Solo modifiqué los procedimientos 'setup' y 'loop':
Gracias tfmtoto, pero para que funcione bien hay que poner primero como premisa que cm2==12cm, y a partir de ahí ir implementando las diferentes opciones. De todas formas ya lo he terminado y ahora estoy con otro proyecto, un rastreador, así que cuando empiece a tener dificultades con el código espero vuestra ayuda.
Saludos.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Buscar más temas sobre:
Lupa Arduino y Raspberry Pi

Cerrar
Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos » Arduino y Raspberry Pi

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.