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. 

18 comentarios:

  1. Hola, sólo darte las gracias por la info que compartes, era justo lo que buscaba, tambien estoy armando un quadcopter de a poco. Saludos y seguiré volviendo por tu blog

    ResponderEliminar
  2. Muchas gracias. Otra opción, quizá mas precisa sea usar la librería "ServoTimer2.h" . Está en las estandares de Arduino, y tiene precisión de microsegundos. (más precisión) ya que con está tenemos precisión un paso de 11 usegndos =1º (grado)

    ResponderEliminar
  3. Muchas Gracias por la info =), justo estaba buscando esto, en cuanto me lleguen mis nuevos brushless outrunners motors los testeare.

    Y también probaré la librería ServoTimer2.h que menciona Albertolg, chance y me cree una para pic, saludos amigo.

    Te sigo

    ResponderEliminar
  4. Se podría llegar a sustituir la batería por una transformador de alterna a continua?? es decir 230 VAC / 15 VDC por poner un ejemplo.

    ResponderEliminar
    Respuestas
    1. Siempre que tenga suficiente potencia para poder arrancar el motor. Los motores consumen mucho al arrancar (corriente de pico) durante muy poco tiempo. Tienes que comprobar lo amperios que saca el trafo, o calcularlo mediante la potencia. (Potencia= Voltaje*Intensidad)

      Eliminar
  5. Perdona mi ignorancia, pero ya he seguido todo el diagrama de conexionado, estoy usando para las pruebas una fuente ATX que me ataca 12V al ESC, conectado a los pines 8 del Arduino Uno... pero no hace nada.

    Viendo el código veo que recibes desde serie comandos de teclado... pero cómo se hace eso? directamente desde el SDK de Arduino?

    Gracias!

    ResponderEliminar
  6. Hola, para mandar comandos por el puerto serie, tienes que abrir el "Serial Monitor", escribir y pulsar enter. Creo que en los últimos entornos de Arduino lo han llamado SDK.

    1 Saludo

    ResponderEliminar
  7. Hola Alberto,

    Gracias por el código, muy útil.

    Una pregunta, antes de usar el motor, ¿no programas el ESC dándole los valores de GAS Max.y GAs mínimo?

    Saludos y gracias,

    Alberto

    ResponderEliminar
  8. Yo me compré la targeta programadora, pero tampoco sirve para mucho, puedes cambiar algunos parámetros, pero los que viene por defecto creo que están bien. A mi sólo ma ha servido para cambiar la melodía de inicio...

    1 saludo

    ResponderEliminar
  9. Jajaja... ni que fueran un móvil :-P
    No, me refiero a programarlos con la Arduino para que los valores de GAS max y min. coincidan con los que tú usas en tu código.

    Esto no aporta nada de cara al uso final en el quad (necesariamente habrá que reprogramarlos con la emisora) pero sí lo veo interesante si lo que se quiere es probar (y comprender mejor) el funcionamiento del duo ESC-motor.

    En fin, sólo preguntaba.

    Gracias y un saludo

    ResponderEliminar
  10. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  11. OLA QUE TAL????bueno primero te felicitoo por tener un gran blog sobre tus proyectos realmente esta muy bueno,pero mi consulta es la siguiente....tengo un motor brushless de 1800kv a una potencia de 165W quisiera saber por que esque mi motor no gira con tu codigoo....o cuanta carga necesito para hacerla girar o que es lo que tu me recomiendas,agradeciendo tu respuesta anticipadamente

    ResponderEliminar
    Respuestas
    1. Pueden ser muchas cosas, has comprobado q estén las GND interconectadas? si enchufas un servo se mueve? el ESC tiene q emitir unos pitidos cuando está preparado.

      Eliminar
  12. que tal buenas tardes si podrias aclarme esta duda la verdad no se mucho de esto pero ese codigo me sirve igual para un arduino uno r3

    ResponderEliminar
    Respuestas
    1. Si, son totalmente compatibles, tienes q comprobar la numeración de los pines q sean los correctos!

      Eliminar
  13. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  14. Hola, muchas gracias en primer lugar porque me ha servido de mucho tu aportación. Estoy intentando mover un Brushless maxon de 50 W y poder invertir el sentido de giro del motor a través de código, es decir, vía software de la manera más rápida posible y no cambiando los cables, ni usando la tarjeta de programación o la emisora, pues lo voy a montar en un pequeño robot que no es de aeromodelismo y quiero que autoequilibre. Supongo que necesito un ESC que me de esa opción de inversión de giro como dice este, en la descripción en el punto 5:

    http://www.avionrc.es/variador-brushless-30a-titan-con-conectores-5552-p.asp

    ¿Alguna vez has hecho algo parecido? Tengo entendido que con la PWM podría invertir el giro o quizás con algún comando específico pero no encuentro documentación al respecto, si me puedes dar alguna referencia lo agradecería muchísimo. No quiero comprarme el ESC y que luego no me vaya a servir.
    Además no sé si me podrías confirmar si los ESC que permiten estos cambios de giro son los llamados en inglés ESC reverse.

    Quizás necesite usar un ESC de coche que me permitiría el cambio de giro, pero a la vez me interesa que sea lo más compacto y ligero posible por diseño y el del link sería una buena opción en este caso.

    Muchas gracias de antemano y perdona la longitud del texto.

    ResponderEliminar
  15. buenas amigo, primero dejame felicitarte que buen post, ahora tengo una pregunta,
    lo que pasa es que yo tambien estoy armando un cuadroptero y utilice tu codigo mas unas ligeras modificaciones y me andubo perfecto pero quice hacer un un ajuste mas que es controlarlo por bluetooth y alli es donde me presento problemas, el arduino no me reconoce el puerto com del bluetooth y no se por que, kisa puedas hecharme una mano, te paso el codigo para que veas las ligeras diferencias y creo yo q alli esta el problema
    #include
    #define PINMOTOR1 7 //in conectado al ESC, corresponde al pin 8
    #define PINMOTOR2 8
    #define PINMOTOR3 9
    #define PINMOTOR4 10
    #define MAXIMOPWM 150 //Son grados Podia llegar hasta 180
    #define MINIMOPWM 60 //por si acaso empezar con un valor inferior, mi motor no arranca hasta 62
    #define PASO 1 // Incrementos del teclado
    #define BAUD 9600 //velocidad puerto serial funciona hasta 38400

    Servo mysecondservo;
    Servo mythirdservo;
    Servo myfourthservo;
    int pulsoMotor;
    int ordenTeclado=0;
    Servo myservo; // creamos el motor como elemento en la libreria
    byte recibiendoByte ;
    boolean iniciado = false;
    void setup()
    {
    Serial.begin(BAUD);
    Serial2.begin(9600); //bluetooth
    myservo.attach(PINMOTOR1); // inicializo el ESC en el pin determinado
    mysecondservo.attach(PINMOTOR2);
    mythirdservo.attach(PINMOTOR3);
    myfourthservo.attach(PINMOTOR4);
    Serial.println(" Comienzo del test"); //
    Serial.println (" Pulsar 'A' para arrancar \n Cuando escuche el pitido de confirmación");
    while ( iniciado==false ){
    myservo.write(0); // Aramado
    mysecondservo.write(0);
    mythirdservo.write(0);
    myfourthservo.write(0);
    recibiendoByte = Serial.read(); // Leemos el Byte recibido
    if (recibiendoByte == 65 || recibiendoByte ==97) { // A o a Mayusculas o minusculas
    iniciado=true;
    }
    }
    Serial.println("inicio del loop principal \n Para subir controlar velocidad pulse \n 'A' para subir \n 'Z' para bajar \n 'S' para terminar Stop \n");
    }

    void loop(){

    ordenTeclado =OrdenSubirBajar ();

    if (ordenTeclado != 0) { // Distinto de Cero
    pulsoMotor = pulsoMotor + ordenTeclado;

    pulsoMotor= constrain( pulsoMotor , MINIMOPWM, MAXIMOPWM); //
    myservo.write(pulsoMotor); //Mientras no hay cambios, automaticamente se siguen enviando los mismos pulsos
    mysecondservo.write(pulsoMotor);
    mythirdservo.write(pulsoMotor);
    myfourthservo.write(pulsoMotor);
    Serial.print("Velocidad del pulso--> ");
    Serial.println (pulsoMotor);
    }

    delay (150); //delay para no colapsar
    }

    int OrdenSubirBajar (){
    int orden=0;
    // Serial.flush();// Limpiamos el Bufer de entrada (evitar efecto ametralladora)
    //delay (150);

    if (Serial.available() > 0) {
    recibiendoByte = Serial.read(); // Leemos el Byte recibido
    if (recibiendoByte == 65 || recibiendoByte ==97) { // A o A Mayusculas o minusculas
    Serial.println( " SUBIR");
    orden = PASO;
    }
    if (recibiendoByte == 90 || recibiendoByte ==122) { // Z o z Mayusculas o minisculas
    Serial.println( " BAJAR");
    orden = -PASO;
    }
    if (recibiendoByte == 83 || recibiendoByte == 115){ // t o T Mayusculas o minisculas
    Serial.println( " Stop!!");
    orden = -(pulsoMotor- MINIMOPWM); // Deja el pulso en MINIMOPWM
    }
    }
    return (orden);
    }

    ResponderEliminar