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
/*
* Original PCA9685 Module library source: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
*
* This is the Arduino code PCA6985 32 channel servo controller
* to control 32 Servo Motors over WiFi using ESP32 MCU
* get this code and wiring from for this video: http://robojax.com/RJT365
* Watch video for this code: https://youtu.be/bvqfv-FrrLM
*
* Related Videos
V4 video of PCA9685 32 Servo with ESP32: https://youtu.be/JFdXB8Za5Os
V3 video of PCA9685 how to control 32 Servo motors https://youtu.be/6P21wG7N6t4
V2 Video of PCA9685 3 different ways to control Servo motors: https://youtu.be/bal2STaoQ1M
V1 Video introduction to PCA9685 to control 16 Servo https://youtu.be/y8X9X10Tn1k
*
* Written by Ahmad Shamshiri for Robojax Video channel www.Robojax.com
* Date: Feb 17, 2020, in Ajax, Ontario, Canada
or make donation using PayPal http://robojax.com/L/?id=64
* * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.*
* This code has been download from Robojax.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
////////////////////// PCA9685 settings started
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32;//how many servos are connected
// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
// Watch video V1 to understand the two lines below: http://youtu.be/y8X9X10Tn1k
#define SERVOMIN 125 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 575 // this is the 'maximum' pulse length count (out of 4096)
int servoAngle =0;
int servoStep = 10;
int stepDelay = 50;// 50 milliseconds
int servoAngleMin =0;
int servoAngleMax = 180;
// minimum angle of each servo
int allServoMin[]={
0, 0, 0, 0, 0, 0, 0, 0,// 1 to 8
0, 0, 0, 0, 0, 0, 0, 0,//9 to 16
0, 0, 0, 0, 0, 0, 0, 0,//17 to 24
0, 0, 0, 0, 0, 0, 0, 0};//25 to 32
//maximum value of each servo
int allServoMax[]={
180, 180, 180, 180, 180, 180, 180, 180,// 1 to 8
180, 180, 180, 180, 180, 180, 180, 180,//9 to 16
180, 180, 180, 180, 180, 180, 180, 180,//17 to 24
180, 180, 180, 180, 180, 180, 180, 180};//25 to 32
// initial position of servos
int allServoPosition[] ={
0, 0, 0, 0, 0, 0, 0, 0,// 1 to 8
0, 0, 0, 0, 0, 0, 0, 0,//9 to 16
0, 0, 0, 0, 0, 0, 0, 0,//17 to 24
0, 0, 0, 0, 0, 0, 0, 0};//25 to 32
int servoNumber = 100;//servo to move
int buttonPushed =0;
int allServo =0;
void handleServo();//this is prototype of function defined at the end of this code
int angleToPulse(int ang); //this is prototype of function defined at the end of this code
////////////////////////PCA9685 ended
#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); // 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]) );
}
}//for end
Serial.begin(115200);
Serial.println("32 channel Servo test!");
//Servo control using ESP32 from Robojax.com
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
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 channel Servo control
delay(100);
}//if pushed
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()
* update the buttonPushed varialbe
* returns nothing
* Written by Ahmad Shamshiri on Dec 29, 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() end
/*
* angleToPulse(int ang)
* gets angle in degree and returns the pulse width
* also prints the value on seial monitor
* written by Ahmad Shamshiri for Robojax, Robojax.com
*/
int angleToPulse(int ang){
int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX);// map angle of 0 to 180 to Servo min and Servo max
//Serial.print("Angle: ");Serial.print(ang);
//Serial.print(" pulse: ");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.