Introducción
Material necesario
En este caso los componentes son la suma de los componentes usados para el Robot Esquivaobstáculos así como los usados para el Robot dirigido mediante mando a distancia por lo que se recomienda leer los citados artículos para obtener el total de elementos.
Circuito eléctrico (diagrama de conexiones)
En este caso, añadiremos la circuitería necesaria para integrar estos elementos con el circuito de nuestro robot. Para no complicar demasiado el diagrama por excesivo número de conexiones, mostraremos por separado el circuito que gobierna el funcionamiento de nuestro robot y el circuito con los elementos no relevantes como son los LED y el zumbador.
Circuito Inicial
Código programa Arduino
Para poder detectar señales lo mejor es usar una librería (código generado que permite usar determinaciones funciones que no pertenecen al IDE de Arduino). No entraremos en profundidad en el uso de dichas librerías (vitales para cualquier programador en cualquier idioma) (leer artículo de Prometec sobre librerías) pero en este caso usaremos la librería Arduino-IRremote desarrollada por Rafi Khan (z3t0) disponible en este enlace.
Distinguiremos 2 codificaciones diferentes:
- En el primero de los casos no controlaremos la velocidad de los motores (mantendremos sin conectar los jumpers para ENA y ENB del driver L298D)
Arduino Code
/* Nombre: Robot Multifunción Autor: Daniel Pascual Gallegos Fecha: Enero 2017 Funcionalidad: Este proyecto reune las propiedades de varios proyectos Leerá la información de un mando a distancia: - Si el usuario pulsa el botón 1 el robot realizará las funciones del robotesquivaobstáculos - Si el usuario pulsa el botón 2 el robot se convertirá en el robot dirigido mando a distancia */ // Inclusión de librería para trabajar con el sensor IR #include "IRremote.h" // Definición de variables y constantes relacionadas con el motor izquierdo const int IN1 = 13; // Pin digital 13 para controlar sentido giro motor izquierdo const int IN2 = 12; // Pin digital 12 para controlar sentido giro motor izquierdo // Definición de variables y constantes relacionadas con el motor derecho const int IN3 = 11; // Pin digital 11 para controlar sentido giro motor izquierdo const int IN4 = 10; // Pin digital 10 para controlar sentido giro motor izquierdo // Definición de variables y constantes relacionadas con los LEDs const int ledVerde1 = 4; // Pin digital 4 para conectar el LED verde 1 const int ledVerde2 = 5; // Pin digital 5 para conectar el LED verde 2 const int ledRojo1 = 6; // Pin digital 6 para conectar el LED rojo 1 const int ledRojo2 = 7; // Pin digital 7 para conectar el LED rojo 2 // Definición de variables y constantes relacionadas con el zumbador const int zumbadorPiezo = 8; // Pin digital 8 para conectar el zumbador /// Definición de variables y constantes relacionadas con el sensor infrarrojos const int sensorInfrarrojos = 9; // Pin digital 9 para conectar el sensor IRrecv irrecv(sensorInfrarrojos); // Se crea un nuevo objeto para trabajar con el sensor decode_results results; // Definición de códigos asociados al mando Keyes más sencillo const unsigned long BOTON_ARRIBA = 0xFF629D; const unsigned long BOTON_ABAJO = 0xFFA857; const unsigned long BOTON_IZQ = 0xFF22DD; const unsigned long BOTON_DER = 0xFFC23D; const unsigned long BOTON_OK = 0xFF02FD; const unsigned long BOTON_1 = 0xFF6897; const unsigned long BOTON_2 = 0xFF9867; const unsigned long BOTON_3 = 0xFFB04F; // Definición de variables y constantes relacionadas con la detección de obstáculos const int triggerEmisor = 3; const int echoReceptor = 2; const int valorUmbral = 10; long tiempoEntrada; // Tiempo de respuesta del sensor de entrada float distanciaEntrada; // Distancia en cm a la que se encuentra el objeto del sensor // Variables y constantes que almacenan la función del ROBOT // Será 1 cuando esté en modo esquivaobstáculos // Será 2 cuando esté controlado por el mando a distancia int funcionRobot = 0; // Al inicio el robot no tiene funcionalidad // Función que se ejecuta una sola vez al cargar el programa void setup() { // Se declaran todos los pines como salidas // Pines asociados a los motores pinMode (IN1, OUTPUT); pinMode (IN2, OUTPUT); pinMode (IN3, OUTPUT); pinMode (IN4, OUTPUT); // Pines asociados a los LEDS pinMode (ledVerde1, OUTPUT); pinMode (ledVerde2, OUTPUT); pinMode (ledRojo1, OUTPUT); pinMode (ledRojo2, OUTPUT); // Pines asociados al zumbador pinMode (zumbadorPiezo, OUTPUT); // Pines asociados al sensor ultrasonico HCSR04 pinMode(triggerEmisor,OUTPUT); // El emisor emite por lo que es configurado como salida pinMode(echoReceptor,INPUT); // El receptor recibe por lo que es configurado como entrada // Se inicia el receptor IR irrecv.enableIRIn(); // Se inicia el puerto de comunicaciones en serie Serial.begin(9600); // } // Función que se repite de manera periódica void loop() { robotFuncion(); // Analiza si el robot funciona como esquivaobstáculos o con el mando if(funcionRobot==1) { robotEsquivaObstaculos(); // Se crea la funcionalidad robotesquivaosbtaculos } else if(funcionRobot==2) { robotMandoDistancia(); // Se lee la señal del sensor IR } } void robotEsquivaObstaculos() { Serial.println("Entra esquiva "); // Se inicializa el sensor de infrasonidos digitalWrite(triggerEmisor,LOW); // Para estabilizar delayMicroseconds(10); // Comenzamos las mediciones // Se envía una señal activando la salida trigger durante 10 microsegundos digitalWrite(triggerEmisor, HIGH); // envío del pulso ultrasónico delayMicroseconds(10); tiempoEntrada=pulseIn(echoReceptor, HIGH); distanciaEntrada= int(0.017*tiempoEntrada); // Calcula la distancia en cm Serial.println("El valor de la distancia es "); Serial.println(distanciaEntrada); delay(200); // Si el valor de la distancia es menor que el valor umbral if(distanciaEntrada<valorUmbral) { robotAvance(); // El robot avanza mientras no encuentre obstáculos enciendeLEDVerde(); // Enciende los LED verdes delanteros } else { enciendeLEDRojoZumbador(); // Enciende los LED rojos traseros y el zumbador // Retrocede 1 segundo y gira a la derecha 0,5 segundos para esquivarlo robotRetroceso(); delay(1000); robotDerecha (); delay(500); } } /* Función robotAvance: esta función hará que ambos motores se activen a máxima potencia por lo que el robot avanzará hacia delante */ void robotAvance() { // Motor izquierdo // Al mantener un pin HIGH y el otro LOW el motor gira en un sentido digitalWrite (IN1, HIGH); digitalWrite (IN2, LOW); // Motor derecho // Al mantener un pin HIGH y el otro LOW el motor gira en un sentido digitalWrite (IN3, HIGH); digitalWrite (IN4, LOW); } /* Función robotRetroceso: esta función hará que ambos motores se activen a máxima potencia en sentido contrario al anterior por lo que el robot avanzará hacia atrás */ void robotRetroceso() { // Motor izquierdo // Al mantener un pin LOW y el otro HIGH el motor gira en sentido contrario al anterior digitalWrite (IN1, LOW); digitalWrite (IN2, HIGH); // Motor derecho // Al mantener un pin LOW y el otro HIGH el motor gira en sentido contrario al anterior digitalWrite (IN3, LOW); digitalWrite (IN4, HIGH); } /* Función robotDerecha: esta función acccionará el motor izquierdo y parará el derecho por lo que el coche girará hacia la derecha (sentido horario) */ void robotDerecha() { // Motor izquierdo // Se activa el motor izquierdo digitalWrite (IN1, HIGH); digitalWrite (IN2, LOW); // Motor derecho // Se para el motor derecho digitalWrite (IN3, LOW); digitalWrite (IN4, LOW); } /* Función robotIzquierda: esta función acccionará el motor derecho y parará el izquierdo por lo que el coche girará hacia la izquierda (sentido antihorario) */ void robotIzquierda () { // Motor izquierdo // Se para el motor izquierdo digitalWrite (IN1, LOW); digitalWrite (IN2, LOW); // Motor derecho // Se activa el motor derecho digitalWrite (IN3, HIGH); digitalWrite (IN4, LOW); } /* Función robotParar: esta función parará ambos motores por lo que el robot se parará. */ void robotParar() { // Motor izquierdo // Se para el motor izquierdo digitalWrite (IN1, LOW); digitalWrite (IN2, LOW); // Motor derecho // Se para el motor derecho digitalWrite (IN3, LOW); digitalWrite (IN4, LOW); } /* Función enciendeLEDVerde: esta función hará que ambos LED verdes se enciendan y se apaguen los LED rojos (en caso de que estuvieran encendidos) y el zumbador (en caso de que estuviera sonando) */ void enciendeLEDVerde() { // Manda 5 V a los pines por lo que enciende los 2 LED verdes digitalWrite (ledVerde1, HIGH); digitalWrite (ledVerde2, HIGH); // Quita 5V de los otros pines por lo que apaga los 2 LED rojos y el zumbador digitalWrite (ledRojo1, LOW); digitalWrite (ledRojo2, LOW); digitalWrite (zumbadorPiezo, HIGH); } /* Función enciendeLEDRojoZumbador: esta función hará que ambos LED rojos se enciendan y que empiece a sonar el zumbador. Además de que se apaguen los LED verdes */ void enciendeLEDRojoZumbador() { // Manda 5 V a los pines por lo que enciende los 2 LED rojos y el zumbador digitalWrite (ledRojo1, HIGH); digitalWrite (ledRojo2, HIGH); digitalWrite (zumbadorPiezo, HIGH); // Quita 5V de los otros pines por lo que apaga los 2 LED verdes digitalWrite (ledVerde1, LOW); digitalWrite (ledVerde2, LOW); } /* Función robotFuncion: esta función recibirá los valores del mando a distancia - Si el usuario pulsa el botón 1 el robot realizará las funciones del robotesquivaobstáculos - Si el ususario pulsa el botón 2 el robot se convertirá en el robot dirigido mando a distancia */ void robotFuncion() { if (irrecv.decode(&results)) { Serial.println (results.value, HEX); //display HEX Serial.println (results.value); delay(1000); // Comprueba inicialmente la función del robot // Si pulsa el botón 1 if(results.value==BOTON_1) { funcionRobot = 1; } else if(results.value==BOTON_2) { funcionRobot = 2; } irrecv.resume(); // Busca el siguiente valor del mando } } void robotMandoDistancia() { Serial.println("Entra mando "); if (irrecv.decode(&results)) { Serial.println (results.value, HEX); //display HEX Serial.println (results.value); switch (results.value) { case BOTON_1: Serial.println("Botón 1"); funcionRobot = 1; break; case BOTON_ARRIBA: Serial.println("Boton arriba"); robotAvance(); enciendeLEDVerde(); break; case BOTON_ABAJO: Serial.println("Boton abajo"); robotRetroceso(); enciendeLEDRojoZumbador(); break; case BOTON_IZQ: Serial.println("Boton izquierda"); robotIzquierda(); break; case BOTON_DER: Serial.println("Boton derecha"); robotDerecha(); break; case BOTON_OK: Serial.println("Boton OK"); robotParar(); break; } irrecv.resume(); } }
- En el segundo conectaremos la salida ENA al pin digital 6 y la salida ENB al pin digital 5 (para poder controlar la velocidad de giro del motor para proyectos siguientes).
Arduino Code
/* Nombre: Robot Multifunción Autor: Daniel Pascual Gallegos Fecha: Enero 2017 Funcionalidad: Este proyecto reune las propiedades de varios proyectos Leerá la información de un mando a distancia: - Si el usuario pulsa el botón 1 el robot realizará las funciones del robotesquivaobstáculos - Si el usuario pulsa el botón 2 el robot se convertirá en el robot dirigido mando a distancia */ // Inclusión de librería para trabajar con el sensor IR #include "IRremote.h" // Definición de variables y constantes relacionadas con el motor izquierdo const int IN1 = 13; // Pin digital 13 para controlar sentido giro motor izquierdo const int IN2 = 12; // Pin digital 12 para controlar sentido giro motor izquierdo const int ENA = 6; // Definición de variables y constantes relacionadas con el motor derecho const int IN3 = 11; // Pin digital 11 para controlar sentido giro motor izquierdo const int IN4 = 10; // Pin digital 10 para controlar sentido giro motor izquierdo const int ENB = 5; // Definición de variables y constantes relacionadas con los LEDs const int ledVerde1 = 4; // Pin digital 4 para conectar el LED verde 1 const int ledRojo2 = 7; // Pin digital 7 para conectar el LED rojo 2 // Definición de variables y constantes relacionadas con el zumbador const int zumbadorPiezo = 8; // Pin digital 8 para conectar el zumbador /// Definición de variables y constantes relacionadas con el sensor infrarrojos const int sensorInfrarrojos = 9; // Pin digital 9 para conectar el sensor IRrecv irrecv(sensorInfrarrojos); // Se crea un nuevo objeto para trabajar con el sensor decode_results results; // Definición de códigos asociados al mando Keyes más sencillo const unsigned long BOTON_ARRIBA = 0xFF629D; const unsigned long BOTON_ABAJO = 0xFFA857; const unsigned long BOTON_IZQ = 0xFF22DD; const unsigned long BOTON_DER = 0xFFC23D; const unsigned long BOTON_OK = 0xFF02FD; const unsigned long BOTON_1 = 0xFF6897; const unsigned long BOTON_2 = 0xFF9867; const unsigned long BOTON_3 = 0xFFB04F; // Definición de variables y constantes relacionadas con la detección de obstáculos const int triggerEmisor = 3; const int echoReceptor = 2; const int valorUmbral = 20; long tiempoEntrada; // Tiempo de respuesta del sensor de entrada float distanciaEntrada; // Distancia en cm a la que se encuentra el objeto del sensor // Variables y constantes que almacenan la función del ROBOT // Será 1 cuando esté en modo esquivaobstáculos // Será 2 cuando esté controlado por el mando a distancia int funcionRobot = 0; // Al inicio el robot no tiene funcionalidad // Función que se ejecuta una sola vez al cargar el programa void setup() { // Se declaran todos los pines como salidas // Pines asociados a los motores pinMode (IN1, OUTPUT); pinMode (IN2, OUTPUT); pinMode (IN3, OUTPUT); pinMode (IN4, OUTPUT); pinMode (ENA, OUTPUT); pinMode (ENB, OUTPUT); // Pines asociados a los LEDS pinMode (ledVerde1, OUTPUT); pinMode (ledRojo2, OUTPUT); // Pines asociados al zumbador pinMode (zumbadorPiezo, OUTPUT); // Pines asociados al sensor ultrasonico HCSR04 pinMode(triggerEmisor,OUTPUT); // El emisor emite por lo que es configurado como salida pinMode(echoReceptor,INPUT); // El receptor recibe por lo que es configurado como entrada // Se inicia el receptor IR irrecv.enableIRIn(); // Se inicia el puerto de comunicaciones en serie Serial.begin(9600); // } // Función que se repite de manera periódica void loop() { robotFuncion(); // Analiza si el robot funciona como esquivaobstáculos o con el mando if(funcionRobot==1) { robotEsquivaObstaculos(); // Se crea la funcionalidad robotesquivaosbtaculos } else if(funcionRobot==2) { robotMandoDistancia(); // Se lee la señal del sensor IR } } void robotEsquivaObstaculos() { Serial.println("Entra esquiva "); // Se inicializa el sensor de infrasonidos digitalWrite(triggerEmisor,LOW); // Para estabilizar delayMicroseconds(10); // Comenzamos las mediciones // Se envía una señal activando la salida trigger durante 10 microsegundos digitalWrite(triggerEmisor, HIGH); // envío del pulso ultrasónico delayMicroseconds(10); tiempoEntrada=pulseIn(echoReceptor, HIGH); distanciaEntrada= int(0.017*tiempoEntrada); // Calcula la distancia en cm Serial.println("El valor de la distancia es "); Serial.println(distanciaEntrada); delay(200); // Si el valor de la distancia es menor que el valor umbral if(distanciaEntrada>valorUmbral) { robotAvance(); // El robot avanza mientras no encuentre obstáculos enciendeLEDVerde(); // Enciende los LED verdes delanteros } else { enciendeLEDRojoZumbador(); // Enciende los LED rojos traseros y el zumbador // Retrocede 1 segundo y gira a la derecha 0,5 segundos para esquivarlo robotRetroceso(); delay(1000); robotDerecha (); delay(500); } } /* Función robotAvance: esta función hará que ambos motores se activen a máxima potencia por lo que el robot avanzará hacia delante */ void robotAvance() { // Motor izquierdo // Al mantener un pin HIGH y el otro LOW el motor gira en un sentido digitalWrite (IN1, HIGH); digitalWrite (IN2, LOW); analogWrite (ENA, 255); //Velocidad motor A // Motor derecho // Al mantener un pin HIGH y el otro LOW el motor gira en un sentido digitalWrite (IN3, HIGH); digitalWrite (IN4, LOW); analogWrite (ENB, 255); //Velocidad motor B } /* Función robotRetroceso: esta función hará que ambos motores se activen a máxima potencia en sentido contrario al anterior por lo que el robot avanzará hacia atrás */ void robotRetroceso() { // Motor izquierdo // Al mantener un pin LOW y el otro HIGH el motor gira en sentido contrario al anterior digitalWrite (IN1, LOW); digitalWrite (IN2, HIGH); analogWrite (ENA, 255); //Velocidad motor A // Motor derecho // Al mantener un pin LOW y el otro HIGH el motor gira en sentido contrario al anterior digitalWrite (IN3, LOW); digitalWrite (IN4, HIGH); analogWrite (ENB, 255); //Velocidad motor B } /* Función robotDerecha: esta función acccionará el motor izquierdo y parará el derecho por lo que el coche girará hacia la derecha (sentido horario) */ void robotDerecha() { // Motor izquierdo // Se activa el motor izquierdo digitalWrite (IN1, HIGH); digitalWrite (IN2, LOW); analogWrite (ENA, 255); //Velocidad motor A // Motor derecho // Se para el motor derecho digitalWrite (IN3, LOW); digitalWrite (IN4, LOW); analogWrite (ENB, 0); //Velocidad motor A } /* Función robotIzquierda: esta función acccionará el motor derecho y parará el izquierdo por lo que el coche girará hacia la izquierda (sentido antihorario) */ void robotIzquierda () { // Motor izquierdo // Se para el motor izquierdo digitalWrite (IN1, LOW); digitalWrite (IN2, LOW); analogWrite (ENA, 0); //Velocidad motor A // Motor derecho // Se activa el motor derecho digitalWrite (IN3, HIGH); digitalWrite (IN4, LOW); analogWrite (ENB, 255); //Velocidad motor A } /* Función robotParar: esta función parará ambos motores por lo que el robot se parará. */ void robotParar() { // Motor izquierdo // Se para el motor izquierdo digitalWrite (IN1, LOW); digitalWrite (IN2, LOW); analogWrite (ENA, 0); //Velocidad motor A // Motor derecho // Se para el motor derecho digitalWrite (IN3, LOW); digitalWrite (IN4, LOW); analogWrite (ENB, 0); //Velocidad motor A } /* Función enciendeLEDVerde: esta función hará que ambos LED verdes se enciendan y se apaguen los LED rojos (en caso de que estuvieran encendidos) y el zumbador (en caso de que estuviera sonando) */ void enciendeLEDVerde() { // Manda 5 V a los pines por lo que enciende los 2 LED verdes digitalWrite (ledVerde1, HIGH); // Quita 5V de los otros pines por lo que apaga los 2 LED rojos y el zumbador digitalWrite (ledRojo2, LOW); digitalWrite (zumbadorPiezo, HIGH); } /* Función enciendeLEDRojoZumbador: esta función hará que ambos LED rojos se enciendan y que empiece a sonar el zumbador. Además de que se apaguen los LED verdes */ void enciendeLEDRojoZumbador() { // Manda 5 V a los pines por lo que enciende los 2 LED rojos y el zumbador digitalWrite (ledRojo2, HIGH); digitalWrite (zumbadorPiezo, HIGH); // Quita 5V de los otros pines por lo que apaga los 2 LED verdes digitalWrite (ledVerde1, LOW); } /* Función robotFuncion: esta función recibirá los valores del mando a distancia - Si el usuario pulsa el botón 1 el robot realizará las funciones del robotesquivaobstáculos - Si el ususario pulsa el botón 2 el robot se convertirá en el robot dirigido mando a distancia */ void robotFuncion() { if (irrecv.decode(&results)) { Serial.println (results.value, HEX); //display HEX Serial.println (results.value); delay(1000); // Comprueba inicialmente la función del robot // Si pulsa el botón 1 if(results.value==BOTON_1) { funcionRobot = 1; } else if(results.value==BOTON_2) { funcionRobot = 2; } irrecv.resume(); // Busca el siguiente valor del mando } } void robotMandoDistancia() { Serial.println("Entra mando "); if (irrecv.decode(&results)) { Serial.println (results.value, HEX); //display HEX Serial.println (results.value); switch (results.value) { case BOTON_1: Serial.println("Botón 1"); funcionRobot = 1; break; case BOTON_ARRIBA: Serial.println("Boton arriba"); robotAvance(); enciendeLEDVerde(); break; case BOTON_ABAJO: Serial.println("Boton abajo"); robotRetroceso(); enciendeLEDRojoZumbador(); break; case BOTON_IZQ: Serial.println("Boton izquierda"); robotIzquierda(); break; case BOTON_DER: Serial.println("Boton derecha"); robotDerecha(); break; case BOTON_OK: Serial.println("Boton OK"); robotParar(); break; } irrecv.resume(); } }
Circuito mBlock