Ce tutoriel fait partie de: Commande de 16 ou 32 servomoteurs avec PCA9685
Cette collection de tutoriels vidéo vous aide à contrôler 32 servomoteurs ou plus à l'aide d'Arduino UNO, Nano, Mini ou ESP32. Tous les codes sont fournis.
Contrôlez 32 servomoteurs via Wi-Fi en utilisant ESP32 et PCA9685 depuis un ordinateur de bureau ou un téléphone mobile V5
Dans ce tutoriel, nous allons apprendre comment contrôler 32 servomoteurs en utilisant le module de contrôle PWM PCA9685 connecté à l'ESP32 via Wi-Fi. Cette configuration vous permet de contrôler chaque servomoteur individuellement ou tous en même temps via une interface web accessible depuis un ordinateur de bureau ou un appareil mobile. À la fin de ce guide, vous disposerez d'un système pleinement fonctionnel capable de gérer plusieurs servos avec facilité.

Le module PCA9685 offre un moyen simple de contrôler plusieurs servomoteurs à l'aide de signaux PWM, tandis que l'ESP32 gère la communication Wi-Fi et les fonctionnalités du serveur web. Vous pourrez ajuster l'angle de chaque servomoteur grâce à une interface conviviale qui affiche des boutons pour chaque servomoteur. Pour une référence visuelle, n'oubliez pas de consulter la vidéo (dans la vidéo à :00).
Matériel Expliqué
Ce projet utilise principalement le microcontrôleur ESP32 et le contrôleur PWM PCA9685. L'ESP32 est un microcontrôleur puissant avec des capacités Wi-Fi intégrées, ce qui le rend idéal pour les projets IoT. Le PCA9685 est un contrôleur PWM à 16 canaux qui peut être mis en cascade pour contrôler jusqu'à 64 servos. Il communique avec l'ESP32 via le protocole I2C, permettant de connecter plusieurs contrôleurs et de les adresser individuellement.
Chaque module PCA9685 a une adresse I2C par défaut de 0x40. Lors de l'utilisation de plusieurs modules, vous pouvez changer leurs adresses en soudant des cavaliers spécifiques. Par exemple, le premier module peut être à 0x40, le second à 0x41, et ainsi de suite. Cette capacité de chaînage permet de contrôler de nombreux servomoteurs sans avoir besoin de broches supplémentaires sur l'ESP32.
Comme montré dans l'image ci-dessus, pour la carte PCA9685 2 (à gauche), assurez-vous de souder ce chemin pour définir l'adresse I2C afin qu'elle soit différente de celle de la carte 1 (à droite).
Détails de la fiche technique
| Fabricant | Adafruit |
|---|---|
| Numéro de pièce | PCA9685 |
| Tension logique/IO | 2,3 V à 5,5 V |
| Tension d'alimentation | 2.3 V à 5.5 V |
| Courant de sortie (par canal) | 25 mA |
| Courant de crête (par canal) | 100 mA |
| Guide de fréquence PWM | 40 Hz à 1000 Hz |
| Seuils logiques d'entrée | 0,3 Vcc (bas) / 0,7 Vcc (haut) |
| Chute de tension / RDS(on)/ saturation | 0,5 V max |
| Limites thermiques | 125 °C max |
| Paquet | TSSOP-28 |
| Notes / variantes | Jusqu'à 64 servomoteurs en cascade |
- Assurez-vous d'une alimentation correcte (5V, 2A recommandée).
- Utilisez des résistances de tirage sur les lignes SDA et SCL si nécessaire.
- Vérifiez les adresses I2C avec soin lors de l'utilisation de plusieurs modules PCA9685.
- Considérez le dissipateur thermique pour les applications haute puissance.
- Testez les servos individuellement pour vous assurer de leur bon fonctionnement.
Mappings de broches I2C courants :SDA= GPIO 21,SCL= GPIO 22.
Instructions de câblage

Pour câbler le PCA9685 et l'ESP32, commencez par connecter l'alimentation et la masse. Connectez la borne positive (V+) du PCA9685 à la sortie 5V de votre alimentation. Connectez le ground (GND) du PCA9685 au ground de l'ESP32. Assurez-vous que les deux appareils partagent une mise à la terre commune.
Ensuite, pour la communication I2C, connectez la broche SDA du PCA9685 au GPIO 21 de l'ESP32 et la broche SCL au GPIO 22. Si vous utilisez plusieurs modules PCA9685, assurez-vous qu'ils sont correctement adressés en soudant le cavalier A0 pour changer l'adresse du deuxième module à 0x41, et ainsi de suite. Après cela, vous pouvez connecter les servomoteurs aux broches de sortie PWM du PCA9685 selon vos besoins.
Exemples de code et guide étape par étape
Le code commence par inclure les bibliothèques nécessaires et initialiser deux cartes PCA9685. Les identifiants tels quemaximumServoetservoAngledéfinir le nombre de servos et l'angle actuel, respectivement.
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // how many servos are connectedCet extrait montre l'initialisation des objets PCA9685 avec leurs adresses respectives. La variablemaximumServodéfinit le nombre total de servomoteurs qui peuvent être contrôlés.
Dans lesetup()fonction, les cartes sont initialisées et la connexion Wi-Fi est établie. La position initiale de tous les servomoteurs est définie à l'aide d'une boucle.
void setup() {
board1.begin();
board2.begin();
board1.setPWMFreq(60); // Analog servos run at ~60 Hz updates
board2.setPWMFreq(60);
//initial position of all servos
for(int i=0; i < maximumServo; i++) {
if(i < 16) {
board1.setPWM(i, 0, angleToPulse(allServoPosition[i]));
} else {
board2.setPWM(i-15, 0, angleToPulse(allServoPosition[i]));
}
}
}Ce code configure les cartes PCA9685 et définit la fréquence PWM. Il initialise tous les servos à leurs positions de départ, qui sont définies dans leallServoPositiontableau.
Enfin, la boucle principale gère les demandes des clients entrantes pour contrôler les servos en fonction des entrées de l'utilisateur.
void loop() {
server.handleClient();
if (buttonPushed && (servoNumber >= 0 && servoNumber < maximumServo)) {
if (servoNumber < 16) {
board1.setPWM(servoNumber, 0, angleToPulse(allServoPosition[servoNumber]));
} else {
board2.setPWM(servoNumber-15, 0, angleToPulse(allServoPosition[servoNumber]));
}
}
buttonPushed = 0;
}Cette boucle traite en continu les demandes des clients et met à jour les positions des servos en fonction du bouton pressé. La variablebuttonPushedest réinitialisé après chaque action pour garantir un contrôle adéquat.
Pour le code complet, veuillez vous référer à la section ci-dessous l'article.
Démonstration / À quoi s'attendre
Une fois que tout est configuré, vous devriez pouvoir contrôler chaque servo individuellement ou tous en même temps depuis une interface web. Vous pouvez ajuster les angles des servos en cliquant sur les boutons correspondants à chaque servo sur votre appareil. Le système devrait répondre rapidement, mais gardez à l'esprit que les limitations de puissance peuvent affecter les performances (dans la vidéo à 14:30).
Les pièges courants incluent s'assurer que les adresses I2C sont correctement attribuées et qu'une alimentation suffisante est fournie aux servos. Si les servos ne répondent pas, vérifiez à nouveau votre câblage et vos connexions.
Horodatages vidéo
- 00:00 Début
- 01:19 Introduction
- 02:32 Réglage de l'adresse I2C
- 05:07 Câblage expliqué
- 07:44 Préparation de l'IDE Arduino pour l'ESP32
- 09:53 Code Arduino expliqué
- 25:49 Démonstration sur bureau
- 31:52 Démonstration sur téléphone mobile
Ce tutoriel fait partie de: Commande de 16 ou 32 servomoteurs avec PCA9685
- Code Arduino et vidéo pour le contrôleur de servomoteurs PCA9685 16 canaux 12 bits V1
- Contrôlez 16 servomoteurs à l'aide d'un module PCA9685 et du croquis Arduino V2 #1 : Un par un
- Contrôler 16 moteurs servo à l'aide d'un module PCA9685 et d'un croquis Arduino V2 : Contrôle individuel des servos
- Controlling 16 Servo Motors Using a PCA9685 Module and Arduino V2 Sketch #3: All Servos Together
- Contrôler un moteur servo 32 en utilisant un module PCA9685 et un croquis Arduino V3 #1 : Tous les servos ensemble
- Contrôler un moteur servo 32 à l'aide d'un module PCA9685 et d'un ESP32 V4
/*
* Source de la bibliothèque originale du module PCA9685 : https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
*
* Voici le code Arduino pour le contrôleur de servo à 32 canaux PCA9685
* pour contrôler 32 moteurs servo via WiFi en utilisant un MCU ESP32.
* Obtenez ce code et le câblage pour cette vidéo : http://robojax.com/RJT365
*
* Regardez la vidéo pour ce code : https://youtu.be/bvqfv-FrrLM
*
* Vidéos associées
* Vidéo V4 du PCA9685 32 Servo avec ESP32 : https://youtu.be/JFdXB8Za5Os
* Vidéo V3 du PCA9685 comment contrôler 32 moteurs servo https://youtu.be/6P21wG7N6t4
* Vidéo V2 du PCA9685 3 manières différentes de contrôler des moteurs servo : https://youtu.be/bal2STaoQ1M
* Vidéo V1 introduction au PCA9685 pour contrôler 16 Servo https://youtu.be/y8X9X10Tn1k
*
* Écrit par Ahmad Shamshiri pour la chaîne vidéo Robojax www.Robojax.com
* Date : 17 février 2020, à Ajax, Ontario, Canada
*
* ou faites un don via PayPal http://robojax.com/L/?id=64
*
* Ce code est "EN L'ÉTAT" sans garantie ni responsabilité. Libre d'être utilisé tant que vous gardez cette note intacte.*
* Ce code a été téléchargé depuis Robojax.com
* Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier
* selon les termes de la Licence Publique Générale GNU telle que publiée par
* la Free Software Foundation, soit la version 3 de la Licence, ou
* (à votre choix) toute version ultérieure.
*
* Ce programme est distribué dans l'espoir qu'il sera utile,
* mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de
* COMMERCIALISATION ou D'ADAPTATION À UN USAGE PARTICULIER. Voir la
* Licence Publique Générale GNU pour plus de détails.
*
* Vous devriez avoir reçu une copie de la Licence Publique Générale GNU
* avec ce programme. Sinon, consultez <https://www.gnu.org/licenses/>.
* /
* ////////////////////// paramètres PCA9685 démarrés
*/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// s'appelant ainsi, il utilise l'adresse par défaut 0x40
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // combien de servos sont connectés
// Selon la marque de votre servo, la largeur d'impulsion minimale et maximale peut varier, vous
// je veux que ceux-ci soient aussi petits/grands que possible sans atteindre le point de non-retour
// pour une portée maximale. Vous devrez les ajuster si nécessaire pour correspondre aux servos que vous
// avoir !
// Regardez la vidéo V1 pour comprendre les deux lignes ci-dessous : http://youtu.be/y8X9X10Tn1k
#define SERVOMIN 125 // c'est le nombre de longueur d'impulsion 'minimum' (sur 4096)
#define SERVOMAX 575 // c'est le nombre de longueur de pulse 'maximum' (sur 4096)
int servoAngle =0;
int servoStep = 10;
int stepDelay = 50; // 50 millisecondes
int servoAngleMin =0;
int servoAngleMax = 180;
// angle minimum de chaque servomoteur
int allServoMin[]={
0, 0, 0, 0, 0, 0, 0, 0, // 1 à 8
0, 0, 0, 0, 0, 0, 0, 0, // 9 à 16
0, 0, 0, 0, 0, 0, 0, 0, // 17 à 24
0, 0, 0, 0, 0, 0, 0, 0}; // 25 à 32
// valeur maximale de chaque servo
int allServoMax[]={
180, 180, 180, 180, 180, 180, 180, 180, // 1 à 8
180, 180, 180, 180, 180, 180, 180, 180, // 9 à 16
180, 180, 180, 180, 180, 180, 180, 180, // 17 à 24
180, 180, 180, 180, 180, 180, 180, 180}; // 25 à 32
// position initiale des servos
int allServoPosition[] ={
0, 0, 0, 0, 0, 0, 0, 0, // 1 à 8
0, 0, 0, 0, 0, 0, 0, 0, // 9 à 16
0, 0, 0, 0, 0, 0, 0, 0, // 17 à 24
0, 0, 0, 0, 0, 0, 0, 0}; // 25 à 32
int servoNumber = 100; // servo à déplacer
int buttonPushed =0;
int allServo =0;
void handleServo(); // c'est le prototype de la fonction définie à la fin de ce code
int angleToPulse(int ang); // c'est le prototype de la fonction définie à la fin de ce code
// //////////////////////PCA9685 terminé
#include "PCA9684_32Servo_ESP32.h"
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
const char *ssid = "Robojax";
const char *password = "YouTube2020";
WebServer server(80);
const int led = 13;
// ///////////////////////////////////
void handleRoot() {
String HTML_page = pageHeader_p1;
if(allServo)
{
HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorAll\" href=\"/servo?do=stop\">Stop Servo</a></div>");
}else{
HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorAll\" href=\"/servo?do=all\">All Servo</a></div>");
}
for (int i=0; i < maximumServo; i++)
{
HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorBtn\" href=\"/servo?move=");
HTML_page.concat(i);
HTML_page.concat("\">SRV ");
HTML_page.concat(i+1);
HTML_page.concat(" </a></div>");
}
HTML_page.concat("</body>\n</html>");
server.send(200, "text/html", HTML_page);
}
void handleNotFound() {
digitalWrite(led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(led, 0);
}
void setup() {
board1.begin();
board2.begin();
board1.setPWMFreq(60); // Les servos analogiques fonctionnent avec des mises à jour d'environ 60 Hz.
board2.setPWMFreq(60);
// position initiale de tous les servos
for(int i=0; i < maximumServo; i++) {
if(i < 16)
{
board1.setPWM(i, 0, angleToPulse(allServoPosition[i]) );
}else{
board2.setPWM(i-15, 0, angleToPulse(allServoPosition[i]) );
}
} // pour la fin
Serial.begin(115200);
Serial.println("32 channel Servo test!");
// Contrôle de servomoteur avec ESP32 de Robojax.com
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Attendez la connexion
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("robojaxESP32")) {
Serial.print("MDNS responder started at http: // ");
Serial.println("robojaxESP32");
}
server.on("/", handleRoot);
server.on("/servo", HTTP_GET, handleServo);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
if(allServo ){
for( int angle =servoAngleMin; angle <= servoAngleMax; angle +=servoStep){
for(int i=0; i<16; i++)
{
board2.setPWM(i, 0, angleToPulse(angle) );
board1.setPWM(i, 0, angleToPulse(angle) );
}
delay(stepDelay);
}
// robojax PCA9865 contrôle de servomoteurs 32 canaux
delay(100);
} // si poussé
if(false){
Serial.print("Servo #");
Serial.print (servoNumber);
Serial.print(" Angle ");
Serial.println(allServoPosition[servoNumber]);
}
if( buttonPushed && (servoNumber >=0 && servoNumber < maximumServo) ){
if(servoNumber < 16)
{
board1.setPWM(servoNumber, 0, angleToPulse(allServoPosition[servoNumber]) );
}else{
board2.setPWM(servoNumber-15, 0, angleToPulse(allServoPosition[servoNumber]) );
}
}
buttonPushed =0;
}
/*
* handleServo()
* met à jour la variable buttonPushed
* ne retourne rien
* Écrit par Ahmad Shamshiri le 29 décembre 2019
* www.Robojax.com
* http://youTube.com/robojaxTV
*/
void handleServo() {
if(server.arg("do") == "all" )
{
allServo =1;
}else{
allServo =0;
}
int servoNumberRequested= server.arg("move").toInt();
if(servoNumberRequested >=0 && servoNumberRequested < maximumServo)
{
buttonPushed = 1;
if(allServoPosition[servoNumberRequested] == allServoMin[servoNumberRequested] ) {
allServoPosition[servoNumberRequested] = allServoMax[servoNumberRequested];
}else{
allServoPosition[servoNumberRequested] = allServoMin[servoNumberRequested];
}
servoNumber =servoNumberRequested;
}
handleRoot();
} // handleServo() fin
/*
* angleToPulse(int ang)
* obtient l'angle en degrés et renvoie la largeur d'impulsion
* imprime également la valeur sur le moniteur série
* écrit par Ahmad Shamshiri pour Robojax, Robojax.com
*/
int angleToPulse(int ang){
int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX); // mapper l'angle de 0 à 180 sur Servo min et Servo max
// Angle : ;Serial.print(ang);
// Serial.print(" impulsion : ");Serial.println(pulse);
return pulse;
}
Ce dont vous pourriez avoir besoin
-
AmazonAcheter le PCA9685 sur Amazonamzn.to
-
AmazonMoteur servo sur Amazonamzn.to
-
eBayAchetez le PCA9685 sur eBayebay.us
-
AliExpressAcheter PCA9685 sur AliExpresss.click.aliexpress.com
-
AliExpressAchetez le moteur servo SG90 180 ou 360 sur AliExpress.s.click.aliexpress.com
-
BanggoodAcheter PCA9685 sur Bangoodbanggood.com
Ressources et références
-
ExterneBibliothèque PAC9685 (de GitHub)github.com
Fichiers📁
Aucun fichier disponible.