Ejercicio 30: Siguelíneas
El robot selecciona dos valores de luminosidad y los usa para distinguir una línea y seguirla.
| Novedades hardware | Novedades 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?.