Ejercicio 30: Siguelíneas

El robot selecciona dos valores de luminosidad y los usa para distinguir una línea y seguirla.

Novedades hardwareNovedades software
 Calibrado de sensores de luz

Requisitos: Chasis del robot, circuito de potencia

Planteamiento: Un clásico.

Presentación de:

Vamos a tomar dos valores de luminosidad como referencia: uno corresponderá al negro y otro al blanco.

Para ello, nada más comenzar, enfrentamos el sensor izquierdo a uno de los dos tonos, da igual cual, y luego, mientras pulsamos el final de carrera, lo enfrentamos al otro.

Cuando soltemos el pulsador, el procedimiento niveles( ) habrá guardado los dos valores de las señales analógicas correspondientes a las dos intensidades de luz en dos variables, y habrá obtenido el valor absoluto de la diferencia (por eso dará igual cuál midamos primero).

Este procedimiento está en el void setup( ), por lo que se ejecutará sólo una vez al inicio.

En el bucle principal se toman las decisiones, la información la aportan otros procedimientos:

  • compruebatoque( ) revisa si se ha pulsado el final de carrera, y si es así usa resetea( ) para guardar esa información en una variable que adopta dos valores.
  • compruebaluz( ) actualiza los valores de las señales de los sensores y calcula su diferencia.

La primera decisión se refiere a si hay colisión, un condicional compara el valor de la variable actualizada por compruebatoque( ) y si la hay, ejecuta evitaobstaculo( ), que es un conjunto de movimientos de intención evasiva.

Luego se pregunta si estamos en la línea o no. Supuesto que hemos comenzado con ambos sensores a los lados, es decir sobre blanco, nos mantendremos en el camino si ninguno detecta negro.

Cuando uno de los sensores se sitúe sobre la línea negra y, por lo tanto, esté el robot en una trayectoria que lo sacaría del camino, la diferencia entre las señales ( el otro sensor aún está sobre blanco) aumentará.

Los condicionales anidados nos seleccionan las diferentes alternativas, llamando a los procedimientos que originan el movimiento correspondiente.

Variantes:

  • Alinea los sensores, toma las medidas y ajusta la sensibilidad para que el robot no se caiga de una mesa

CODIGO FUENTE

 Copyright (C) 2006  Juan Carlos Alonso de Mena
 This program is free software; you can redistribute it and/or modify it under the terms
 of the GNU General Public License as published by the Free Software Foundation;
 See the GNU General Public License for more details?

  • Motor dc y circuito con par Darlington y relé de doble conmutador configurado como un inversor de giro:

 int motori =6;
 int motord =8;
 int fotod =4;
 int fotoi =5;
 int medida1=0;
 int medida2=0;
 int diferencia=0;
 int sens=2;
 int nivel=0;
 int nivel1=0;                    
 int nivel2=0;
 int puls=2; 
 int c=1;
 int n=0;
 void niveles(){
   while(digitalRead(puls)==LOW){          //mientras no estamos pulsando:
     nivel1=10*analogRead(fotoi);          // guarda la primera medida de luminosidad
   }
   while(digitalRead(puls)==HIGH){         //mientras mantenemos pulsado por primera vez:
     nivel2=10*analogRead(fotod);          // guarda la segunda medida de luminosidad
   }
   nivel=abs(nivel1-nivel2)/sens;          //caracterizamos el nivel de referencia como una fracción 
 }                                         //de la diferencia entre las dos primeras medidas
 void setup(){
   pinMode(motori,OUTPUT);
   pinMode(motord,OUTPUT);
   pinMode(puls,INPUT);
   niveles();                              //ejecuta una vez el proceso de calibrado
 }
 void compruebaluz(){                      //procedimiento que guarda los valres de las señales analógicas de los sensores
   medida1=analogRead(fotoi);              //en dos variables y calcula su diferencia
   medida2=analogRead(fotod);
   diferencia =abs(10*(medida1 - medida2));
 } 
 void resetea (){                          //procedimiento que guarda en la variable c si se ha producido una colisión o no
   c=c*(-1);                                
 }
 void compruebatoque(){
   if(digitalRead(puls) == HIGH){           // si se pulsa el pulsador(normalmente abierto) 
     delay(200);
     resetea();                             //es que se ha producido una colisión
   }
 }  
 void avanza(){
   digitalWrite(motori,LOW);
   digitalWrite(motord,LOW);
 }
 void retrocede(){
   digitalWrite(motori,HIGH);
   digitalWrite(motord,HIGH);
 }  
 void giraderecha(){
   digitalWrite(motori,LOW);
   digitalWrite(motord,HIGH);
 }
 void giraizquierda(){
   digitalWrite(motori,HIGH);
   digitalWrite(motord,LOW);
 }
 void evitaobstaculo(){                     //acción evasiva para cuando hay colisión
   retrocede();                          
   delay(800);
   giraderecha();
   delay(800);
 } 
 void loop(){
   compruebatoque();                        //comprobamos si ha chocado con algo
   if(c==-1){                               //si ha chocado:
     evitaobstaculo();                      //emprende la acción evasiva
     resetea();                             //y deja la variable indicando que no hay choque
   }      
   compruebaluz();                          //actualizamos los valores de las señales de los sensores
   if(medida1>=medida2){                    //si hay más luz a la izquierda:
     if(diferencia>nivel){                  //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraizquierda();                     // gira a la izquierda
     }     else{                            //si la diferencia es menor que el nivel:
       avanza();                            //avanza
       delay(500);
     }
   }
   else{                                    //si hay más luz ala derecha
     if(diferencia>nivel){                  //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraderecha();                       // gira a la derecha
     }
     else{                                  //si la diferencia es menor que el nivel:
       avanza();                            //avanza
       delay(500);
     }
   }
 }  

  • Motor dc y circuito con driver integrado 293D:

 int medida1=0;
 int medida2=0;
 int diferencia=0;
 int sens=2;
 int nivel=0;
 int nivel1=0;
 int nivel2=0;
 int puls = 2; 
 int activai=8;
 int activad=13;
 int motord1=9;
 int motord2=10;
 int motori1=11;
 int motori2=12;
 int fotoi =0;
 int fotod =1;
 int n=0;
 int c=1;
 void niveles(){
   while(digitalRead(puls)==LOW){  //mientras no estamos pulsando:
     nivel1=10*analogRead(fotoi);  // guarda la primera medida de luminosidad
   }
   while(digitalRead(puls)==HIGH){ //mientras mantenemos pulsado por primera vez:
     nivel2=10*analogRead(fotod);  // guarda la segunda medida de luminosidad
   }
   nivel=abs(nivel1-nivel2)/sens;  //caracterizamos el nivel de referencia como una fracción 
 }                                 //de la diferencia entre las dos primeras medidas
 void para(){
   digitalWrite(activai,LOW);                  
   digitalWrite(activad,LOW);  
 }                                    
 void setup(){
   pinMode(motori1,OUTPUT);
   pinMode(motori2,OUTPUT);
   pinMode(motord1,OUTPUT);
   pinMode(motord2,OUTPUT);
   pinMode(activai,OUTPUT);
   pinMode(activad,OUTPUT);
   pinMode(puls,INPUT);
   niveles();                      //ejecuta una vez el proceso de calibrado 
   while(digitalRead(puls)==LOW){  //mientras no se vuelva a pulsar
     para(); 
   }                               //los motores están parados
 }
 void compruebaluz(){              //procedimiento que guarda los valres de las señales analógicas de los sensores
   medida1=analogRead(fotoi);      //en dos variables y calcula su diferencia
   medida2=analogRead(fotod);
   diferencia =abs(10*(medida1 - medida2));
 } 
 void resetea(){                   //procedimiento que guarda en la variable c si se ha producido una colisión o no
   c=c*(-1);
 }
 void compruebatoque(){
   if(digitalRead(puls) == HIGH){  // si se pulsa el pulsador(normalmente abierto)
     delay(200);
     resetea();                    //es que se ha producido una colisión
   }
 }  
 void avanza(){
   digitalWrite(motori1,HIGH);
   digitalWrite(motori2,LOW);
   digitalWrite(motord1,HIGH);
   digitalWrite(motord2,LOW);
 }
 void retrocede(){
   digitalWrite(motori1,LOW);
   digitalWrite(motori2,HIGH);
   digitalWrite(motord1,LOW);
   digitalWrite(motord2,HIGH);
 }  
 void giraderecha(){
   digitalWrite(motori1,HIGH);
   digitalWrite(motori2,LOW);
   digitalWrite(motord1,LOW);
   digitalWrite(motord2,HIGH);
 }
 void giraizquierda(){
   digitalWrite(motord1,HIGH);
   digitalWrite(motord2,LOW);
   digitalWrite(motori1,LOW);
   digitalWrite(motori2,HIGH);
 }
 void evitaobstaculo(){            //acción evasiva para cuando hay colisión
   retrocede();
   delay(1000);
   giraderecha();
   delay(1000);
 } 
 void loop(){                      //cuando se pulse por segunda vez:
   digitalWrite(activai,HIGH);     //activamos los motores 
   digitalWrite(activad,HIGH);
   compruebatoque();               //comprobamos si ha chocado con algo
   if(c==-1){                      //si ha chocado 
     evitaobstaculo();             //emprende la acción evasiva
     resetea();                    //y deja la variable indicando que no hay choque
   }      
   compruebaluz();                 //actualizamos los valores de las señales de los sensores
   if (medida1>=medida2){          //si hay más luz a la izquierda:
     if(diferencia>nivel){         //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraizquierda();            // gira a la izquierda
     }
     else{                         //si la diferencia es menor que el nivel:
       avanza();                   //avanza
       delay(700);
     }
   }
   else{
     if(diferencia>nivel){         //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraderecha();              // gira a la derecha
     }
     else{                         //si la diferencia es menor que el nivel:
       avanza();                   //avanza
       delay(500);
     }
   }
 }  

  • Motor paso a paso y circuito con driver integrado 74H245

 int vel2=5;         
 int vel =5;        
 int unoai = 8;         
 int unobi = 9;         
 int dosai = 10;         
 int dosbi = 11;        
 int unoad = 2;
 int unobd = 3;
 int dosad = 4;
 int dosbd = 5;
 int fotod =4;
 int fotoi =5;
 int medida1=0;
 int medida2=0;
 int diferencia=0;
 int sens=2;
 int nivel=0;
 int nivel1=0;
 int nivel2=0;
 int puls=2; 
 int c=1;
 int n=0;
 void niveles(){
   while(digitalRead(puls)==LOW){   //mientras no estamos pulsando:
     nivel1=10*analogRead(fotoi);   // guarda la primera medida de luminosidad
   }
   while(digitalRead(puls)==HIGH){  //mientras mantenemos pulsado por primera vez:
     nivel2=10*analogRead(fotod);   // guarda la segunda medida de luminosidad
   }
   nivel=abs(nivel1-nivel2)/sens;   //caracterizamos el nivel de referencia como una fracción 
 }                                  //de la diferencia entre las dos primeras medidas
 void para(){
   digitalWrite(unoai,LOW);
   digitalWrite(unoad,LOW);
   digitalWrite(unobi,LOW);
   digitalWrite(unobd,LOW);
   digitalWrite(dosai,LOW);
   digitalWrite(dosad,LOW);
   digitalWrite(dosbi,LOW);
   digitalWrite(dosbd,LOW);
 }                                      
 void setup(){
   pinMode(unoai,OUTPUT);      
   pinMode(unobi,OUTPUT);
   pinMode(dosai,OUTPUT);
   pinMode(dosbi,OUTPUT);
   pinMode(unoad,OUTPUT);
   pinMode(unobd,OUTPUT);
   pinMode(dosad,OUTPUT);
   pinMode(dosbd,OUTPUT);
   pinMode(puls,INPUT);
   niveles();                       //ejecuta una vez el proceso de calibrado
   while(digitalRead(puls)==LOW){   //mientras no se pulse 
     para();                        //los motores están parados
   }                                 
 }
 void compruebaluz(){               //procedimiento que guarda los valres de las señales analógicas de los sensores
   medida1=analogRead(fotoi);       //en dos variables y calcula su diferencia
   medida2=analogRead(fotod);
   diferencia =abs(10*(medida1 - medida2));
 } 
 void resetea(){                    //procedimiento que guarda en la variable c si se ha producido una colisión o no
   c=c*(-1);
 }
 void compruebatoque(){
   if(digitalRead(puls) == HIGH){   // si se pulsa el pulsador(normalmente abierto)
     delay(200);
     resetea();                     //es que se ha producido una colisión
   }
 }
 void avanza(){
   digitalWrite(unoai,HIGH);
   digitalWrite(unoad,HIGH);
   digitalWrite(unobi,LOW);
   digitalWrite(unobd,LOW);
   digitalWrite(dosai,HIGH);
   digitalWrite(dosad,HIGH);
   digitalWrite(dosbi,LOW);
   digitalWrite(dosbd,LOW);
   delay(vel);
   digitalWrite(unoai,LOW);
   digitalWrite(unoad,LOW);
   digitalWrite(unobi,HIGH);
   digitalWrite(unobd,HIGH);
   delay(vel);
   digitalWrite(dosai,LOW);
   digitalWrite(dosad,LOW);
   digitalWrite(dosbi,HIGH);
   digitalWrite(dosbd,HIGH);
   delay(vel);
   digitalWrite(unoai,HIGH);
   digitalWrite(unoad,HIGH);
   digitalWrite(unobi,LOW);  
   digitalWrite(unobd,LOW);  
   delay(vel);
 } 
 void retrocede(){
   digitalWrite(unoai,LOW);
   digitalWrite(unoad,LOW);
   digitalWrite(unobi,HIGH);
   digitalWrite(unobd,HIGH);
   digitalWrite(dosai,LOW);
   digitalWrite(dosad,LOW);
   digitalWrite(dosbi,HIGH);
   digitalWrite(dosbd,HIGH);
   delay(vel);
   digitalWrite(unoai,HIGH);
   digitalWrite(unoad,HIGH);
   digitalWrite(unobi,LOW);
   digitalWrite(unobd,LOW);
   delay(vel);
   digitalWrite(dosai,HIGH);
   digitalWrite(dosad,HIGH);
   digitalWrite(dosbi,LOW);
   digitalWrite(dosbd,LOW);
   delay(vel);
   digitalWrite(unoai,LOW);
   digitalWrite(unoad,LOW);
   digitalWrite(unobi,HIGH);  
   digitalWrite(unobd,HIGH);  
   delay(vel);
 }
 void giraizquierda(){
   digitalWrite(unoad,HIGH);
   digitalWrite(unoai,LOW);
   digitalWrite(unobd,LOW);
   digitalWrite(unobi,HIGH);
   digitalWrite(dosad,HIGH);
   digitalWrite(dosai,LOW);
   digitalWrite(dosbd,LOW);
   digitalWrite(dosbi,HIGH);
   delay(vel2);
   digitalWrite(unoad,LOW);
   digitalWrite(dosbi,LOW);
   digitalWrite(unobd,HIGH);
   digitalWrite(dosai,HIGH);
   delay(vel2); 
   digitalWrite(dosad,LOW);
   digitalWrite(unobi,LOW);
   digitalWrite(dosbd,HIGH);
   digitalWrite(unoai,HIGH);
   delay(vel2);
   digitalWrite(unoad,HIGH);
   digitalWrite(dosbi,HIGH);
   digitalWrite(unobd,LOW); 
   digitalWrite(dosai,LOW); 
   delay(vel2);    
 }
 void giraderecha(){
   digitalWrite(unoai,HIGH);
   digitalWrite(unoad,LOW);
   digitalWrite(unobi,LOW);
   digitalWrite(unobd,HIGH);
   digitalWrite(dosai,HIGH);
   digitalWrite(dosad,LOW);
   digitalWrite(dosbi,LOW);
   digitalWrite(dosbd,HIGH);
   delay(vel2);
   digitalWrite(unoai,LOW);
   digitalWrite(dosbd,LOW);
   digitalWrite(unobi,HIGH);
   digitalWrite(dosad,HIGH);
   delay(vel2); 
   digitalWrite(dosai,LOW);
   digitalWrite(unobd,LOW);
   digitalWrite(dosbi,HIGH);
   digitalWrite(unoad,HIGH);
   delay(vel2);
   digitalWrite(unoai,HIGH);
   digitalWrite(dosbd,HIGH);
   digitalWrite(unobi,LOW); 
   digitalWrite(dosad,LOW); 
   delay(vel2);    
 }
 void evitaobstaculo(){             //acción evasiva para cuando hay colisión
   retrocede();
   delay(700);
   giraderecha();
   delay(700);
 } 
 void loop(){
   compruebatoque();                //comprobamos si ha chocado con algo
   if(c==-1){                       //si ha chocado (
     evitaobstaculo();              //emprende la acción evasiva
     resetea();                     //y deja la variable indicando que no hay choque
   }      
   compruebaluz();                  //actualizamos los valores de las señales de los sensores
   if (medida1>=medida2){           //si hay más luz a la izquierda:
     if(diferencia>nivel){          //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraizquierda();             // gira a la izquierda
     }
     else{                          //si la diferencia es menor que el nivel:                      
       avanza();                    //avanza
       delay(400);
     }
   }
   else{
     if(diferencia>nivel){          //y si la diferencia entre la izquierda y la derecha es mayor que el nivel fijado al comienzo
       giraderecha();               // gira a la derecha
     }
     else{                          //si la diferencia es menor que el nivel:
       avanza();                    //avanza
       delay(400);
     }
   }
 }  

Volver?

  Copyright (c) 2006  Juan Carlos Alonso de Mena

  Permission is granted to copy, distribute and/or modify this document under the terms of 
 the GNU Free Documentation License, Version 1.2 or any later version published by the
 Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no
 Back-Cover Texts.  A copy of the license is included in the section entitled 
 GNU Free Documentation License?.