miércoles, 16 de abril de 2014

Robot Andromina con un mando a distancia. (Robot Arduino, Raspberry, PICAXE, ROS)

En esta entrada muestro el Andromina robot controlado a través de un mando a distancia de una televisión PHILIPS. El robot tiene la configuración básica, una placa Arduino UNO con una "shield" modificada por nosotros con un regulador de voltaje a 5v, una placa de motor y un receptor de IR. El programa que controla el robot ya es un poco más complejo y podríamos añadir un sin fin de maniobras (ver programa más abajo).

Vídeo que muestra algunos movimientos del robot Andromina OFF ROAD.
En el programa hemos configurado botones predefinidos con una maniobra o botones por ejemplo para acelerar o girar el robot.
Robot controlado por IR.
Andromina robot v1.2. y el mando a distancia.
En este montaje hemos usado 6 pilas de 1,2v que nos proporcionan un voltaje de 7.2v. El robot funciona correctamente, pero se nota que estas pilas son un poco justas para este robot e incrementan el peso del robot. Se ha substituido la bateria por una de 12,6v y 9800mAh.de Ion Litio, que esta más acorde a esta aplicación. El robot funciona a la perfección y ha aumentado su velocidad máxima al trabajar ahora 12v.
Robot con control remoto
Disposición de las pilas.
/* Programa para Andromina Robot 4x4 con 4 ruedas direccionales con 4 servos  + Arduino Uno + una "proshield" KEYES 5.1 + motor shield KEYES L298N. (17-04-2013). 
Programa para probar el movimiento del Andromina robot y el mando a distancia PHILIPS. El programa funciona BIEN.
Los servo del robot tiene unos pulsos diferentes que los servos estandares.
Autor: Jordi T. C.
Para que no haya interferencias "Ruido" se tiene que poner un condensador cerámico (0,1uf 50v) soldado en los dos bornes de cada motor.
Para que los motores arranque mejor también es bueno colocar un gran codensador electrolitico (16V) en la entrada de la placa del motor. 
*/// Librerías /////////////////////////////////////////////////////////////////////////////////
#include <Servo.h>    // Carga la libreria de los servos
#include <IRremote.h> // Carga la libreria del mando a distancia
//// Declaración de constantes, teclas del mando a distancia Philips /////////////////////
#define TECLA_ON_1         0XC   // Definición de la tecla ON. Cada tecla tiene dos códigos diferentes.
#define TECLA_ON_2         0X80C  //
#define TECLA_ROJA_1       0X4B995E59
#define TECLA_ROJA_2       0X1C102884
#define TECLA_VERDE_1      0XE050BDE6
#define TECLA_VERDE_2      0XEF4EDF53
#define TECLA_AMARILLA_1   0XDF50BC53
#define TECLA_AMARILLA_2   0XF04EE0E6
#define TECLA_GRIS_1       0X8533B77
#define TECLA_GRIS_2       0X5F564B6A
#define TECLA_MUSICA_1     0X14
#define TECLA_MUSICA_2     0X814
#define TECLA_RADIO_1      0XA4E66026
#define TECLA_RADIO_2      0X9CEDF1F
#define TECLA_PANTALLA_1   0X15
#define TECLA_PANTALLA_2   0X815
#define TECLA_i_1          0XF
#define TECLA_i_2          0X80F
#define TECLA_AUGMENTAR_1  0X2B
#define TECLA_AUGMENTAR_2  0X82
#define TECLA_REDUCIR_1    0X29
#define TECLA_REDUCIR_2    0X829
#define TECLA_PREGUNTA_1   0X2C
#define TECLA_PREGUNTA_2   0X82C
#define TECLA_MENU_1       0XD9F9700B
#define TECLA_MENU_2       0XBFB8F2FE
#define TECLA_RALLAS_1     0X3C
#define TECLA_RALLAS_2     0X83C
#define TECLA_ARRIBA_1     0XE5139CA7
#define TECLA_ARRIBA_2     0XAC516266
#define TECLA_ABAJO_1      0XE4139B12
#define TECLA_ABAJO_2      0XAD5163FB
#define TECLA_IZQUIERDA_1  0XDB9D3097
#define TECLA_IZQUIERDA_2  0XBE15326E
#define TECLA_DERECHA_1    0X9FA96F
#define TECLA_DERECHA_2    0X9912B99A
#define TECLA_VOL_MENOS_1  0X11
#define TECLA_VOL_MENOS_2  0X811
#define TECLA_VOL_MAS_1    0X10
#define TECLA_VOL_MAS_2    0X810
#define TECLA_P_MENOS_1    0X21
#define TECLA_P_MENOS_2    0X821
#define TECLA_P_MAS_1      0X20
#define TECLA_P_MAS_2      0X820
#define TECLA_UNO_1        0X1
#define TECLA_UNO_2        0X801
#define TECLA_DOS_1        0X2
#define TECLA_DOS_2        0X802
#define TECLA_TRES_1       0X3
#define TECLA_TRES_2       0X803
#define TECLA_CUATRO_1     0X4
#define TECLA_CUATRO_2     0X804
#define TECLA_CINCO_1      0X5
#define TECLA_CINCO_2      0X805
#define TECLA_SEIS_1       0X6
#define TECLA_SEIS_2       0X806
#define TECLA_SIETE_1      0X7
#define TECLA_SIETE_2      0X807
#define TECLA_OCHO_1       0X8
#define TECLA_OCHO_2       0X808
#define TECLA_NUEVE_1      0X9
#define TECLA_NUEVE_2      0X809
#define TECLA_CERO_1       0X0
#define TECLA_CERO_2       0X800
const int receptorPin_12 = 12; // Declaración del pin donde se va a recibir la señal del mando a distancia, PIN Nº12
IRrecv irrecv(receptorPin_12); // Crea un objeto para el mando a distancia llamado IRRECV
decode_results results;        // Declara una variable que almacena los resultados del receptor del mando a distancia  
//// Declaración de las variables ///////////////////////////////////////////////////////////////
Servo servo_derecho_delantero; int calibracion_dd = -1; // Declaración de los servos y su calibración inicial.
Servo servo_izquierdo_delantero; int calibracion_id = -3;
Servo servo_derecho_trasero; int calibracion_dt = -2;
Servo servo_izquierdo_trasero; int calibracion_it = 2;
// Variables que almacenan los valores actuales de velocidad, giro tracción del robot. Valores iniciales
int v_d_a = 0;       // velocidad_derecha_actual
int v_i_a = 0;      // velocidad_izquierda_actual
int a_r_d_d_a = 90; // angulo_rueda_derecha_delantera_actual
int a_r_i_d_a = 90; // angulo_rueda_izquierda_delantera_actual
int a_r_d_t_a = 90; // angulo_rueda_derecha_trasera_actual
int a_r_i_t_a = 90; // angulo_rueda_izquierda_trasera_actual
int traccion_actual = 0;
//// Variables del controlador de los 4 motores ///////////////////////////////////////////////
int ENA=5;   //connected to Arduino's port 5 (output pwm)
int IN1=2;    //connected to Arduino's port 2
int IN2=8;    //connected to Arduino's port 8 (ojo que originariamente era la salida 3.
int ENB=6;  //connected to Arduino's port 6(output pwm)
int IN3=4;   //connected to Arduino's port 4
int IN4=7;  //connected to Arduino's port 7
//// Configuración de Arduino ///////////////////////////////////////////////////////////////////
void setup(){
   Serial.begin(115200);    // Velocidad de conexión entre el PC y el Arduino
   irrecv.enableIRIn();   // Inicializa el receptor del mando a distancia
//// Configuración de los 4 servos //////////////////////////////////////////////////////////////
   servo_derecho_delantero.attach(11); delay(100);
   servo_izquierdo_delantero.attach(10);delay(100);
   servo_derecho_trasero.attach(9);delay(100);
   servo_izquierdo_trasero.attach(3);delay(100);
   recto();
//// Configuración de los pines de la placa KEYES L298N.////////////////////////////////////////
   pinMode(ENA,OUTPUT);  // Configuración de las salidas
   pinMode(ENB,OUTPUT);
   pinMode(IN1,OUTPUT);
   pinMode(IN2,OUTPUT);
   pinMode(IN3,OUTPUT);
   pinMode(IN4,OUTPUT);
   delay(500);}
//// Inicio del programa //////////////////////////////////////////////////////////////////////
void loop(){
  if (irrecv.decode(&results)) {mostrarTecla();}}
//// Fin del programa //////////////////////////////////////////////////////////////////////////
//// Función que frena los motores /////////////////////////////////////////////////////////////
void frenar() {
  digitalWrite(ENA,LOW); //Para el motor A
  digitalWrite(ENB,LOW);} //Para el motor B
////Función ir recto /////////////////////////////////////////////////////
void recto(){
  desplazar(0,0,90,90,90,90,0);}
//// Función desplazamiento del robot ///////////////////////////////////////////////////////////////////////////////////
void desplazar(int velocida_derecha,int velocida_izquierda,int angulo_rueda_derecha_delantera,int angulo_rueda_izquierda_delantera,int angulo_rueda_derecha_trasera,int angulo_rueda_izquierda_trasera,int traccion) {
  boolean giro_derecho;    // Variable que define el sentido de giro de los motores
  boolean giro_izquierdo;  // Variable que define el sentido de giro de los motores
  // Variables que almacenan los valores entrantes actuales de velocidad, giro y tracción. 
  v_d_a = velocida_derecha; 
  v_i_a = velocida_izquierda;
  a_r_d_d_a = angulo_rueda_derecha_delantera;
  a_r_i_d_a = angulo_rueda_izquierda_delantera;
  a_r_d_t_a = angulo_rueda_derecha_trasera;
  a_r_i_t_a = angulo_rueda_izquierda_trasera;
  traccion_actual = traccion;
  // Configura el sentido de la marcha //////////////////////////////////////////////////////////////////////////
  if (traccion == 0){ // Tracción hacia delante
    giro_derecho = HIGH; 
    giro_izquierdo = LOW;}
  if (traccion == 1){ // Tracción hacia atras
    giro_derecho =  LOW; 
    giro_izquierdo =  HIGH;}
  if (traccion == 2){ // Tracción hacia la derecha ROTAR
    giro_derecho = LOW; 
    giro_izquierdo = LOW;}
  if (traccion == 3){ // Tracción hacia la izquierda ROTAR
    giro_derecho = HIGH; 
    giro_izquierdo = HIGH;}
//// Activa el Motor A //////////////////////////////////////////////////////////////////////////////
  digitalWrite(IN1,giro_derecho); // IN1 y IN2 Configuran la dirección de giro del motor A. Se tienen que cambiar "invertir" los dos valores HIGH y LOW para invertir el giro.
  digitalWrite(IN2,!giro_derecho);
  analogWrite(ENA,velocida_derecha);   // Inicia la marcha del motor A
//// Activa el Motor B //////////////////////////////////////////////////////////////////////////////  
  digitalWrite(IN3,giro_izquierdo); // IN3 y IN4 Configuran la dirección de giro del motor B. Se tienen que cambiar "invertir" los dos valores HIGH y LOW para invertir el giro.
  digitalWrite(IN4,!giro_izquierdo);
  analogWrite(ENB,velocida_izquierda);   // Inicia la marcha del motor B
//// Giro de la dirección ////////////////////////////////////////////////////////////////////
  delay(150); // Espera a que el robot se ponga en movimiento. El coeficiente de rozamiento dinámico es inferior al coeficiente de rozamiento estàtico. Los servos consumen menos energia.
  servo_derecho_delantero.writeMicroseconds(map(angulo_rueda_derecha_delantera + calibracion_dd,-5, 185,455,2144));  // (0,180,500,2100)    // Giro de la rueda derecha delantera
  delay(50); // Sirve para que los servos no se pongan en funcionamiento todos a la misma vez.
  servo_izquierdo_delantero.writeMicroseconds(map(angulo_rueda_izquierda_delantera + calibracion_id,-5, 185,455,2144));
  delay(50);
  servo_derecho_trasero.writeMicroseconds(map(angulo_rueda_derecha_trasera + calibracion_dt,-5, 185,455,2144));
  delay(50);  
  servo_izquierdo_trasero.writeMicroseconds(map(angulo_rueda_izquierda_trasera + calibracion_it,-5, 185,455,2144));}
//// Función del mando a distancia PHILIPS ////////////////////////
void mostrarTecla (){
         switch (results.value) { // Llega el valor del mando de infrarrojos y lo compara con el "case" que corresponda. Y hace la sentencia del "case"
           case TECLA_ON_1: desplazar(0,0,90,90,90,90,0);break;  // Caso para la tecla ON
           case TECLA_ON_2 : desplazar(0,0,90,90,90,90,0);break;
           case TECLA_ROJA_1: desplazar(v_d_a,v_i_a,a_r_d_d_a-2,a_r_i_d_a-2,a_r_d_t_a-2,a_r_i_t_a-2,traccion_actual); break;
           case TECLA_ROJA_2: desplazar(v_d_a,v_i_a,a_r_d_d_a-2,a_r_i_d_a-2,a_r_d_t_a-2,a_r_i_t_a-2,traccion_actual); break;
          case TECLA_VERDE_1      : desplazar(v_d_a,v_i_a,a_r_d_d_a-2,a_r_i_d_a 2,a_r_d_t_a+2,a_r_i_t_a+2,traccion_actual); break;
           case TECLA_VERDE_2      : desplazar(v_d_a,v_i_a,a_r_d_d_a-2,a_r_i_d_a-2,a_r_d_t_a+2,a_r_i_t_a+2,traccion_actual); break;
           case TECLA_AMARILLA_1   : desplazar(v_d_a,v_i_a,a_r_d_d_a+2,a_r_i_d_a+2,a_r_d_t_a-2,a_r_i_t_a-2,traccion_actual); break;
           case TECLA_AMARILLA_2   : desplazar(v_d_a,v_i_a,a_r_d_d_a+2,a_r_i_d_a+2,a_r_d_t_a-2,a_r_i_t_a-2,traccion_actual); break;
          case TECLA_GRIS_1       : desplazar(v_d_a,v_i_a,a_r_d_d_a+2,a_r_i_d_a+2,a_r_d_t_a+2,a_r_i_t_a+2,traccion_actual); break;
           case TECLA_GRIS_2       : desplazar(v_d_a,v_i_a,a_r_d_d_a+2,a_r_i_d_a+2,a_r_d_t_a+2,a_r_i_t_a+2,traccion_actual); break;
           case TECLA_i_1          : desplazar(255,255,90,90,90,90,2);break;
           case TECLA_i_2          : desplazar(255,255,90,90,90,90,2);break;
           case TECLA_AUGMENTAR_1  : desplazar(155,155,45,45,45,45,0);break;
           case TECLA_AUGMENTAR_2  : desplazar(155,155,45,45,45,45,0);break;
           case TECLA_REDUCIR_1    : desplazar(155,155,135,135,135,135,0);break;
           case TECLA_REDUCIR_2    : desplazar(155,155,135,135,135,135,0);break;
           case TECLA_PREGUNTA_1   : desplazar(255,255,90,90,90,90,3);break;
           case TECLA_PREGUNTA_2   : desplazar(255,255,90,90,90,90,3);break;
           case TECLA_MUSICA_1     : desplazar(v_d_a,v_i_a,3,0,3,16,0);break;
           case TECLA_MUSICA_2     : desplazar(v_d_a,v_i_a,3,0,3,16,0);break;
           case TECLA_RADIO_1      : desplazar(v_d_a,v_i_a,90,90,90,90,0);break;
           case TECLA_RADIO_2      : desplazar(v_d_a,v_i_a,90,90,90,90,0);break;
           case TECLA_PANTALLA_1   : desplazar(v_d_a,v_i_a,200,200,174,160,0);break;
           case TECLA_PANTALLA_2   : desplazar(v_d_a,v_i_a,200,200,174,160,0);break;
           case TECLA_MENU_1       : desplazar(v_d_a,v_i_a,a_r_d_d_a-5,a_r_i_d_a-5,a_r_d_t_a,a_r_i_t_a,traccion_actual); break;
           case TECLA_MENU_2       : desplazar(v_d_a,v_i_a,a_r_d_d_a-5,a_r_i_d_a-5,a_r_d_t_a,a_r_i_t_a,traccion_actual); break;
           case TECLA_RALLAS_1     : desplazar(v_d_a,v_i_a,a_r_d_d_a+5,a_r_i_d_a+5,a_r_d_t_a,a_r_i_t_a,traccion_actual); break;
           case TECLA_RALLAS_2     : desplazar(v_d_a,v_i_a,a_r_d_d_a+5,a_r_i_d_a+5,a_r_d_t_a,a_r_i_t_a,traccion_actual); break;
           case TECLA_ARRIBA_1     : desplazar(155,155,90,90,90,90,0); break;
           case TECLA_ARRIBA_2     : desplazar(155,155,90,90,90,90,0); break;
           case TECLA_ABAJO_1      : desplazar(155,155,90,90,90,90,1); break;
           case TECLA_ABAJO_2      : desplazar(155,155,90,90,90,90,1); break;
           case TECLA_IZQUIERDA_1  : desplazar(155,155,0,0,0,0,0); break;
           case TECLA_IZQUIERDA_2  : desplazar(155,155,0,0,0,0,0); break;
           case TECLA_DERECHA_1    : desplazar(155,155,180,180,180,180,0); break; 
           case TECLA_DERECHA_2    : desplazar(155,155,180,180,180,180,0); break;  
           case TECLA_VOL_MENOS_1  : desplazar(v_d_a-10,v_i_a-10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,0); break;
           case TECLA_VOL_MENOS_2  : desplazar(v_d_a-10,v_i_a-10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,0); break;
           case TECLA_VOL_MAS_1    : desplazar(v_d_a+10,v_i_a+10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,0); break;
           case TECLA_VOL_MAS_2    : desplazar(v_d_a+10,v_i_a+10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,0); break;
           case TECLA_P_MENOS_1    : desplazar(v_d_a-10,v_i_a-10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,1); break;
           case TECLA_P_MENOS_2    : desplazar(v_d_a-10,v_i_a-10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,1); break;
           case TECLA_P_MAS_1      : desplazar(v_d_a+10,v_i_a+10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,1); break;
           case TECLA_P_MAS_2      : desplazar(v_d_a+10,v_i_a+10,a_r_d_d_a,a_r_i_d_a,a_r_d_t_a,a_r_i_t_a,1); break;          
           
           case TECLA_UNO_1        : desplazar(68,150,124,105,56,75,0);break;
           case TECLA_UNO_2        : desplazar(68,150,124,105,56,75,0);break;
           case TECLA_DOS_1        : desplazar(150,68,75,56,105,124,0);break;
           case TECLA_DOS_2        : desplazar(150,68,75,56,105,124,0);break;
           case TECLA_TRES_1       : desplazar(68,150,147.5,109,32.5,71.2,0);break;
           case TECLA_TRES_2       : desplazar(68,150,147.5,109,32.5,71.2,0);break;
           case TECLA_CUATRO_1     : desplazar(150,68,71.2,32.5,109,147.5,0);break;
           case TECLA_CUATRO_2     : desplazar(150,68,71.2,32.5,109,147.5,0);break;
           case TECLA_CINCO_1      : Serial.print("TECLA CINCO_1 = ");Serial.println(TECLA_CINCO_1,HEX); break;
           case TECLA_CINCO_2      : Serial.print("TECLA CINCO_2 = ");Serial.println(TECLA_CINCO_2,HEX); break;
           case TECLA_SEIS_1       : Serial.print("TECLA SEIS_1 = ");Serial.println(TECLA_SEIS_1,HEX); break;
           case TECLA_SEIS_2       : Serial.print("TECLA SEIS_2 = ");Serial.println(TECLA_SEIS_2,HEX); break;
           case TECLA_SIETE_1      : Serial.print("TECLA SIETE_1 = ");Serial.println(TECLA_SIETE_1,HEX); break;
           case TECLA_SIETE_2      : Serial.print("TECLA SIETE_2 = ");Serial.println(TECLA_SIETE_2,HEX); break;
           case TECLA_OCHO_1       : Serial.print("TECLA OCHO_1 = ");Serial.println(TECLA_OCHO_1,HEX); break;
           case TECLA_OCHO_2       : Serial.print("TECLA 0CHO_2 = ");Serial.println(TECLA_OCHO_2,HEX); break;
           case TECLA_NUEVE_1: 
           case TECLA_NUEVE_2: 
           case TECLA_CERO_1: 
           case TECLA_CERO_2: 
       default                     : Serial.print("TECLA SENAL ERRONEA = ");Serial.println(results.value,HEX);break;} // Si no entiende la señal da señal erronea.
    irrecv.resume();} // Inicializa la función para recivir el siguiente valor del mando a distancia.
///// Fin de las funciones ////////////////////////////////////////////////////////////////////////////////


1 comentario :

  1. Hola,

    Cambia esta linea que esta equivocada:
    En este montaje hemos usado 12 pilas de 1,2v que nos proporcionan un voltaje de 7.2v.

    Son 6 pilas en de 12 :-)

    Saludos

    ResponderEliminar

Google analytics