jueves, 29 de diciembre de 2011

Leer radio PPM desde un emisor RC y Arduino. Tutorial

¿Qué diferencias hay entre leer la radio mediante PPM o mediante las señales de los servos?
           Según Jordi Muñoz, Rendimiento y simplicidad en el código son los motivos para leer en PPM y no en PWM.
           Una señal PPM (Pulse Position Modulation) integra todos los canales del receptor/emisor en una sola línea. Así usando sólamente un pin podemos leer los 8 canales de la radio. (Menos cables=menos problemas.)
           La idea es leer las señales de radio con un Arduino auxiliar y mandar los datos de radio ya leídos e interpretados por SPI o i2C al Arduino principal.
           Si desmontamos el receptor, desechando la carcasa y los pines (10x3= 30 pines) ahorramos alrededor del 70 % del peso. Que no es mucho en este caso,además también ahorra espacio.

click en la imagen para agrandar.
       Los transmisores de radio suelen tener dos modos: PPM (Pulse Position Modulation) y PCM (Pulse Code Modulation). Ponerla en modo ACRO (sin mezclas),  sin TRIM,  no DUAL-RATE y tampoco EXPONENCIAL. Esto es para que las lecturas del equipo no se vean distorsionadas por el software de la emisora.


               En el receptor Turnigy 9X 8CH V2 no se puede obtener en ningun sitio de su placa la señal PPM. Ya que este cuenta con dos micros, uno receptor y el otro decodificador, los cuales se comunican por SPI. Aquí una lista de como hackear receptores para sacar la señal PPM enlace.


              Aquí otra solución alternativa para obtener la salida PPM mediante un Chip extra, pero si puedes acceder a esta señal mucho más fácil, ¿no?
           Si no sabemos donde está nuestra señal PPM podemos cargar este programa (de Jordi) e ir comprobando todos los pines con el Serial Monitor hasta ver valores aleatorios de entre 300 y 9000, lo que significará que ya hemos encontrado el pin PPM. No olvidar interconectar las tierras del receptor y arduino!!

void setup()
{
Serial.begin(57600);
pinMode(3, INPUT);
}
void loop()
{
Serial.println(pulseIn(3, LOW));
}


           Los programas usados fueron creados por Jordi Muñoz y subidos al blog de Arduino el 1 de Enero de 2008.

Lector PPM básico Arduino
#define channumber 6 //Cuantos canales tiene tu radio?/How many channels have your radio?
int channel[channumber]; //Valores de canales leidos/ readed Channel values
int PPMin = 4;

void setup()
{
  Serial.begin(9600); //Iniciamos com serial/
  pinMode(PPMin, INPUT); //Patita 4 como entrada / Pin 4 as input
}

void loop()
{
  //Espera hasta que la senal de sincronizacion llegue, debe ser > 4 milisegundos
  //waits ultil synchronize arrives > 4 miliseconds
  if(pulseIn(PPMin , HIGH) > 4000); //Si el pulso del pin 4 es > que 4 msegundos continua /If pulse > 4 miliseconds, continues
  {
    for(int i = 1; i <= channumber; i++) //lee los pulsos de los demas canales / Read the pulses of the remainig channels
    {
 channel[i-1]=pulseIn(PPMin, HIGH);
    }
    for(int i = 1; i <= channumber; i++) //Imprime los valores de todos los canales / Prints all the values readed
    {
 Serial.print("CH"); //Canal/Channel
 Serial.print(i); // Numero del canal / Channel number
 Serial.print(": "); // que te importa
 Serial.println(channel[i-1]); // Imprime el valor/ Print the value
    }
    delay(200);//Le da tiempo para imprimir los valores en el puerto/ Give time to print values.
  }
}


Lector PPM básico con filtro Antisalto:

#define channumber 6 //Cuantos canales tiene tu radio???????/How many channels have your radio???
#define filter 10 // Filtro anti salto/ Glitch Filter
int channel[channumber]; //Valores de canales leidos/ readed Channel values
int lastReadChannel[channumber]; //Ultima lectura obtenida/ Last  values readed
int conta=0; //Contador/couter


void setup()
{
  Serial.begin(9600); //Iniciamos com serial/ Serial Begin
  pinMode(4, INPUT); //Patita 4 como entrada / Pin 4 as input
  pinMode(13, OUTPUT); // Led pin 13
}

void loop()
{

  if(pulseIn(4, HIGH) > 3000) //Si el pulso del pin 4 es > 3000 usegundos continua /If pulse > 3000 useconds, continues
  {
    for(int i = 0; i <= channumber-1; i++) //lee los pulsos de los canales / Read the pulses of the channels
    {
 channel[i]=pulseIn(4, HIGH);
    }
    for(int i = 0; i <= channumber-1; i++) //Promedia los pulsos/Average the pulses
    {
 if((channel[i] > 2000) || (channel[i] <100))//Si se pasa del rango envia ultimo pulso/ If channel > max range, chage the value to the last pulse
 {
  channel[i]= lastReadChannel[i];
 }
 else
 {
 channel[i]=(lastReadChannel[i]+channel[i])/2; //Promedio el pulso pasado con el nuevo pulso/Average the last pulse eith the current pulse
 conta++; //Incrementa el contador/ increment counter
 }
    }

    }
    if(conta > filter)//Si el contador es mayor al filtro imprime valores/ If counter is > than filter, then prints values
    {
 for(int i = 0; i <= channumber-1; i++) //Ciclo para imprimir valores/Cycle to print values
 {
   Serial.print("CH"); //Canal/Channel
   Serial.print(i+1); // Numero del canal / Channel number
   Serial.print(": "); // que te importa
   Serial.println(channel[i]);
   lastReadChannel[i]=channel[i];
 }
 if(channel[4] > 1000) //si el canal 5 tiene un rango mayor a 500 enciende el LED/ If channel 5 is > than 500 turn on the led
 {
   digitalWrite(13, HIGH);
 }
 else
 {
   digitalWrite(13, LOW);//Si no lo apaga/If not turn it off
 }
 delay(400); //Delay
 conta=0;//Reinicia el contador/ Restart couter.
    }
  } 










PPM Vs PWM
PPM and PWM are two different protocols for radio information. The PPM has the advantage that you can get all the channels information through one port only. Some call it PPM sum since it’s the sum of all channels. That helps a lot when you have limit number of connectors to your flightcontroller. So I will use PPM into my flight controller, and then the flight controller will use PWM outputs to the ESCs and to the servos for the camera mount.
By using the PPM input, I can now use 10 PWM outputs from my Open Pilot Copter Control instead of 6 PWM outputs. That is for obvious reasons essential for me, because my camera mount needs two servo outputs plus the 6 ESC outputs.

miércoles, 28 de diciembre de 2011

Como controlar un motor Brushless con Arduino. Tutorial

            A continuación explico con un pequeño tutorial, como controlar un motor Brushless con un variador de velocidad (ESC) y una placa Arduino o en mi caso, ArduPilotMega.



Necesitamos un batería LiPo, un ESC, un motor Brushless y un Arduino.

El esquema de conexión utilizado es el siguiente:


              Para controlar un motor de este tipo hay que mandar al ESC señales como si quisiéramos controlar un servo normal. Estas señales son cuadradas con un tiempo en alto que varían entre 1 y 2 milisegundos, que correspondería a un águlo de entre 0 y 180 grados. Podemos probar primero con un servo: Si un servo no se mueve, el motor brushless nunca lo hará.



          Para la conexión con el microcontrolador usaremos un pin de salida, en nuestro caso usaremos el pin 8. Si usamos ArduPilot Mega, este pin número 8 equivale al canal número 5 (CH_5). Conectamos el cable blanco al pin, el cable rojo, alimentación, queda libre y las tierras las unimos. (cable negro a GND del arduino)

          Para conectar el ESC, le conectamos los cables de alimentación a la batería LiPo mediante un conector tipo banana de 4mm.(también podemos utilizar un fuente de alimentación externa, pero debemos de asegurarnos que tenga la potencia que el motor requiera.. que por lo general suele ser alta) Y para las conexiones del motor, en mi caso he soldado unas pinzas como se muestra en la figura. Importante amarrar bien el motor a una madera, ya que al arrancar puede ser peligroso y más si es un motor outrunner.


      Para el código,importante armar el motor antes de arrancarlo, ya que si no lo hacemos no arrancará nunca. Para inicializar un motor basta con enviar señales de ángulo 0 hasta que el motor emita pitidos. Consiste en recibir un pulso de 1 milisegundo cada 20 milisegundos por un tiempo aproximado de 4 o 5 segundos.
        El proceso es:


  • Alimentar el ESC y escuchar la música de confirmación.
  • Armar: 

          myservo.write(0);   // Aramado

  • Esperar pitidos  "Ready".
  • Mover el motor:

           myservo.write(pulsoMotor); //pulsoMotor lo variamos desde alrededor de 70 a 180 (máximo)


          Notas:

  • Cada motor arranca con una señal de ángulo diferente, en mi caso está en 65º.
  • Si despues de armarlo envío señal de 70 directamente no arranca, hay que subir progresivamente. Basta con mandar un 30º y ya pasar a 70º.
  • Si queremos cambiar el sentido de giro al motor, intercambiando 2 de los 3 cables de motor es suficiente.



Descargar aquí el archivo con el CÓDIGO.

Para cualquier duda, sugerencia o opinión no dude en comentar.