El reto que me planteé era controlar un camión de radio control colocándole un sensor de distancia infrarrojo, situado sobre un servo de modo que cuando detecta un obstáculo hace girar al sensor de modo que pueda descubrir si hay algún obstáculo que le impida girar.
Para controlar el camión he utilizado los controles de marcha y giro del emisor de radiocontrol (que he colocado sobre el propio camión) manejándolos mediante cada uno de los cuatro MOSFET, símplemente para abrir o cerar cada uno de los cuatro interruptores.
Tanto el sensor de infrarrojos como el servo sobre el que se apoya van directamente a la placa de Arduino.
Debido a la velocidad que desarrolla el camión unido al poco ángulo de giro de sus ruedas me ha obligado a frenar cuando se detecta un obstáculo al frente y entonces, tras detectar si hay espacio para torcer retroceder girando. Inicialmente para frenar únicamente cortaba la alimentación del motor, pero debido a la inercia conseguía unos estupendos choques. Así pues para frenar pongo la marcha atrás el tiempo necesario para paralo.
Otro problema fue el servo utilizado para conseguir el giro del sensor. En las pruebas realizadas alimentando la placa mediante USB funcionaba perfectamente, pero cuando lo alimentaba mediante la batería fallaba. Para solucionarlo cambié el servo por otro más pequeño, con menos consumo de energía.
Componentes utilizados:
- El camión de radiocontrol comprado en una tienda de chinos por 9,90€ (yo lo compré en la tienda, no en la web que enlazo).
- Arduino UNO
- Una caja para la batería de 9v. .
- 1 sensor de distancia infrarrojo
- Una placa para prototipos
- Un servo para hacer girar el sensor. Usé este microservo porque cuando utilicé otro mayor no funcionaba adecuadamente que debido a la batería, porque cuando lo alimentaba con la salida usb iba perfectamente.
Diagrama (¡mi primer diagrama con Fritzing!):
Programa:
#include <Servo.h>
const int distanciaLimiteFrontal=180; // Valor mas alto cuanto más cerca
const int distanciaLimiteLateral=450;
const int pinAdelante = 9; // connected to the base of the transistor
const int pinAtras = 10;
const int pinDerecha = 11;
const int pinIzquierda = 12;
const int retardoServo = 1000;
const int tiempoGiro = 1100;
const int tiempoFreno = 600;
int sensorValue;
Servo myservo;
int grados;
//Permite saber hacia donde se giró la vez anterior
//para intentar girar de nuevo hacia ahí
int gradosGiroAnterior=0;
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
// preparo el led como salida
pinMode(13, OUTPUT);
// set the transistor pin as output:
pinMode(pinAdelante, OUTPUT);
pinMode(pinAtras, OUTPUT);
pinMode(pinDerecha, OUTPUT);
pinMode(pinIzquierda, OUTPUT);
myservo.attach(8); // attaches the servo on pin 8 to the servo object
myservo.write(90); // Lo inicializamos en el centro
delay(retardoServo);
}
void loop() {
//Siempre comenzamos iteracción con el servo al frente
centraServo();
sensorValue = analogRead(A2);
Serial.print("En loop sensorValue=");
Serial.println(sensorValue, DEC);
//Detectamos si hay algún obstáculo al frente
if (sensorValue < distanciaLimiteFrontal){
avanza();
}else{
paraConRetroceso(); //Paramos mientras se decide hacia donde girar
Serial.print("Se ha rebasado la distancia limite. La distancia para colision es ");
Serial.println(sensorValue, DEC);
grados=gradosDireccionASeguir();
if (grados == 0){
giroConRetroceso(pinIzquierda);
}else if (grados == 180){
giroConRetroceso(pinDerecha);
}else{
Serial.println("No se puede girar.");
}
}
}
void avanza(){
Serial.println("Avanza");
digitalWrite(pinAdelante, HIGH);
Serial.println("Damos potencia al motor");
}
void centraServo(){
if (myservo.read()!=90){
Serial.println("Se coloca a 90 grados");
myservo.write(90); //Colocamos el servo orientado al frente
delay(retardoServo); //Le damos tiempo a colocarse
}
}
void para(){
Serial.println("Para");
digitalWrite(pinAdelante, LOW);
digitalWrite(pinAtras, LOW);
}
// Para evitar que avance por la inercia
void paraConRetroceso(){
Serial.println("Para");
digitalWrite(pinAdelante, LOW);
digitalWrite(pinAtras, HIGH);
delay(tiempoFreno);
digitalWrite(pinAtras, LOW);
}
void giroConRetroceso(int pinSentido){
Serial.print("Giro con retroceso. pinSentido: ");
Serial.println(pinSentido, DEC);
digitalWrite(pinAdelante, LOW); //Paro la marcha adelante
digitalWrite(pinSentido, HIGH);
digitalWrite(pinAtras, HIGH);
delay(tiempoGiro);
digitalWrite(pinAtras, LOW);
digitalWrite(pinSentido, LOW);
}
int distanciaObstaculo(int grados){
myservo.write(grados);
delay(retardoServo);
int distancia = analogRead(A2);
Serial.print("Distancia a ");
Serial.print(grados, DEC);
Serial.print("grados es ");
Serial.println(distancia, DEC);
return distancia;
}
//Devuelve los grados 0 ó 180 cuya dirección está más despejada de obstáculos
int gradosDireccionASeguir(){
int distancia0Grados = distanciaObstaculo(0);
int distancia180Grados = distanciaObstaculo(180);
if (distancia0Grados > distanciaLimiteLateral && distancia180Grados > distanciaLimiteLateral){
Serial.println("Grados direccion a seguir=999");
return 999; //No se puede ir ni a derecha ni a izquierda
}
if (distancia0Grados < distanciaLimiteLateral && distancia180Grados > distanciaLimiteLateral){
Serial.println("Grados direccion a seguir=0");
gradosGiroAnterior=0;
return 0; //A cero grados está más despejado
}
if (distancia0Grados < distanciaLimiteLateral && distancia180Grados > distanciaLimiteLateral){
Serial.println("Grados direccion a seguir=0");
gradosGiroAnterior=0;
return 0; //A cero grados está más despejado
}
if (distancia0Grados > distanciaLimiteLateral && distancia180Grados < distanciaLimiteLateral){
Serial.println("Grados direccion a seguir=180");
gradosGiroAnterior=180;
return 180; //A 180 grados está más despejado
}
if (distancia0Grados < distanciaLimiteLateral && distancia180Grados < distanciaLimiteLateral){
//Podríamos a derecha o izquierda y lo decidimos en función del giro anterior
if (gradosGiroAnterior == 0){
Serial.println("Grados direccion a seguir=0");
gradosGiroAnterior=0;
return 0;
}else{
Serial.println("Grados direccion a seguir=180");
gradosGiroAnterior=180;
return 180; //A 180 grados está más despejado
}
}
}
No hay comentarios:
Publicar un comentario