fbpixel
Etiquetas: , , , ,
5
(2)

El módulo PCA9685 es un controlador de 16 canales que puede controlar 16 salidas PWM a través de la comunicación I2C. Permite, entre otras cosas, liberar las entradas y salidas de su microcontrolador y manejar hasta 16 LEDs o servomotores (o cualquier otro módulo que tome una señal PWM como entrada) usando dos pines (SCL y SDA) mientras mantiene los pines de su microcontrolador para otros módulos como los sensores.

Prerrequisitos: Conducir un servomotor con Arduino

Hardware

  • Computadora
  • ArduinoUNO
  • USB A Macho a B Cable macho
  • PCA9685Módulo

Principio de funcionamiento

El módulo se basa en el controlador PCA9685, que permite controlar las salidas PWM mediante la comunicación I2C y un reloj integrado. Este módulo tiene 6 puentes para seleccionar la dirección de la placa y para colocar en el mismo bus hasta 62 controladores para un total de 992 actuadores (direcciones disponibles 0x40 a 0x7F).
Puede manejar salidas PWM con frecuencia ajustable y resolución de 12 bits. El módulo es compatible con microcontroladores de 5V y 3.3V.

Diagrama

El módulo está equipado con un bus I2C y una entrada de energía. El bus I2C está conectado de la siguiente manera:

  • Pin A5 o SCL al pin SCL del módulo
  • Pin A4 o SDA al pin SDA del módulo
  • Pin 5V al pin Vcc del módulo
  • Pin GND al pin GND del módulo En este tutorial usamos la placa Arduino UNO pero puede ser adaptada a otros microcontroladores. Para ello, sólo hay que adaptar los pines de I2C disponibles en el microcontrolador en cuestión y posiblemente el código.

Código

Para usar el módulo PCA9685, usamos la biblioteca Adafruit_PWMServoDriver.h. Los anchos de los PWM suelen darse en microsegundos durante un período de 20ms (50Hz), pero estos valores pueden cambiar de un actuador a otro y entre proveedores. Tendrá que modificar los valores del código para adaptarlos a su actuador.
En nuestro caso, utilizamos el actuador MG90S cuyos rangos son de 400-2400µs sobre 20ms.

Para establecer el comando PWM, la biblioteca proporciona dos funciones: setPWM() y writeMicroseconds(). La función writeMicroseconds() nos permite usar los valores del constructor directamente. Para la función setPWM, necesitamos encontrar el ancho de pulso correspondiente en el 4096 (2^12, 12bits).

Ejemplo: La frecuencia es de 50Hz por lo que un período de 20ms o 20000µs.
pwmvalmin=400/200004096=81.92-> 90 redondeo con un margen de seguridad pwmvalmax=2400/200004096=491.52 -> 480 redondeo con un margen de seguridad


Lo que nos da la siguiente equivalencia:
pca.writeMicrosegundos(i,400) es igual a pca.setPwm(i,0,90)
y pca.writeMicrosegundos(i,2400) es igual a pca.setPwm(i,0,480)
Depende de ti usar la función que más te convenga.

//Libraries
#include <Wire.h>//https://www.arduino.cc/en/reference/wire
#include <Adafruit_PWMServoDriver.h>//https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
//Constants
#define nbPCAServo 16
//Parameters
int MIN_IMP [nbPCAServo] ={500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500};
int MAX_IMP [nbPCAServo] ={2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500};
int MIN_ANG [nbPCAServo] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int MAX_ANG [nbPCAServo] ={180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180};
//Objects
Adafruit_PWMServoDriver pca= Adafruit_PWMServoDriver(0x40);
void setup(){
//Init Serial USB
Serial.begin(9600);
Serial.println(F("Initialize System"));
pca.begin();
pca.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
}
void loop(){
 pcaScenario();
}
void pcaScenario(){/* function pcaScenario */ 
////Scenario to test servomotors controlled by PCA9685 I2C Module
for (int i=0; i<nbPCAServo; i++) {
 Serial.print("Servo");
 Serial.println(i);
     //int middleVal=((MAX_IMP[i]+MIN_IMP[i])/2)/20000*4096; // conversion µs to pwmval
     //pca.setPWM(i,0,middleVal);
     for(int pos=(MAX_IMP[i]+MIN_IMP[i])/2;pos<MAX_IMP[i];pos+=10){
       pca.writeMicroseconds(i,pos);delay(10);
     }
     for(int pos=MAX_IMP[i];pos>MIN_IMP[i];pos-=10){
       pca.writeMicroseconds(i,pos);delay(10);
     }
     for(int pos=MIN_IMP[i];pos<(MAX_IMP[i]+MIN_IMP[i])/2;pos+=10){
       pca.writeMicroseconds(i,pos);delay(10);
     }
     pca.setPin(i,0,true); // deactivate pin i
   }
}
int jointToImp(double x,int i){/* function jointToImp */ 
////Convert joint angle into pwm command value
    
     int imp=(x - MIN_ANG[i]) * (MAX_IMP[i]-MIN_IMP[i]) / (MAX_ANG[i]-MIN_ANG[i]) + MIN_IMP[i];
     imp=max(imp,MIN_IMP[i]);
     imp=min(imp,MAX_IMP[i]);
     
return imp;
}

Aplicaciones

  • Control del robot Quadrina6

Fuentes

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuarlo!

Promedio de puntuación 5 / 5. Recuento de votos: 2

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en los medios sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?