5/31/2016

Selección de motores para robots

Selección de motores para robots

Dentro de todas las opciones que se pueden encontrar en el mercado actualmente, vamos a comentar unas cuantas opciones con la que he trabajado o estoy trabajando. Lo primero que necesitamos saber es que necesitamos hacer con el robot, es necesario llevar una carga pesada, que tipo de control necesito, rápido, preciso, etc. Para ello explicaremos una serie de alternativas y como controlarlas.

Servomotores


Hace unos cuantos años ya, se empleaban los servomotores hackeados, se le eliminaba la electrónica y el bloqueo mecánico, convirtiéndolos en motores DC con una reducción. Hoy en día existen los servos normales de 180 grados y los de 360 grados o continuos. Nos centraremos en estos últimos que nos permitirán un control estable de la velocidad del robot.



Principales características

Incluyen el driver de control del motor.

La reducción le da una fuerza elevada para el tamaño del motor.

Velocidad reducida.

Estabilidad.

Servos existen de muchos tipos, analógicos, digitales, con feedbak de posición, etc. Pero casi todos ellos se controlan de la misma manera. Cada 20 ms el servo ha de recibir un pulso.




En este caso al ser de 360 grados el comportamiento es diferente, el servo no se posiciona en un ángulo determinado, sino que gira en un sentido u otro a una velocidad proporcional al ángulo. Si le enviamos un pulso de 1500 us el motor no se mueve, a partir de ahí si aumentamos o disminuimos el tamaño del pulso aumentamos la velocidad en una dirección o en la otra.






180 grados o 1000 us (estos valores de tiempo de pulsos varían en función del modelo de servo) sería la velocidad máxima en el sentido de las agujas del reloj. 0 grados la velocidad máxima en sentido anti horario.

Control


Si empleamos un Arduino, su control es sencillo empleando la librería Servo.h


#include <Servo.h>
Servo servo1;
void setup()
{
 servo1.attach(3); // la entrada donde colocas el servo
}

void loop()
{
servo1.write(90); // Posición en forma de ángulo de 0à180 grados
servo1.writeMicroseconds(1500); // Posición en forma de tiempo 400à2200 us en función del servo                 
  }


Si trabajamos con pics se puede hacer un programa sencillo controlando las interrupciones de forma que cada 20 ms obtengamos el pulso que necesitamos.


#include <16F684.h>
int16 val=1500;
#int_TIMER2
void  TIMER2_isr(void)
{
output_high(PIN_C1); // tenemos conectado el servo en el pin C1
delay_us(val); // tiempo que le indicamos la posición
output_low(PIN_C1);
}
void main()
{
   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_16,250,10); // configuración de la interrupción a 20.0ms
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER2);  // se habilitan las interrupciones
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ);
   set_adc_channel(0);
  
   while(1){                    //loop
   }
}



En el ejemplo anterior podemos ir actualizando el valor de “val” para ir cambiando de posición o velocidad el servo. Si realizamos muchos procesos dentro de la interrupción, podemos calcular el tiempo que tarda en ejecutarse y ajustar el tiempo de la interrupción para que se realice cada 20 ms.


Base con servos de contuina


Motores DC



Los más conocidos y empleados son los motores de corriente continua, siendo consciente que los servomotores llevan motores en continua. Aquí vamos a explicar los diferentes tipos que podemos encontrar. Teniendo en cuenta que nuestra intención es para construir robots o vehículos de radiocontrol. En esta sección hablaremos del tipo de motores que se pueden emplear y como controlarlos.





Principales características

            Baratos.

            Multitud de formatos.

            Control sencillo.

            Bajo consumo, velocidad alta poco par.

Motores de escobillas de poca potencia


El motor de escobillas tiene como característica un rotor bobinado y un estator formado por imanes permanentes, son muy ruidosos eléctricamente hablado pues la conmutación de las escobillas hace saltar muchas chispas. Pero también son muy baratos de fabricar y por ello se emplean en un sinfín de electrodomésticos.

Son los motores DC de poco consumo funcionan con tensiones de 1 ,5 a 6 V y un consumo de corriente reducido. Para que os hagáis una idea sería el equivalente de los motores que llevan los servos, sin la reducción.  El problema está a la hora de conectarlos al microcontrolador pues las salidas de estos proporcionan corrientes de unos 40mA. Quizá algunos modelos de motores funcionen si carga, pero poco harán.

Existe otro problema con el conectar motores dc directamente al Arduino o similares, los motores no dejan de ser bobinas, que una vez cargadas tienden a descargarse. Si realizamos conmutaciones para controlar la velocidad de un motor esta posiblemente sufrirá las descargas y puede fastidiarnos esa salida.

Solución conectar un driver, o un circuito que nos realice la conmutación.



Este tipo de circuitos también nos serviría para controlar un relé o cualquier dispositivo que necesite más corriente de salida.



El inconveniente que presente este montaje es que el motor solo nos girara en un sentido, si queremos que pueda girar en varios sentidos tendremos que o bien hacer un puente en H o emplear un driver.


L298M: Control de 2 motores DC o un PSP, 2,5 A de salida Max.

L272M: Control de un motor DC , 1 A de salida Max.






Comento estos porque son algunos de los que he empleado, encontrareis un monton más de soluciones por internet. El primero tendréis que montar un puente en H de diodos para controlar el motor o bien compraros el kit montado, pero la diferencia de precio es alta.


En Arduino definiremos 4 salidas digitales, recomendable que al menos dos de ellas sean pwm.


int motor1= 2;
int pwmM1=3;
int motor2=4;
int pwmM2=5
unsigned char vel1=0;
unsigned char vel2=0;
boolean direc1=false;
boolean direc2=false;
delayMove=1000;

void setup() {
  pinMode(motor1,OUTPUT);
  pinMode(pwmM1,OUTPUT);
  pinMode(motor2,OUTPUT);
  pinMode(pwmM2,OUTPUT);
}

void moveMotor(unsigned char m1,boolean d1, unsigned char m2,boolean d2, int delayM){
  digitalWrite(motor1,d1);
 analogWrite(pwmM1,m1);
  digitalWrite(motor2,d2);
 analogWrite(pwmM2,m2);
  delay(delayM);
}


void loop() {
  moveMotor(255,0,255,0,1000); // àforward
  moveMotor(0,1,0,1,1000); //àbackward
  moveMotor(0,1,255,0,1000);// àLeft
  moveMotor(255,0,0,1,1000);//àRight
 moveMotor(vel1,direc1,vel2,direc2,delayMove); // con los valores actuales àStop
}



La velocidad de los motores se determina con variable vel1 y vel2 y toman valores de 0 a 255 y el tiempo que realiza el movimiento lo determina el tiempo que le demos al delay.




L298 montado con Photon
 L272M(x2) montado con teensy 3.2




En mis últimos montajes estamos empleando el L272M, dado su reducido tamaño y la simplicidad de su montaje. Y los motores que empleamos son estos, con una reducción de 298:1 no son muy rápidos, pero si dan mucha precisión de movimientos, existen de diferentes reducciones 5;1,10:1,30:1,50:1 o 298:1. Evidente me para tu montaje debes llegar a un compromiso entre velocidad y fuerza.









Este tipo de motor nos permite también reducir el espacio que ocupaban los servomotores.

Dejándonos un espacio útil para la electrónica y las baterías, que son otros factores importantes a la hora de diseñar nuestro Robot.


En la imagen se aprecia la estructura y motores del ColorBot.




Motores de radiocontrol


El sistema de muchos de ellos es idéntico al anterior, sistema de escobillas, pero requieren más potencia y son más grandes. Para ellos podríamos emplear un circuito similar al primero que os he mostrado con el transistor NPN bc547. Pero en este caso empleando un transistor mosfet.





Yo estoy utilizando el modelo IRPF3708, pero lo utilizo para conmutar líneas de leds, termo resistencias o ventiladores. Al igual que en ejemplo anterior solo se puede controlar la velocidad en un sentido.






Principales características

            Baratos.

            Altas prestaciones ratio velocidad/par.


           
Para controlar este tipo de motores recomiendo la utilización de variadores, ahorran la circuitería de potencia y el control es simple.


Dos cables se conectan al motor, dos cables a la batería normalmente de 7,2 v 3600mAh y el conector de servo se conecta con el microcontrolador. Su control se realiza de forma similar al control de un servomotor en continua como hemos explicado en el primer apartado.







Aquí os muestro uno de los vehículos que tenemos de radiocontrol, es un coche 4x4.


Las ventajas de este tipo de control es que se proporciona gran potencia a los motores y se adquiere una gran velocidad.

Así mismo se obtiene una falta de precisión en el control, no me malinterpretéis, el coche se controla de maravilla, pero es muy difícil darle ordenes específicas para realizar operaciones de precisión. Según el modelo de variador se pueden programar rampas de aceleración y desaceleración.

Si empleáis la librería servo.h para controlar estos motores con el variador, notareis que a bajas velocidades el variador pita y el motor casi no se mueve, eso es debido no se alcanza el par motor suficiente para moverlo y el motor vibra.




Motores Brushelss


A diferencia de los motores de escobillas vistos hasta ahora los brushless tiene un rotor con imanes permanentes y un estator con los bobinados, muy eficientes. La conmutación mecánica de los motores DC se substituye por una conmutación electrónica, de la cual se encarga en driver. Si bien no producen chispas ni salto de arcos, como los motores de escobillas, la conmutación electrónica puede producir otro tipo de interferencias en armónicos, pero que se pueden evitar si el sistema esta protegido. Se están empleando mucho en drones por su relación entre potencia y tamaño, también en ventiladores de cpu o en discos duros.



Principales características

            Compacto

            Relación baja de potencia/peso

            Par máximo de 3 a 6 veces el par en servicio continuo.






Para realizar el control es necesario un driver.

El motor brushless tiene tres cables que se conectan al driver. El driver a su vez tiene unos dos conectores para la batería y un conector tipo servomotor.



Si lo queréis controlar con Arduino podéis emplear la librería servo.h como en las anteriores ocasiones.


Mi experiencia con ellos ha sido poca, únicamente cambiar algún driver quemado o un motor roto en los cuadricoptero que tenemos.



Aunque hay muchos montajes con que se pueden llevar a cabo con motores brushless reciclados, por ejemplo, los discos duros que han pasado a mejor vida pueden proporcionar elementos reutilizables como los imanes o el motor.


Motores PAP



Otro tipo de motores muy usados son los motores paso a paso o stepper que bien en estos últimos años se han puesto en boga debido a las impresoras 3d. aunque desde hace años los relacionamos con las impresoras normales una fuente de material de reciclaje.



El precio de estos ha bajado considerablemente y se pueden encontrar a buen precio. Los PAP tiene una ventaja respecto a los motores en continua y es que el rotor se mueve a intervalos regulares y no de forma continua, por ello es sencillo emplearlo para movimientos de precisión.









Principales características

            Barato.

            De fácil control y preciso.

            Desde 6 a 600 pulsos por vuelta.


Existen varios tipos de motores PAP de dos, tres fases o más los llamados polifases, y en la clase de devanado que puede ser unipolar o bipolar. Para esta explicación nos centraremos en los motores bipolares.



De los seis cables que traen el motor solo emplearemos cuatro para su control, descartando el amarillo y el blanco.


Es necesario de un driver para controlarlo, en el mercado hay un gran número de opciones para emplear desde el L298, ULN28003PG, A4988 , etc…



El L298 ya lo comentamos con los motores de continua, en esta ocasión en vez de controlar dos motores solo podremos controlar uno.


El ULN28003 nos proporciona una alta salida de corriente que tenemos que regular con resistencias, aconsejo resistencias de potencia pues las normales de 1/4W se chamuscan.



En la imagen muestro una placa de testeo que me hice con un PIC18F4420.


Para controlar un par de motores pap, la cuestión era ver que mejor alternativa escoger. Como podéis observar las resistencias están algo ennegrecidas.



Adapte o sablee o rehusé, la librería Accelstepper.h hecha para Arduino para poder utilizarla con los pic´s, que aquí os podéis descargar.








Finalmente, en casi todos los proyectos he terminado usando los drivers A4988 por su simplicidad en el montaje.



Se puede emplear estos motores para un gran número de proyectos:

Impresoras 3D o cnc.

Vehículos, donde se requiera precisión de movimientos, grandes o pequeños.

Plataformas rotatorias para escáner 3D.




La tensión que necesitan los motores pap suelen ser superiores que el resto. Pero con baterías de 7,2 V 3600mAh podéis hacer funcionar estos motores sin problemas, únicamente tenéis que tener en cuenta la carga que han de desplazar. Si no son robots móviles suelo emplear transformadores a 12V 3 A.









Si empleamos la librería Accelstepper.h, podemos contar el número de pulsos que el motor recibe y emplear esa información como un encoder… Pero no podemos estar seguro de que el motor no se ha saltado ningún paso, o que ha iniciado en la posición correcta. Por ello se recomienda emplear finales de carrera para indicar el punto de inicio.


Aquí os dejo un ejemplo para controlar los motores pap, utilizo la función stepper1.runSpeed() incluida en la librería Accelstepper.h, lo que me proporcionara una velocidad constante al movimiento del motor el tiempo que determine el usuario. El usuario envía mediante bluetooth, xbee, o cable una instrucción codificada en la siguiente forma:



0x01
byte M1
byte M2
byte Tmove
0x01



El primer y último byte lo empleo para comprobar que el mensaje que llega es correcto, el byte M1 indico la velocidad y la dirección de ese motor, de 0 a 127 es un sentido y de 128 a 255 es en el otro, con M2 se hace igual, en Tmove enviamos una letra que determina el tiempo que se repite la orden.


#include <AccelStepper.h>
AccelStepper stepper1(AccelStepper::DRIVER, 3,2);
AccelStepper stepper2(AccelStepper::DRIVER, 9,10);
boolean  EnablePin1=4;
boolean EnablePin2=11;
byte bufer[5];
int i=0;
long aux1,aux2;
boolean dir_be1=0, dir_be2=0;
long repe=10000;
int pi=0;
int aux5,aux6,aux7;

void setup()
{
  Serial.Begin(9600);
  digitalWrite(EnablePin1,LOW);
  digitalWrite(EnablePin2,LOW);
  stepper1.setMaxSpeed(600.0);
  stepper1.setAcceleration(10000.0);
  stepper2.setMaxSpeed(600.0);
  stepper2.setAcceleration(10000.0);
  stepper1.setPinsInverted(false,false,false);
  stepper2.setPinsInverted(true,false,false);
  stepper1.setCurrentPosition(0);
  stepper2.setCurrentPosition(0);
  }

void loop()
{
  if(pi<repe){ 
  if(aux1>0)  { stepper1.runSpeed();}
  if(aux2>0)  { stepper2.runSpeed();}
  pi++;}

  }

void serialEvent(){
  i=0;
 aux5=millis();
  do{
     if (Serial.available()>0) {
     bufer[i]= Serial.read();
     i++;}
     aux6=millis();
     aux7=aux6-aux5;
      }while((i<5)&&(aux7<5));

     if ((bufer[0]==0x01)&&(bufer[4]==0x01)){ // message is correct
        Serial.println("Message received");
        aux1=long(bufer[1]);
        aux2=long(bufer[2]);
        char Tmove=bufer[3];
        switch (Tmove){
            case 'A':repe=10000;break;//500ms
            case 'B':repe=8000;break;//400ms
            case 'C':repe=6000;break;//300ms
            case 'D':repe=4000;break;//200ms
            case 'E':repe=2000;break;//100ms
            case 'Z': repe=100000;break;//5s
          }
          if (aux1==0){
            stepper1.setSpeed(0);
            stepper1.setPinsInverted(false,false,false);}
            else if (aux1<=128){
              stepper1.setPinsInverted(false,false,true);
              aux1*=6;
              stepper1.setSpeed(aux1);
             
                  }else if (aux1>128){
                    stepper1.setPinsInverted(true,false,true);
                    aux1-=128;
                    aux1*=6;
                    stepper1.setSpeed(aux1);
                   
                  }
                 
          if (aux2==0){         
            stepper2.setSpeed(0);
            stepper2.setPinsInverted(false,false,false);}
            else if (aux2<=128){
              stepper2.setPinsInverted(true,false,true);
              aux2*=6;
             stepper2.setSpeed(aux2);
                  }else if (aux2>128){
                    stepper2.setPinsInverted(false,false,true);
                    aux2-=128;
                     aux2*=6;
                    stepper2.setSpeed(aux2);
                  }
                   
          pi=0;
        }

  }



Anakleto.

2 comentarios:

  1. Que interesante!! Gracias por el post Anakleto !!

    ResponderEliminar