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)
/*
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).
/*
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