ARDUINO: CONTROL MEDIANTE INFRARROJOS

Cambiamos en el mando los códigos, para que cuando pulsemos los diferentes números del mando infrarrojo, el arduino realice las diferentes funciones en base al código programado.

El código es el siguiente:

#include <IRremote.h>             // Librería versión 2.2.3 para el mando de infrarrojos
#include <Servo.h>                                        // Librería para el servomotor
Servo myservo;                                            // Declara variable para el servo
int minAngle = 700;
int maxAngle = 2400;
typedef unsigned char u8;
#define F 16736925	                                  // Marcha hacia adelante
#define B 16754775	                                  // Marcha atrás
#define L 16720605	                                  // Izquierda
#define R 16761405	                                  // Derecha
#define S 16712445	                                  // Parada
#define UNKNOWN_F 5316027		                  // Marcha hacia adelante relacionada con F
#define UNKNOWN_B 2747854299	                          // Marcha atrás relacionada con B
#define UNKNOWN_L 1386468383	                          // Izquierda relacionada con L
#define UNKNOWN_R 553536955		                  // Derecha relacionada con R
#define UNKNOWN_S 3622325019	                          // Parada relacionada con S
#define KEY1 16738455                                     // Código para tecla 1
#define KEY2 16750695                                     // Código para tecla 2
#define KEY3 16756815                                     // Código para tecla 3
#define KEY4 16724175                                     // Código para tecla 4

En esta primera parte del código importamos las librerías para el mando infrarrojo y el servomotor. Definimos las variables constantes de tipo numérico y las de cada tecla del mando con su código correspondiente.

#define KEY5 16718055                                         // Código para tecla 5
#define KEY6 16743045                                         // Código para tecla 6
#define KEY7 16716015                                         // Código para tecla 7
#define KEY8 16726215                                         // Código para tecla 8
#define KEY9 16734885                                         // Código para tecla 9
#define KEY0 16730805                                         // Código para tecla 0
#define KEY_STAR 16728765                                     // Código para tecla Asterisco
#define KEY_HASH 16732845                                     // Código para tecla Almohadilla
#define RECV_PIN  12                                      // Recibe información en el pin 12
/*define los pines activos de salida*/
#define ENA 5	                                                // Velocidad Rueda izquierda por ciclos
#define ENB 6	                                                // Velocidad Rueda derecha por ciclos
/*define los pines lógicos de salida*/
#define IN1 7	                                                // Rueda izquierda hacia delante
#define IN2 8	                                                // Rueda izquierda hacia atrás
#define IN3 9	                                                // Rueda derecha hacia atrás
#define IN4 11	                                                // Rueda derecha hacia delante
#define carSpeed 250	                                        // Velocidad inicial del coche de 0 a 255

Continuamos con los pines activos y lógicos de salida e indicamos la velocidad inicial del coche.

/*Instrucciones para el recibimiento de los pintes a través del infrarrojo*/
IRrecv irrecv(RECV_PIN);       // Pin que recibe el infrarrojo
decode_results results;        // Decodificación de los resultados obtenidos
unsigned long val;             // Variable larga no asignada para los posteriores resultados
unsigned long preMillis;       // Variable larga no asignada de medición de tiempo

Declaramos las instrucciones de recepción y decodificación de los resultados con un intervalo de tiempo, y el código realiza  la medición. 

void forward(){                                               // Función marcha delante
  digitalWrite(ENA,HIGH);                                     // Pin ENA activo
  digitalWrite(ENB,HIGH);                                     // Pin ENB activo
  digitalWrite(IN1,HIGH);                                     // Rueda izquierda hacia delante activa
  digitalWrite(IN2,LOW);                                      // Rueda izquierda hacia atrás inactiva
  digitalWrite(IN3,LOW);                                      // Rueda derecha hacia atrás inactiva
  digitalWrite(IN4,HIGH);                                     // Rueda derecha hacia delante activa
  Serial.println("go forward!");                              // Imprime por monitor serie
}
void back(){                                                  // Función marcha atrás
  digitalWrite(ENA,HIGH);                                     // Pin ENA activo
  digitalWrite(ENB,HIGH);                                     // Pin ENB activo
  digitalWrite(IN1,LOW);                                      // Rueda izquierda hacia delante activa
  digitalWrite(IN2,HIGH);                                     // Rueda izquierda hacia atrás activa
  digitalWrite(IN3,HIGH);                                     // Rueda derecha hacia atrás activa
  digitalWrite(IN4,LOW);                                      // Rueda derecha hacia atrás inactiva
  Serial.println("go back!");                                 // Imprime por pantalla
}
void left(){                                                  // Igual que arriba
  analogWrite(ENA,carSpeed);                                  // Variable carSpeed para dar velocidad al giro
  analogWrite(ENB,carSpeed);
  digitalWrite(IN1,LOW);

A partir de aquí, indicamos las funciones que el coche tiene que realizar como marcha hacia delante definimos los pines activos y le indicamos que rueda con high y low tiene que estar activa o inactiva.

  digitalWrite(IN2,HIGH);
  digitalWrite(IN3,LOW);
  digitalWrite(IN4,HIGH);
  Serial.println("go left!");
}
void right(){                                   //Igual que arriba pero derecha
  analogWrite(ENA,carSpeed);                    // Variable carSpeed para dar velocidad al giro
  analogWrite(ENB,carSpeed);
  digitalWrite(IN1,HIGH);
  digitalWrite(IN2,LOW);
  digitalWrite(IN3,HIGH);
  digitalWrite(IN4,LOW);
  Serial.println("go right!");
}
void stop(){                                   // Función para llamar a la parada del coche
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("STOP!");
}

También, introducimos la variable carSpeed para darle velocidad al giro del coche, y la variable Stop para llamar a la parada del coche.

void forward(u8 car_speed)                                    // Mismas funciones que las anterior pero con variables distintas para agregar una velocidad distinta a la definida
{
  analogWrite(ENA, car_speed);
  analogWrite(ENB, car_speed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void back(u8 velocidad)
{
  analogWrite(ENA, 100);
  analogWrite(ENB, 100);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void left(u8 velocidad)
{
 analogWrite(ENA, 250);
  analogWrite(ENB, 250);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void right(u8 velocidad)
{
  analogWrite(ENA, 250);
  analogWrite(ENB, 250);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

Usamos las mismas funciones anteriores pero con distintas variables para agregar una velocidad distinta, en este caso más lenta, a la definida del coche.

void setup() {                                                 // Primera función que hace la placa al inciar
  Serial.begin(9600);                                          // Velocidad de transmisión de 9600 baudios para conectar con el bluetooth e infrarrojos
  pinMode(IN1,OUTPUT);                                         // Declara los pines output de salida y los input de entrada
  pinMode(IN2,OUTPUT);                                         // Los ouput están en la tarjeta de expansión y los input en la propia placa
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
  pinMode(10,INPUT);
  pinMode(4,INPUT);
  pinMode(2,INPUT);
  stop();                                                     // Llamada para parar el proceso
  irrecv.enableIRIn();                                        // Activa el recibimiento de infrarrojos
  myservo.attach(3,700,2400);                                 // Pin 3 se ocupa de mover el servo entre los dos valores de ancho de pulso
  myservo.write(90);                                          // Define al servo en 90º
}
void loop() {                                                 // Función de repetición
  if(irrecv.decode(&results)){                                // Función de decodificación de resultados
    preMillis = millis();                                     // Variable de tiempo
    val = results.value;                                      // Almacena los datos en variable val

Indicamos la velocidad de transmisión de 9600 baudios para conectar el infrarrojos, declaramos los pines output de salida en la tarjeta de expansión y los input de entrada en la propia placa.El pin 3 se ocupará de mover el servo entre los valores de ancho de pulso y definir el servo en 90 grados.

Serial.println(val);                                 // Imprime los resultados en pantalla
    irrecv.resume();                                 // Resumen los códigos
    switch(val){                                     // Función en relación a la variable val
      case KEY_STAR:               // En caso de tecla asterisco mueve el servo en 3 ángulos
      myservo.write(10);
      delay (500);
      myservo.write(90);
      delay (500);
      myservo.write(180);
      delay (500);
      myservo.write(90);
      delay (500);break;                     // Rompe la función con un break tras un delay
      case F:                                // En caso de F avanza
      case UNKNOWN_F: forward();
      delay (1000);break;                    // Rompe la función
      case B:                                // En caso de B avanza hacia atrás
      case UNKNOWN_B: back();
      delay (1000);break;                    // Rompe la función tras realizar el movimiento
      case L:                                // En caso de L gira a la izquierda
      case UNKNOWN_L: left();
      delay (1000);break;                    // Rompre la función

Con Serial.println imprimimos los resultados por pantalla. La tecla del mando infrarrojo * (asterisco) mueve el servo en tres ángulos, el valor de case aplica valores como el de avanzar, retroceder, girar hacia la derecha, hacia la izquierda.

     case R:                                                 // En caso de R gira a la derecha
      case UNKNOWN_R: right();
      delay (1000);break;                                     // Rompre la función
      case S:                                                 // En caso de S para el moviento
      case UNKNOWN_S: stop();
      delay (1000);break;                                     // Tras la parada rompe la función
      case KEY_HASH:                                          // En caso de tecla almohadilla
      forward();                                              //Hace forma de L
      delay(2000);
      left();
      delay(450);
      forward();                                               //Fin forma de L
      delay(2000);
      stop();                                                  //Llama a la parada
      delay(1000);break;                                       //Rompe la función
      case KEY3:                                              //En caso de tecla 3 hace forma de K
      left();
      delay(450);
      forward();
      delay(2000);
      back();
      delay(1000);

En esta parte le indicamos que haga forma de L y de K. 

El Delay es una función que hace que el procesador espere, esta función tiene un parámetro de entrada del tipo entero, que es la espera en milisegundos.

     case R:                                                 // En caso de R gira a la derecha
      case UNKNOWN_R: right();
      delay (1000);break;                                    // Rompre la función
      case S:                                                // En caso de S para el moviento
      case UNKNOWN_S: stop();
      delay (1000);break;                                     // Tras la parada rompe la función
      case KEY_HASH:                                          // En caso de tecla almohadilla
      forward();                                              //Hace forma de L
      delay(2000);
      left();
      delay(450);
      forward();                                              //Fin forma de L
      delay(2000);
      stop();                                                 //Llama a la parada
      delay(1000);break;                                      //Rompe la función
      case KEY3:                                              //En caso de tecla 3 hace forma de K
      left();
      delay(450);
      forward();
      delay(2000);
      back();
      delay(1000);

Con esta última parte, llamamos a la parada de fin de las letras con break. En caso de la tecla 4 con el loop giramos el coche a la derecha y con la tecla 5 hacia la izquierda.

else{                                        //Si no mide el tiempo en espera de llamada
    if(millis() - preMillis > 500){
      stop();
      preMillis = millis();
    }
  }
} 

Video de demostración: Infrarrojos 1 e infrarrojos 2

https://youtu.be/q2emfXDKaf0

https://youtu.be/Vvv5MAIwTZc

Este proyecto ha sido realizado basándose en el código por defecto de Smart Robot Car Kit 3.0 Plus.

Proyecto Arduino

Realizado por: Kevin Maldonado Pico y Laura Tovar Pérez