هذا الدليل جزء من: التحكم في محرك سيرفو 16 أو 32 باستخدام PCA9685
تساعدك هذه المجموعة من الدروس التعليمية المصحوبة بمقاطع فيديو على التحكم في 32 محرك سيرفو أو أكثر باستخدام أردوينو أونو، أو نانو، أو ميني، أو إي إس بي 32. جميع الأكواد متوفرة.
التحكم في 32 سيرفو عبر الواي فاي باستخدام ESP32 و PCA9685 من خلال الكمبيوتر المكتبي أو الهاتف المحمول V5
في هذا الدليل، سنتعلم كيف نتحكم في 32 محرك سيرفو باستخدام وحدة تحكم PWM PCA9685 المتصلة بـ ESP32 عبر الواي فاي. تتيح لك هذه الإعدادات التحكم في كل سيرفو بشكل فردي أو جميعها دفعة واحدة من خلال واجهة ويب يمكن الوصول إليها من جهاز كمبيوتر مكتبي أو جهاز محمول. بنهاية هذا الدليل، سيكون لديك نظام كامل الوظائف قادر على إدارة عدة محركات سيرفو بسهولة.

يقدم وحدة PCA9685 طريقة بسيطة للتحكم في عدة سيرفو باستخدام إشارات PWM، بينما يتولى ESP32 التواصل عبر الواي فاي ووظائف خادم الويب. ستتمكن من ضبط زاوية كل محرك سيرفو من خلال واجهة سهلة الاستخدام تعرض أزرارًا لكل سيرفو. للرجوع البصري، تأكد من مشاهدة الفيديو (في الفيديو عند 00:00).
شرح الأجهزة
يستخدم هذا المشروع بشكل أساسي متحكم ESP32 الدقيق ووحدة التحكم PWM PCA9685. يعد ESP32 متحكمًا قويًا مزودًا بإمكانيات واي فاي مدمجة، مما يجعله مثاليًا لمشاريع إنترنت الأشياء. PCA9685 هو وحدة تحكم PWM ذات 16 قناة يمكن توصيلها ببعضها للتحكم في ما يصل إلى 64 سيرفو. يتواصل مع ESP32 عبر بروتوكول I2C، مما يسمح بتوصيل العديد من الوحدات والتحكم فيها بشكل فردي.
كل وحدة PCA9685 لها عنوان I2C افتراضي هو 0x40. عند استخدام وحدات متعددة، يمكنك تغيير عناوينها عن طريق لحام موصلات معينة. على سبيل المثال، يمكن أن تكون الوحدة الأولى على 0x40، والثانية على 0x41، وهكذا. تمكّن هذه القدرة على التسلسل من التحكم في العديد من السيرفو بدون الحاجة إلى دبابيس إضافية على ESP32.
كما هو موضح في الصورة أعلاه، بالنسبة لقرص PCA9685 رقم 2 (على اليسار)، تأكد من لحام تلك المسار لضبط عنوان I2C بحيث يكون مختلفًا عن القرص 1 (على اليمين).
تفاصيل ورقة البيانات
| الشركة المصنعة | أدا فروت |
|---|---|
| رقم الجزء | PCA9685 |
| فولتية المنطق/الإدخال والإخراج | 2.3 فولت إلى 5.5 فولت |
| جهد الإمداد | 2.3 فولت إلى 5.5 فولت |
| تيار الخرج (لكل قناة) | ٢٥ مللي أمبير |
| ذروة التيار (لكل قناة) | 100 مللي أمبير |
| إرشادات تردد PWM | 40 هرتز إلى 1000 هرتز |
| عتبات منطق الإدخال | 0.3 فولت (منخفض) / 0.7 فولت (مرتفع) |
| انخفاض الجهد / RDS(on)/ التشبع | 0.5 فولت كحد أقصى |
| الحدود الحرارية | 125 °م كحد أقصى |
| حزمة | TSSOP-28 |
| ملاحظات / متغيرات | ما يصل إلى 64 سيرفو مع ترابط |
- تأكد من توفير الطاقة المناسبة (5 فولت، 2 أمبير مستحسن).
- استخدم مقاومات السحب لأعلى على خطوط SDA و SCL إذا لزم الأمر.
- تحقق من عناوين I2C بعناية عند استخدام وحدات PCA9685 متعددة.
- اعتبر تبديد الحرارة للتطبيقات عالية القدرة.
- اختبر السيرفوهات بشكل فردي لضمان عملها بشكل صحيح.
تعيينات الدبابيس الشائعة لـ I2C:SDA= GPIO 21،SCL= GPIO 22.
تعليمات التوصيل

لتهيئة PCA9685 و ESP32، ابدأ بتوصيل الطاقة والأرض. قم بتوصيل الطرف الموجب (V+قم بتوصيل الدبوس VCC من PCA9685 بمخرج 5V من مصدر الطاقة الخاص بك. قم بتوصيل الأرضي (GND) من PCA9685 بالأرضي لجهاز ESP32. تأكد من أن كلا الجهازين يتشاركان في الأرضي المشترك.
بعد ذلك، بالنسبة لتواصل I2C، قم بتوصيل دبابيس SDA لجهاز PCA9685 إلى GPIO 21 على ESP32 ودبوس SCL إلى GPIO 22. إذا كنت تستخدم وحدات PCA9685 متعددة، تأكد من أنها موجهة بشكل صحيح عن طريق لحام جمبر A0 لتغيير عنوان الوحدة الثانية إلى 0x41، وهكذا. بعد ذلك، يمكنك توصيل محركات السيرفو بمنافذ إخراج PWM لجهاز PCA9685 حسب الحاجة.
أمثلة الشفرات وشرحها
يبدأ الرمز بتضمين المكتبات اللازمة وتهيئة لوحين من نوع PCA9685. المعرفات مثلmaximumServoوservoAngleحدد عدد السيرفو وزاوية الحالية، على التوالي.
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // how many servos are connectedهذا المقتطف يُظهر تهيئة كائنات PCA9685 مع عناوينها الخاصة. المتغيرmaximumServoيحدد العدد الإجمالي للخدمات التي يمكن التحكم فيها.
في الـsetup()تتم تهيئة اللوحات، ويتم establishes الاتصال بشبكة الواي فاي. تم تعيين الموضع الابتدائي لجميع المحركات باستخدام حلقة.
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]));
}
}
}هذا الكود يقوم بتكوين لوحات PCA9685 ويضبط تردد PWM. يقوم بتهيئة جميع السيرفو إلى مواضعها الابتدائية، والتي تم تعريفها في الـallServoPositionمصفوفة.
أخيرًا، الحلقة الرئيسية تتعامل مع طلبات العملاء الواردة للتحكم في المحركات استنادًا إلى إدخال المستخدم.
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;
}تقوم هذه الحلقة بمعالجة طلبات العملاء باستمرار وتحديث وضعيات السيرفورات بناءً على الزر المضغوط عليه. المتغيرbuttonPushedيتم إعادة تعيينه بعد كل إجراء لضمان التحكم السليم.
للحصول على الكود الكامل، يرجى الرجوع إلى القسم الموجود أسفل المقال.
عرض / ماذا تتوقع
بمجرد إعداد كل شيء، يجب أن تكون قادرًا على التحكم في كل سيرفو بشكل فردي أو جميعًا مرة واحدة من واجهة ويب. يمكنك ضبط زوايا السيرفوات من خلال النقر على الأزرار المقابلة لكل سيرفو على جهازك. يجب أن يستجيب النظام بسرعة، ولكن تذكر أن قيود الطاقة يمكن أن تؤثر على الأداء (في الفيديو عند 14:30).
تشمل الأخطاء الشائعة التأكد من تعيين عناوين I2C بشكل صحيح وأنه يتم توفير طاقة كافية للخدمات. إذا لم تستجب الخدمات، تحقق مرة أخرى من التوصيلات والأسلاك الخاصة بك.
طوابع الزمن في الفيديو
- :00 بداية
- 01:19 مقدمة
- :32 إعداد عنوان I2C
- 05:07 شرح الأسلاك
- 07:44 إعداد Arduino IDE لـ ESP32
- 09:53 شرح كود الأردوينو
- 25:49 عرض على سطح المكتب
- :52 عرض على الهاتف المحمول
هذا الدليل هو جزء من: التحكم في محرك سيرفو 16 أو 32 باستخدام PCA9685
- كود أردوينو وفيديو لمتحكم السيرفو PCA9685 ذو 16 قناة و12 بت V1
- Control 16 Servo Motors Using a PCA9685 Module and Arduino V2 Sketch #1: One-by-One
- التحكم في 16 محرك سيرفو باستخدام وحدة PCA9685 وكود أردوينو V2: التحكم الفردي في السيرفو
- Controlling 16 Servo Motors Using a PCA9685 Module and Arduino V2 Sketch #3: All Servos Together
- التحكم في محرك سيرفو 32 باستخدام وحدة PCA9685 وبرنامج Arduino V3 الرسم التخطيطي #1: جميع السيرفوهات معًا
- التحكم في محرك سيرفو 32 باستخدام وحدة PCA9685 و 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;
}
الأشياء التي قد تحتاجها
-
أمازونشراء PCA9685 من أمازونamzn.to
-
أمازونمحرك سيرفو على أمازونamzn.to
-
إي باياشترِ PCA9685 من eBayebay.us
-
علي إكسبريساشترِ PCA9685 من علي إكسبريسs.click.aliexpress.com
-
علي إكسبريساشترِ محرك سيرفو SG90 بزاوية 180 أو 360 من علي إكسبريسs.click.aliexpress.com
-
بانجوداشترِ PCA9685 من بانجودbanggood.com
الموارد والمراجع
-
خارجيمكتبة PAC9685 (من GitHub)github.com
ملفات📁
لا توجد ملفات متاحة.