Site icon AranaCorp

Utilisation d’un module PCA9685 avec Arduino

3.8
(6)

Le module PCA9685 est un contrôleur 16 canaux qui permet de piloter 16 sorties PWM via la communication I2C. Il permet entre autre de libérer des entrées sorties de votre microcontrôleur et piloter jusqu’à 16 LED ou servomoteurs (ou tout autre module prenant en entrée un signal PWM) à l’aide de deux broches (SCL et SDA) tout en conservant les broches de votre microcontrôleur pour d’autres modules comme des capteurs.

Prérequis: Piloter un servomoteur avec Arduino

Matériel

Principe de fonctionnement

Le module est basé sur le contrôleur PCA9685 qui permet de piloter des sorties PWM à l’aide de la communication I2C et d’une horloge intégrée. Ce module comporte 6 ponts permettant de sélectionner l’adresse de la carte et ansi de placer sur le même bus jusqu’à 62 contrôleurs pour un total de 992 servomoteurs (Adresses disponibles 0x40 à 0x7F).
Il permet de piloter des sorties PWM avec une fréquence ajustable et avec une résolution de 12 bits. Le module est compatible avec les microcontrôleurs 5V et 3.3V.

Schéma

Le module est muni d’un bus I2C et d’un entrée de puissance. Le bus I2C est branché comme suit:

N.B.: Dans le cas de plusieurs servomoteurs ou d’un servomoteur puissant, il faut brancher une alimentation externe à votre système sur les broches V+ et GND tout en s’assurant que les masses de l’alimentation et de l’Arduino sont reliées.

Code

Pour utiliser le module PCA9685, nous utilisons la librairie Adafruit_PWMServoDriver.h. Les largeurs de PWM généralement données en microsecondes sur une période de 20ms (50Hz) mais ces valeurs peuvent changer d’un servomoteur à l’autre et entre fournisseur. Il vous faudra modifier les valeurs du code pour les adapter à votre servomoteur.
Dans notre cas, nous utilisons le servomoteur MG90S dont les plages sont 400-2400µs sur 20ms.

Pour définir la commande PWM, la librairie présente deux fonctions setPWM() et writeMicroseconds(). La fonction writeMicroseconds() nous permet d’utiliser les valeurs constructeur directement. Pour la fonction setPWM, il nous faut trouver la largeur d’impulsion correspondante sur 4096 (2^12, 12bits).

Exemple: La fréquence est de 50Hz donc une période de 20ms soit 20000µs.

Ce qui nous donne l’équivalence suivante:

A vous d’utiliser la fonction qui vous arrange le plus.

//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;
}

Applications

Sources

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

How useful was this post?

Click on a star to rate it!

Average rating 3.8 / 5. Vote count: 6

No votes so far! Be the first to rate this post.

Quitter la version mobile