Tutorial Módulo Controlador de servos PCA9685 con Arduino Leave a comment

Comparte este Post

EL controlador PCA9685 fue diseñado para controlar leds por PWM, pero también nos permite controlar servos, ya que estos también se controlan por PWM, aplicación que actualmente es muy usada.

El Módulo Controlador de servos PCA9685 tiene la placa diseñada para el control de servos, tiene los pines en el orden correcto para simplemente conectar los servomotores, además una bornera para la alimentación de los servos y conectores para la alimentación de la parte lógica junto con los pines I2C para comunicarse con arduino.

Se puede establecer la dirección I2C soldando los puentes A0-A5 con esto podemos usar el mismo bus I2C para controlar más módulos PCA9685 u otros dispositivos I2C

Módulo Controlador de servos PCA9685

EL PCA9685 nos permite controlar individualmente 16 salidas PWM con 12 bits de resolución y con frecuencia máxima de 1600Hz.

La salida PWM que envía el PCA9685 es de la siguiente forma:

Pulso PWM PCA9685

Básicamente lo se tiene que establecer es la frecuencia de la señal PWM, frecuencia que será la misma para las 16 salidas PWM. Para establecer el ciclo de trabajo (Duty) tenemos que manipular el flanco de subida (Up) y flanco de bajada (Down), esto se configura individualmente para cada salida PWM, La resolución del PWM es de 12 bits (de 0 a 4095)

Conexión Entre Arduino y Modulo PCA9685

 

Módulo PCA9685Arduino Uno, Nano, Mini.Arduino Mega , DUEArduino Leonardo
  GNDGNDGNDGND
  OEGNDGNDGND
  SCLA5213
  SDAA4202
  VCC5V5V5V
  +VNo conectadoNo conectadoNo conectado

VCC es la alimentación para la parte lógica del módulo y V+ es la alimentación para los servomotores, entonces adicionalmente se tienen que conectar una fuente externa a V+ y GND, fuente que debe ser  del voltaje correspondiente a los servos. No usar los 5V que entrega Arduino para alimentar a lo servos pues los 5V que entrega la placa Arduino es de poca corriente.

La mayoría de servos trabajan con voltajes de 4.5 y 6V nosotros usaremos una fuente de 5V / 5A.

La corriente mínima de la fuente externa depende del tipo de servomotores que se use y de la cantidad de servos que estarán conectados, Si bien la corriente no es un dato constante en el servomotor es mejor sobredimensionar la fuente para que trabaje correctamente, si la fuente no es muy estable o genera ruido, es necesario soldar un condensador en el espacio de la placa del Módulo con una valor de 1000uF o el equivalente a 100uF por cada servomotor.

Entonces, gráficamente las conexiones serian dela siguiente forma:

Conexion arduino y PCA9685

Librería PCA9685 para Arduino

Usaremos la librería de Adafruit el cual lo pueden descargar aquí:
https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library

Después de descargar necesitan importar la librería al IDE Arduino

Expliquemos como usar la librería:

Como cualquier librería inicialmente se incluyen las librerías correspondientes y se declara la variable u objeto:

#include <Wire.h>
#include 

Adafruit_PWMServoDriver servos = Adafruit_PWMServoDriver(dirección);

La dirección si no han modificado en su placa del módulo PCA9685 es 0x40, si desean modificar la dirección, necesitan soldar los puentes de la placa, y queda establecida por: Dirección=0|1|A5|A4|A3|A2|A1|A0, por ejemplo si no sueldan ningún puente seria 01000000=0x40, si sueldan el segundo puente seria: 01000100=0x44

El siguiente paso es inicializar el objeto creado anteriormente.

  servos.begin();  

Posteriormente configurar la frecuencia del PWM, que será la misma para los 16 canales PWM

  servos.setPWMFreq(60); 

La frecuencia que usamos es de 60Hz que equivale una señal PWM con periodo 16,6ms que se encuentra dentro del rango del ciclo de trabajo de la mayoría de los servos

Para establecer el ancho de pulso de una salida PWM usamos la siguiente función

  servos.setPWM(n_servo, up, down);  

En este caso n_servo es el número de servo o salida que van a configurar (valor entre 0 y 15), up es el valor de cuentas en el que se producirá el flanco de subida, y down el valor para el flanco de bajada, ambos valores deben estar entre el valor de 0 y 4096 (12bits). El ancho de pulso será la resta de down-up.

Explicado el uso de la librería vamos a ver unos ejemplos:

Realizando un Sweep, barrido de 16 servos:

Este ejemplo hace una barrido de 0 a 180° y después de 180° a 0°, el barrido se hace a todos los servos por igual.

Antes de empezar necesitamos saber el ancho de pulso (duty) para la posición 0° y el correspondiente para 180°

Trabajaremos con 172 (0.7ms) para la posición 0° y 565(2.3ms) para la posición 180°

Para otros valores de los extremos del servo pueden calcularlo con la siguiente formula:

nCuentas=Pulso_ms*(frecuencia_Hz/1000)*4096

Generalmente se acostumbra aumentar o disminuyen los valores mínimo (0°) y máximo (180) hasta conseguir los valores para el rango correcto,

El sketch es el siguiente:

#include <Wire.h>
#include 

Adafruit_PWMServoDriver servos = Adafruit_PWMServoDriver(0x40);

unsigned int pos0=172; // ancho de pulso en cuentas para pocicion 0°
unsigned int pos180=565; // ancho de pulso en cuentas para la pocicion 180°

void setup() {
  servos.begin();  
  servos.setPWMFreq(60); //Frecuecia PWM de 60Hz o T=16,66ms
}


void loop() {
  
  for (int duty = pos0; duty < pos180; duty=duty+10) {
    for(int n=0;n<16;n++)
    {
      servos.setPWM(n,0,duty);
    }   
  }
  delay(1000);
  for (int duty = pos180; duty > pos0; duty=duty-10) {
    for(int n=0;n<16;n++)
    {
      servos.setPWM(n,0,duty);
    }   
  }
  delay(1000);
}

Moviendo los servomotores en posiciones diferentes.

Para la mayoría de aplicaciones los servomotores van a estar en diferente posición, para este caso es mejor hacer una función que nos calcule y envié el valor en cuentas al servo y manipular el servo desde el void loop() con con valores de 0 y 180.

La función seria la siguiente:

void setServo(uint8_t n_servo, int angulo) {
  int duty;
  duty=map(angulo,0,180,pos0, pos180);
  servos.setPWM(n_servo, 0, duty);  
}

Con esta función podemos enviar a cualquier servomotor el valor del ángulo al que queremos que se ubique.

El sketch que se muestra a continuación mueve los servomotores cada segundo a posiciones establecidas:

#include <Wire.h>
#include 

Adafruit_PWMServoDriver servos = Adafruit_PWMServoDriver(0x40);

unsigned int pos0=172; // ancho de pulso en cuentas para pocicion 0°
unsigned int pos180=565; // ancho de pulso en cuentas para la pocicion 180°

void setup() {
  servos.begin();  
  servos.setPWMFreq(60); //Frecuecia PWM de 60Hz o T=16,66ms
}

void setServo(uint8_t n_servo, int angulo) {
  int duty;
  duty=map(angulo,0,180,pos0, pos180);
  servos.setPWM(n_servo, 0, duty);  
}

void loop() {
  
    setServo(0,30);
    setServo(2,90);
    setServo(4,180);
    setServo(6,120);
    setServo(8,0);
    setServo(10,30);
    setServo(12,90);
    setServo(14,170);
    delay(1000);
    setServo(1,30);
    setServo(3,90);
    setServo(5,180);
    setServo(7,120);
    setServo(9,30);
    setServo(11,90);
    setServo(13,180);
    setServo(15,120);
    delay(1000);
    setServo(0,120);
    setServo(2,180);
    setServo(4,90);
    setServo(6,60);
    setServo(8,45);
    setServo(10,160);
    setServo(12,170);
    setServo(14,30);
    delay(1000);
    setServo(1,120);
    setServo(3,0);
    setServo(5,90);
    setServo(7,60);
    setServo(9,120);
    setServo(11,180);
    setServo(13,0);
    setServo(15,30);
    delay(1000);
    
}

Usando este ejemplo como base ya pueden realizar cualquier aplicación.

En el caso que usen diferentes tipos de servomotores con diferente rango del ancho de pulso; incluso siendo del mismo fabricante en sus modelos de servos los valores mínimo y máximo pueden variar, por ejemplo para algunos casos el ancho de pulso para la posición 0° puede ser 0.7ms, 1ms u otro valor, de igual forma para la posición 180°.

Para este caso se necesita tener en cuenta que si bien la señal PWM puede ser el mismo para todos los servos debemos de tener como referencia diferentes valores del rango del ancho de pulso. Esto lo hacemos haciendo las siguientes modificaciones en el código anterior:

Al declarar las posición 0 y 180, lo debemos hacer con valores independientes para los 16 servos:

unsigned int pos0[16]=  {172,172,172,246,246,172,246,200,200,150,160,172,172,172,200,246}; 
unsigned int pos180[16]={565,256,256,492,492,565,492,550,550,600,590,565,565,565,550,492}; 

Y en la función para mover el servo debemos de usar estos valores a la hora de convertir de ángulo a duty

void setServo(uint8_t n_servo, int angulo) {
  int duty;
  duty=map(angulo,0,180,pos0[n_servo], pos180[n_servo]);
  servos.setPWM(n_servo, 0, duty);  
}

También pueden modificar el valor 180 en caso quieran trabajar con valores de 0 a 255, valores con los que muchos traban puesto que ocupa un byte en la comunicación.

Pueden adquirir los materiales usados en este tutorial en nuestra tienda

Módulo Controlador de servos PCA9685

Arduino Uno R3

Servomotores


Comparte este Post

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Abrir chat
0

Tu carrito