Proyecto 15 - Coche Radiocontrol

5 de abril de 2015

En este proyecto vamos a hacer un coche de radio control.

Partiendo de un coche de radio control averiado, le cambiaremos la electrónica por un CI L293D, básicamente un driver para motores y con un mando por infrarrojos haremos el control remoto.

Proyecto 15a - Motor Test

En primer lugar vamos a probar los motores del coche. Montamos el circuito del esquema y con un código sencillo comprobamos que los motores funcionan y se mueven como queremos.

Creamos funciones para cada uno de los movimientos, que luego invocaremos según corresponda.

Esquema

Sketch

//M1 motor de giro

//M2 motor traccion

int enableM1 = 11;

int in1Pin = 10;

int in2Pin = 9;

int enableM2 = 6;

int in4Pin = 5;

int in3Pin = 4;

int speed = 255;

void setup()

{

pinMode(in1Pin, OUTPUT);

pinMode(in2Pin, OUTPUT);

pinMode(enableM1, OUTPUT);

pinMode(in3Pin, OUTPUT);

pinMode(in4Pin, OUTPUT);

pinMode(enableM2, OUTPUT);

}

void loop()

{

boolean FW = 0;

boolean BW = 1;

goForward(speed, FW);      // Go Forward straight

turnRight(speed, BW);      // Go Forward and turn Right

turnRightBK(speed, BW);    // Go Backward and turn Right

goBackward(speed, BW);     // Go Backward straight

goForward(speed, FW);      // Go Forward straight

turnLeft(speed, FW);       // Go Forward and turn Left

turnLeftBK(speed, FW);     // GO Backward and turn Left

delay(3000);

}

//Turn Left and go Forward

void turnLeft(int speed, boolean FW)

{

//Motor1

boolean reverse1 = FW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2

boolean reverse2 = FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Right and go Forward

void turnRight(int speed, boolean BW)

{

//Motor1

boolean reverse1 = BW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2

boolean reverse2 = !BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Funcion Go Forward

void goForward(int speed, boolean FW)

{

//Motor1 inhabilitado, para que vaya recto

analogWrite(enableM1, 0);

//Motor2

boolean reverse2 = FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM2, 0);

}

//Funcion Go Backward

void goBackward(int speed, boolean BW)

{

//Motor1 inhabilitado, para que vaya recto

analogWrite(enableM1, 0);

//Motor2

boolean reverse2 = BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Left and go Backward

void turnLeftBK(int speed, boolean FW)

{

//Motor1 Giro

boolean reverse1 = FW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2 Traccion

boolean reverse2 = !FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Right and go Backward

void turnRightBK(int speed, boolean BW)

{

//Motor1 giro

boolean reverse1 = BW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2 traccion

boolean reverse2 = BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(1500);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

Proyecto 15b - Mando a Distancia por Infrarrojos

A continuación vamos a hacer el control remoto por infrarrojos.

Este tutorial lo he sacado de la web tronixstuff. Mira el original aquí.

Para ello necesitamos un mando por infrarrojos y un receptor. El mando puede ser uno que tengamos por casa y como receptor utilizamos el TSOP31238, funciona a 38KHz y se puede adquirir por menos de 1€.

En mi caso he utilizado el mando de un antiguo reproductor de CD Philips. También vale un mando universal.

Lo primero es verificar que el receptor funciona correctamente, para ello mediante un sencillo sketch veremos en el monitor serial los distintos códigos hexadecimales asociados a cada botón.

Aquí podemos descargar la librería necesaria para que funcione el receptor:

Esquema

Sketch

// example 32.1 - IR receiver code repeater

// http://tronixstuff.com/tutorials > chapter 32

// based on code by Ken Shirriff - http://arcfn.com

#include <IRremote.h> // use the library

int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11

IRrecv irrecv(receiver); // create instance of 'irrecv'

decode_results results;

void setup()

{

  Serial.begin(9600); // for serial monitor output

  irrecv.enableIRIn(); // Start the receiver

}

void loop()

{

  if (irrecv.decode(&results)) // have we received an IR signal?

  {

    Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal

    irrecv.resume(); // receive the next value

  }  // Your loop can do other things while waiting for an IR command

}


Una vez cargado el sketch, abrir el monitor serial y comenzar a pulsar botones, a cada pulsación le corresponde un código en hexadecimal.

 

 

Indicar que cada mando es diferente, el aquí usado tiene la particularidad de que el mismo botón tiene dos códigos que se repiten secuencialmente.

Apuntad en un papel el código correspondiente a cada botón, lo necesitaremos para programar las funciones.

Dependiendo del mando utilizado habrá que modificar el sketch para adaptarlo a nuestras necesidades, como veremos más adelante.


Proyecto 15c - Creando un Control Remoto por Infrarrojos 

En este proyecto haremos un mando a distancia con el que controlaremos los pines digitales del Arduino.

Mediante una estructura switch-case asociamos cada código a una acción, en este caso encender un led.

Este ejemplo servirá de base para controlar un coche teledirigido.

 

Esquema

Sketch

int receiverpin = 11;

#include <IRremote.h>

IRrecv irrecv(receiverpin);

decode_results results;

void setup()

{

  

  pinMode(2, OUTPUT);

  pinMode(4, OUTPUT);

  pinMode(6, OUTPUT);

  irrecv.enableIRIn();

}

void ledUno() // enciende el led 1 tres segundos

{

  digitalWrite(2, HIGH);

  delay(3000);

  digitalWrite(2, LOW);

}

void ledDos() // enciende el led 2 tres segundos

{

  digitalWrite(4, HIGH);

  delay(3000);

  digitalWrite(4, LOW);

}

void ledTres() // enciende el led 3 tres segundos

{

  digitalWrite(6, HIGH);

  delay(3000);

  digitalWrite(6, LOW);

}

void translateIR()

{

  switch(results.value)

  {

    case 0xD02: ledUno(); break; 

    case 0xD05: ledDos(); break; 

    case 0xD06: ledTres(); break;

  }

}

 

void loop()

{

if (irrecv.decode(&results))

  {

  translateIR();

  irrecv.resume();

  }

}


Proyecto 15d - RC Car 

Vamos a agrupar lo aprendido hasta aquí, para hacer nuestro propio coche de radiocontrol.

Esquema

En el circuito definitivo he empleado el L293D y un arduino Nano, versión en miniatura y más barata que el arduino UNO.

Debido a su reducido tamaño y coste, arduino Nano es ideal para trabajar de forma permanente in situ en proyectos ya testeados.

En la foto podéis ver el resultado final del coche.

Sketch

//RC car with IR Remote Control

//M1 motor de giro

//M2 motor traccion

int receiverpin = 11; 

#include <IRremote.h>

IRrecv irrecv(receiverpin); // create instance of 'irrecv'

decode_results results;

int enableM1 = 5;

int in1Pin = 10;

int in2Pin = 9;

int enableM2 = 6;

int in4Pin = 13;

int in3Pin = 4;

int speed = 255;

int duration = 500;

void setup()

{

pinMode(in1Pin, OUTPUT);

pinMode(in2Pin, OUTPUT);

pinMode(enableM1, OUTPUT);

pinMode(in3Pin, OUTPUT);

pinMode(in4Pin, OUTPUT);

pinMode(enableM2, OUTPUT);

irrecv.enableIRIn(); 

}

//Turn Left and go Forward

void turnLeft(int speed)

{

//Motor1

boolean FW = 0;

boolean reverse1 = FW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2

boolean reverse2 = FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Right and go Forward

void turnRight(int speed)

{

//Motor1

boolean BW = 1;

boolean reverse1 = BW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2

boolean reverse2 = !BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Funcion Go Forward

void goForward(int speed)

{

//Motor1 inhabilitado, para que vaya recto

boolean FW = 0;

analogWrite(enableM1, 0);

//Motor2

boolean reverse2 = FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM2, 0);

}

//Funcion Go Backward

void goBackward(int speed)

{

//Motor1 inhabilitado, para que vaya recto

boolean BW = 1;

analogWrite(enableM1, 0);

//Motor2

boolean reverse2 = BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Left and go Backward

void turnLeftBK(int speed)

{

//Motor1 Giro

boolean FW = 0;

boolean reverse1 = FW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2 Traccion

boolean reverse2 = !FW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

//Turn Right and go Backward

void turnRightBK(int speed)

{

//Motor1 giro

boolean BW = 1;

boolean reverse1 = BW;

analogWrite(enableM1, speed);

digitalWrite(in1Pin, !reverse1);

digitalWrite(in2Pin, reverse1);

//Motor2 traccion

boolean reverse2 = BW;

analogWrite(enableM2, speed);

digitalWrite(in3Pin, !reverse2);

digitalWrite(in4Pin, reverse2);

delay(duration);

analogWrite(enableM1, 0);

analogWrite(enableM2, 0);

}

void translateIR()

{

  switch(results.value)

  {

    speed = 255;

    case 0xD02: goForward(speed); break;  // Go Forward straight

    case 0x502: goForward(speed); break;  // Go Forward straight

    case 0xD08: goBackward(speed); break; // Go Backward straight

    case 0x508: goBackward(speed); break; // Go Backward straight

    case 0xD06: turnRight(speed); break;  // Go Forward and turn Right

    case 0x506: turnRight(speed); break;  // Go Forward and turn Right

    case 0xD04: turnLeft(speed); break;   // Go Forward and turn Left

    case 0x504: turnLeft(speed); break;   // Go Forward and turn Left

    case 0xD07: turnLeftBK(speed); break; // GO Backward and turn Left

    case 0x507: turnLeftBK(speed); break; // GO Backward and turn Left

    case 0xD09: turnRightBK(speed); break; // Go Backward and turn Right

    case 0x509: turnRightBK(speed); break; // Go Backward and turn Right

  }

}

void loop()

{

  

  if (irrecv.decode(&results)) 

  {

    translateIR();

    irrecv.resume(); // receive the next value

    

  }

}


Aquí debajo hay una versión modificada del código anterior.

Se trata de un modo de funcionamiento continuo para las funciones de avanzar, retroceder y girar, de esa forma el manejo del coche resulta más cómodo al no tener que mantener constantemente pulsado el botón correspondiente.

Al disponer del botones de sobra, se han mantenido también las funciones originales con delay para maniobras que necesiten de movimientos más precisos.