Dieses Tutorial ist Teil von: Ansteuerung von 16 oder 32 Servomotoren mit PCA9685
Diese Sammlung von Tutorials mit Videos hilft Ihnen, 32 oder mehr Servomotoren mit Arduino UNO, Nano, Mini oder ESP32 zu steuern. Alle Codes sind enthalten.
Steuere 32 Servos über Wi-Fi mit ESP32 und PCA9685 über Desktop oder Mobiltelefon V5
In diesem Tutorial lernen wir, wie man 32 Servomotoren mit dem PCA9685 PWM-Controller-Modul steuert, das über Wi-Fi mit dem ESP32 verbunden ist. Diese Einrichtung ermöglicht es Ihnen, jeden Servomotor einzeln oder alle auf einmal über eine Weboberfläche zu steuern, die von einem Desktop- oder mobilen Gerät aus zugänglich ist. Am Ende dieses Leitfadens werden Sie ein voll funktionsfähiges System haben, das in der Lage ist, mehrere Servos mühelos zu verwalten.

Das PCA9685-Modul bietet eine einfache Möglichkeit, mehrere Servos mit PWM-Signalen zu steuern, während der ESP32 die Wi-Fi-Kommunikation und die Funktionen des Webservers übernimmt. Sie können den Winkel jedes Servomotors über eine benutzerfreundliche Oberfläche anpassen, die Schaltflächen für jeden Servo anzeigt. Für visuelle Referenz sollten Sie sich das Video (im Video bei :00) ansehen.
Hardware erklärt
Dieses Projekt verwendet hauptsächlich den ESP32-Mikrocontroller und den PCA9685-PWM-Controller. Der ESP32 ist ein leistungsstarker Mikrocontroller mit integrierten WLAN-Funktionen, was ihn ideal für IoT-Projekte macht. Der PCA9685 ist ein 16-Kanal-PWM-Controller, der kaskadiert werden kann, um bis zu 64 Servos zu steuern. Er kommuniziert mit dem ESP32 über das I2C-Protokoll, was es ermöglicht, mehrere Controller anzuschließen und individuell anzusprechen.
Jedes PCA9685-Modul hat eine Standard-I2C-Adresse von 0x40. Wenn mehrere Module verwendet werden, können Sie deren Adressen durch Löten bestimmter Jumper ändern. Zum Beispiel kann das erste Modul auf 0x40, das zweite auf 0x41 usw. eingestellt werden. Diese Kaskadierungsfähigkeit ermöglicht die Steuerung vieler Servos, ohne zusätzliche Pins am ESP32 zu benötigen.
Wie im obigen Bild gezeigt, stellen Sie sicher, dass Sie diesen Pfad für die PCA9685-Platine 2 (links) löten, um die I2C-Adresse so einzustellen, dass sie sich von der Platine 1 (rechts) unterscheidet.
Datenblattdetails
| Hersteller | Adafruit |
|---|---|
| Teilenummer | PCA9685 |
| Logik/IO-Spannung | 2,3 V bis 5,5 V |
| Versorgungsspannung | 2,3 V bis 5,5 V |
| Ausgangsstrom (pro Kanal) | 25 mA |
| Spitzenstrom (pro Kanal) | 100 mA |
| PWM-Frequenzanleitung | 40 Hz bis 1000 Hz |
| Eingabelogik-Schwellenwerte | 0,3 Vcc (niedrig) / 0,7 Vcc (hoch) |
| Spannungsabfall / RDS(on)/ Sättigung | 0,5 V max |
| Thermische Grenzen | 125 °C max |
| Paket | TSSOP-28 |
| Hinweise / Varianten | Bis zu 64 Servos mit Kaskadierung |
- Stellen Sie eine ordnungsgemäße Stromversorgung sicher (5V, 2A empfohlen).
- Verwenden Sie bei Bedarf Pull-up-Widerstände an den SDA- und SCL-Leitungen.
- Überprüfen Sie die I2C-Adressen sorgfältig, wenn Sie mehrere PCA9685-Module verwenden.
- Berücksichtigen Sie eine Wärmeableitung für Hochleistungsanwendungen.
- Testen Sie die Servos einzeln, um den korrekten Betrieb sicherzustellen.
Übliche I2C-Pin-Zuordnungen:SDA= GPIO 21,SCL= GPIO 22.
Verdrahtungsanweisungen

Um den PCA9685 und ESP32 zu verdrahten, beginnen Sie mit dem Anschließen von Stromversorgung und Erde. Schließen Sie den positiven Anschluss (V+) des PCA9685 an den 5V-Ausgang Ihres Netzteils. Verbinden Sie die Masse (GND) des PCA9685 mit der Masse des ESP32. Stellen Sie sicher, dass beide Geräte eine gemeinsame Masse haben.
Verbinden Sie als Nächstes für die I2C-Kommunikation den SDA-Pin des PCA9685 mit GPIO 21 des ESP32 und den SCL-Pin mit GPIO 22. Wenn Sie mehrere PCA9685-Module verwenden, stellen Sie sicher, dass sie entsprechend adressiert sind, indem Sie den A0-Jumper löten, um die Adresse des zweiten Moduls auf 0x41 zu ändern, und so weiter. Danach können Sie die Servomotoren nach Bedarf an die PWM-Ausgangs-Pins des PCA9685 anschließen.
Code-Beispiele & Durchlauf
Der Code beginnt mit dem Einfügen notwendiger Bibliotheken und der Initialisierung von zwei PCA9685-Boards. Die Bezeichner wiemaximumServoundservoAngledefiniere die Anzahl der Servos und den aktuellen Winkel.
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // how many servos are connectedDieser Auszug zeigt die Initialisierung der PCA9685-Objekte mit ihren jeweiligen Adressen. Die VariablemaximumServolegt die Gesamtzahl der Servos fest, die gesteuert werden können.
In dersetup()Die Funktion, die Platinen werden initialisiert und die Wi-Fi-Verbindung wird hergestellt. Die Anfangsposition aller Servos wird mit einer Schleife eingestellt.
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]));
}
}
}Dieser Code konfiguriert die PCA9685-Boards und setzt die PWM-Frequenz. Er initialisiert alle Servos auf ihre Ausgangspositionen, die in derallServoPositionArray.
Schließlich verarbeitet die Hauptschleife eingehende Client-Anfragen, um die Servos basierend auf Benutzereingaben zu steuern.
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;
}Diese Schleife verarbeitet kontinuierlich Client-Anfragen und aktualisiert die Servopositionen basierend auf dem gedrückten Knopf. Die VariablebuttonPushedwird nach jeder Aktion zurückgesetzt, um eine ordnungsgemäße Steuerung zu gewährleisten.
Für den vollständigen Code verweisen Sie bitte auf den Abschnitt unter dem Artikel.
Demonstration / Was zu erwarten ist
Sobald alles eingerichtet ist, sollten Sie in der Lage sein, jeden Servomotor einzeln oder alle auf einmal über eine Weboberfläche zu steuern. Sie können die Winkel der Servomotoren anpassen, indem Sie auf die Schaltflächen klicken, die jedem Servomotor auf Ihrem Gerät entsprechen. Das System sollte schnell reagieren, aber bedenken Sie, dass Leistungsgrenzen die Leistung beeinträchtigen können (im Video um 14:30).
Häufige Fallstricke sind die korrekte Zuordnung der I2C-Adressen und die ausreichende Stromversorgung der Servos. Wenn die Servos nicht reagieren, überprüfen Sie Ihre Verkabelung und Anschlüsse erneut.
Video-Zeitstempel
- 00:00 Start
- 01:19 Einführung
- 02:32 I2C-Adresse einstellen
- 05:07 Verdrahtung erklärt
- 07:44 Vorbereitung der Arduino IDE für ESP32
- 09:53 Arduino-Code erklärt
- 25:49 Demonstration auf dem Desktop
- 31:52 Demonstration auf dem Mobiltelefon
Dieses Tutorial ist Teil von: Ansteuerung von 16 oder 32 Servomotoren mit PCA9685
- Arduino-Code und Video für PCA9685 16-Kanal 12-Bit Servo-Controller V1
- Steuere 16 Servomotoren mit einem PCA9685-Modul und Arduino V2 Sketch #1: Eins nach dem anderen
- Steuerung von 16 Servomotoren mit einem PCA9685-Modul und Arduino V2-Sketch: Individuelle Servosteuerung
- Controlling 16 Servo Motors Using a PCA9685 Module and Arduino V2 Sketch #3: All Servos Together
- Steuerung eines 32 Servo Motors mit einem PCA9685 Modul und Arduino V3 Sketch #1: Alle Servos zusammen
- Steuerung eines 32 Servo-Motors mit einem PCA9685-Modul und einem ESP32 V4
/*
* Ursprüngliche PCA9685 Modulbibliotheksquelle: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
*
* Dies ist der Arduino-Code PCA6985 32-Kanal Servosteuerung
* zur Steuerung von 32 Servomotoren über WiFi mit dem ESP32 MCU.
* Holen Sie sich diesen Code und die Verdrahtung für dieses Video: http://robojax.com/RJT365
*
* Video zu diesem Code ansehen: https://youtu.be/bvqfv-FrrLM
*
* Verwandte Videos
* V4 Video von PCA9685 32 Servos mit ESP32: https://youtu.be/JFdXB8Za5Os
* V3 Video von PCA9685 wie man 32 Servomotoren steuert https://youtu.be/6P21wG7N6t4
* V2 Video von PCA9685 3 verschiedenen Möglichkeiten zur Steuerung von Servomotoren: https://youtu.be/bal2STaoQ1M
* V1 Video Einführung in PCA9685 zur Steuerung von 16 Servos https://youtu.be/y8X9X10Tn1k
*
* Geschrieben von Ahmad Shamshiri für den Robojax Video-Kanal www.Robojax.com
* Datum: 17. Februar 2020, in Ajax, Ontario, Kanada
*
* oder machen Sie eine Spende über PayPal http://robojax.com/L/?id=64
*
* Dieser Code ist "WIE BESEHEN" ohne Gewährleistung oder Haftung. Kostenfrei zu verwenden, solange Sie diese Notiz unverändert lassen.*
* Dieser Code wurde von Robojax.com heruntergeladen.
* Dieses Programm ist freie Software: Sie können es weitergeben und/oder ändern
* unter den Bedingungen der GNU General Public License, die von
* der Free Software Foundation veröffentlicht wurde, entweder Version 3 der Lizenz oder
* (nach Ihrer Wahl) jede spätere Version.
*
* Dieses Programm wird in der Hoffnung verbreitet, dass es nützlich sein wird,
* aber OHNE IRGENDEINE GARANTIE; nicht einmal die implizierte Garantie der
* MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. Siehe die
* GNU General Public License für weitere Details.
*
* Sie sollten eine Kopie der GNU General Public License
* zusammen mit diesem Programm erhalten haben. Wenn nicht, siehe <https://www.gnu.org/licenses/>.
* /
* ////////////////////// PCA9685-Einstellungen gestartet
*/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// so genannt, verwendet es die Standardadresse 0x40
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // Wie viele Servos sind angeschlossen?
// Je nach Ihrem Servomotor-Hersteller können die minimalen und maximalen Pulsweiten variieren, Sie
// möchte, dass diese so klein/groß wie möglich sind, ohne die harte Grenze zu erreichen
// für maximale Reichweite. Du musst sie nach Bedarf anpassen, um zu den Servos zu passen, die du
// haben!
// Sehen Sie sich Video V1 an, um die beiden Zeilen unten zu verstehen: http://youtu.be/y8X9X10Tn1k
#define SERVOMIN 125 // dies ist die 'Mindest'-Pulslängenanzahl (von 4096)
#define SERVOMAX 575 // dies ist die 'maximale' Pulsdaueranzahl (von 4096)
int servoAngle =0;
int servoStep = 10;
int stepDelay = 50; // 50 Millisekunden
int servoAngleMin =0;
int servoAngleMax = 180;
// Mindestwinkel jedes Servos
int allServoMin[]={
0, 0, 0, 0, 0, 0, 0, 0, // 1 bis 8
0, 0, 0, 0, 0, 0, 0, 0, // 9 bis 16
0, 0, 0, 0, 0, 0, 0, 0, // 17 bis 24
0, 0, 0, 0, 0, 0, 0, 0}; // 25 bis 32
// maximaler Wert jedes Servos
int allServoMax[]={
180, 180, 180, 180, 180, 180, 180, 180, // 1 bis 8
180, 180, 180, 180, 180, 180, 180, 180, // 9 bis 16
180, 180, 180, 180, 180, 180, 180, 180, // 17 bis 24
180, 180, 180, 180, 180, 180, 180, 180}; // 25 bis 32
// Ursprungsposition der Servos
int allServoPosition[] ={
0, 0, 0, 0, 0, 0, 0, 0, // 1 bis 8
0, 0, 0, 0, 0, 0, 0, 0, // 9 bis 16
0, 0, 0, 0, 0, 0, 0, 0, // 17 bis 24
0, 0, 0, 0, 0, 0, 0, 0}; // 25 bis 32
int servoNumber = 100; // Servo bewegen
int buttonPushed =0;
int allServo =0;
void handleServo(); // dies ist der Prototyp einer Funktion, die am Ende dieses Codes definiert ist
int angleToPulse(int ang); // dies ist der Prototyp einer Funktion, die am Ende dieses Codes definiert ist
// PCA9685 beendet
#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); // Analoge Servos arbeiten mit ~60 Hz Aktualisierungen.
board2.setPWMFreq(60);
// anfängliche Position aller 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]) );
}
} // für Ende
Serial.begin(115200);
Serial.println("32 channel Servo test!");
// Servo-Steuerung mit ESP32 von Robojax.com
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Warten auf Verbindung
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 32-Kanal Servosteuerung
delay(100);
} // wenn gedrückt
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()
* aktualisiere die Variable buttonPushed
* gibt nichts zurück
* Geschrieben von Ahmad Shamshiri am 29. Dezember 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() Ende
/*
* angleToPulse(int ang)
* nimmt den Winkel in Grad und gibt die Pulsbreite zurück
* druckt auch den Wert auf dem seriellen Monitor aus
* geschrieben von Ahmad Shamshiri für Robojax, Robojax.com
*/
int angleToPulse(int ang){
int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX); // Karte den Winkel von 0 bis 180 auf Servo min und Servo max.
// Serial.print("Winkel: ");Serial.print(ang);
// Serial.print(" Puls: ");Serial.println(pulse);
return pulse;
}
Dinge, die Sie vielleicht brauchen
-
AmazonKaufe PCA9685 bei Amazonamzn.to
-
AmazonServomotor auf Amazonamzn.to
-
eBayPCA9685 bei eBay kaufenebay.us
-
AliExpressKaufen Sie den SG90 Servomotor 180 oder 360 von AliExpresss.click.aliexpress.com
-
AliExpressPCA9685 bei AliExpress kaufens.click.aliexpress.com
-
BanggoodKaufen Sie PCA9685 bei Bangoodbanggood.com
Ressourcen & Referenzen
-
ExternPAC9685 Bibliothek (von GitHub)github.com
Dateien📁
Keine Dateien verfügbar.