Tutoriel · Intermédiaire · 18 min de lecture

Piloter des servomoteurs avec le PCA9685 (pilote PWM I2C)

Comment piloter de nombreux servos avec un PCA9685 en I2C : fréquence PWM, angle converti en impulsion étalonnée, et alimentation sûre des servos.

Un microcontrôleur ne possède qu’une poignée de canaux PWM matériels. C’est suffisant pour un ou deux servomoteurs, mais un bras robotique en a quatre, un hexapode dix-huit, et l’Arduino épuise ses minuteries bien avant que vous manquiez d’articulations. Le PCA9685 résout cela : une petite carte génère seize signaux PWM indépendants en matériel, et vous les commandez tous via deux seuls fils I2C. C’est ainsi qu’on pilote chaque articulation du simulateur de bras robotique sur du matériel réel.

Schéma légendé d'une carte pilote PWM/servomoteurs 16 canaux PCA9685 : seize connecteurs trois broches en haut, la puce PCA9685 au centre, un connecteur de commande I2C cinq broches à gauche, des cavaliers d'adresse à souder, et un bornier V+ pour l'alimentation des servomoteurs à droite.
Seize canaux PWM en matériel, pilotés via deux broches I2C ; le courant des servomoteurs vient du bornier V+ séparé, jamais du microcontrôleur. Télécharger le SVG

Pourquoi ne pas câbler les servomoteurs à l’Arduino ?

Deux raisons. D’abord, les broches : l’Uno a assez de minuteries pour quelques objets Servo avant que la bibliothèque ne se batte avec elle-même. Ensuite, et surtout, la puissance : un servomoteur peut appeler 500–700 mA au blocage, et quatre en mouvement ensemble peuvent appeler plusieurs ampères. Ce courant ne peut pas venir de la broche 5 V de l’Arduino — il fait chuter la carte et la redémarre en plein mouvement. Le PCA9685 corrige les deux. Il décharge la génération PWM sur une puce dédiée, et il achemine le courant des servomoteurs depuis son propre bornier V+, en tenant le courant fort à l’écart de votre logique.

Régler la fréquence PWM

Chaque servomoteur amateur attend un signal de commande à 50 Hz — une impulsion toutes les 20 ms. Le PCA9685 règle une fréquence pour toute la puce, on la règle donc une fois dans setup() :

#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);  // default I²C address

void setup() {
  pwm.begin();
  pwm.setPWMFreq(50);   // 50 Hz — the standard servo refresh rate
}

Les seize canaux pulsent désormais à 50 Hz. L’angle tenu par chaque servomoteur est fixé par la largeur de son impulsion, pas la fréquence — c’est la partie que vous réglez par canal.

Angle vers largeur d’impulsion — l’étalonnage qui compte

Un servomoteur lit la largeur d’impulsion comme une commande de position : environ 1 ms pour 0°, 1,5 ms au centre, 2 ms pour 180°, répétée 50 fois par seconde. C’est le même code largeur-d’impulsion-vers-angle qu’utilise le SG90 ; le PCA9685 le génère simplement en matériel.

Schéma de commande du servomoteur : un signal PWM à 50 Hz dont la largeur d'impulsion fixe l'angle. Une impulsion d'une milliseconde commande 0 degré, une milliseconde et demie commande 90 degrés, et deux millisecondes commandent 180 degrés, montrés sur des cadrans de rapporteur.
Le servomoteur lit la largeur d'impulsion, pas la tension : 1 ms vaut 0°, 1,5 ms le centre, 2 ms toute la course — répété 50 fois par seconde. Télécharger le SVG

Le PCA9685 ne prend pas directement des millisecondes. Il découpe chaque période de 20 ms en 4096 pas (résolution 12 bits) et vous lui dites pendant combien de pas l’impulsion reste haute. À 50 Hz, une période complète vaut 4096 pas = 20 ms, donc :

  • 1 ms ≈ 205 pas (0°)
  • 1,5 ms ≈ 307 pas (90°)
  • 2 ms ≈ 410 pas (180°)

Ce sont les nombres nominaux. Les vrais servomoteurs varient — le même SG90 peut buter en bas à 130 et en haut à 490. C’est le seul nombre à étalonner. Stockez un min et un max par servomoteur et mappez votre angle dans cette plage :

// Calibrate these two per servo by eye — see "Gotchas" below.
const int SERVO_MIN = 130;   // counts at the servo's 0° hard stop
const int SERVO_MAX = 490;   // counts at the servo's 180° hard stop

int angleToCount(int deg) {
  return map(deg, 0, 180, SERVO_MIN, SERVO_MAX);
}

Sauter l’étalonnage explique qu’une commande « 90° » tombe à 78° sur une articulation et 96° sur une autre — et pourquoi un bras construit sur des servomoteurs non étalonnés n’atteint jamais tout à fait la pose demandée par le solveur de cinématique inverse.

Câblage : deux rails d’alimentation, une masse

  • Logique — VCC, GND, SDA, SCL depuis l’Arduino. Cela alimente uniquement la puce.
  • Puissance servomoteurs — une alimentation 5–6 V séparée vers le bornier V+, dimensionnée pour le courant de blocage de tous les servomoteurs à la fois, pas leur consommation à vide.
  • Masse commune — la masse de l’alimentation et celle de l’Arduino doivent être reliées, sinon le signal PWM n’a aucune référence et les servomoteurs tremblent ou vous ignorent. Il en va de même pour les lignes I2C portant les commandes.

Ajoutez un condensateur aux bornes de V+ pour absorber la pointe de courant au démarrage des servomoteurs ; la carte PCA9685 prévoit un emplacement pour cela.

Le code : bouger une articulation

#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

const int SERVO_MIN = 130;
const int SERVO_MAX = 490;

int angleToCount(int deg) {
  return map(deg, 0, 180, SERVO_MIN, SERVO_MAX);
}

void setServo(uint8_t channel, int deg) {
  pwm.setPWM(channel, 0, angleToCount(deg));  // on at count 0, off at the angle count
}

void setup() {
  pwm.begin();
  pwm.setPWMFreq(50);
  setServo(0, 90);   // base to centre
  setServo(1, 45);   // shoulder
  setServo(2, 120);  // elbow
  setServo(3, 10);   // gripper open
}

void loop() {}

Chaque setPWM(channel, 0, count) signifie « active ce canal au début de la période et coupe après count pas ». Balayez une articulation en avançant l’angle pas à pas dans une boucle avec un court delay() entre les pas, pour que le servomoteur ait le temps de bouger au lieu de claquer.

Pièges

  • Étalonnez SERVO_MIN / SERVO_MAX par servomoteur. Commandez 0°, notez où se trouve vraiment le palonnier, et ajustez le nombre jusqu’à correspondance. Faites de même à 180°. Dix minutes ici économisent toutes les poses en aval.
  • Ne pilotez jamais V+ depuis l’Arduino. Un servomoteur pourrait y survivre ; quatre feront chuter la carte et la redémarrer.
  • Dimensionnez l’alimentation pour le blocage, pas le vide. Une alimentation sous-dimensionnée s’affaisse quand plusieurs servomoteurs bougent ensemble, et toute la carte tremble.
  • Vérifiez l’adresse. Le défaut est 0x40. Pontez les cavaliers à souder pour chaîner les cartes, et passez la nouvelle adresse au constructeur.
  • Bougez doucement. Avancer vers une cible par pas vaut mieux que claquer dessus — cela réduit la pointe de courant et ménage les pignons en plastique.
  • Le canal de pince est celui qui chauffe. Toute autre articulation atteint son angle puis se repose ; une pince tenant un objet est un servomoteur bloqué contre lui, appelant environ un demi-ampère en continu. Ouvrez-la dès que la pièce est posée, et voyez force, blocage et souplesse de pince à servomoteur pour comprendre pourquoi une meilleure résolution PWM n’achète pas une meilleure force.

Une fois que chaque articulation répond à un angle, le bras est prêt pour la géométrie : transformer un point cible en angles articulaires qui l’atteignent, ce qui est exactement l’objet de la cinématique inverse d’un bras à deux segments et du simulateur de bras robotique.

Explorer le graphe

Fait partie de ces réalisations

Les projets et parcours d'apprentissage qui incluent ce tutoriel.

Pour aller plus loin

Références