هذا الدليل جزء من: التحكم في محرك سيرفو 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
/*
* المصدر الأصلي لمكتبة وحدة PCA9685: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
*
* هذا هو كود آردوينو لجهاز تحكم سيرفو PCA6985 بـ 32 قناة للتحكم في 32 محرك سيرفو عبر WiFi باستخدام ESP32 MCU. احصل على هذا الكود والأسلاك من هذا الفيديو: http://robojax.com/RJT365
*
* شاهد الفيديو لهذا الكود: https://youtu.be/bvqfv-FrrLM
*
* فيديوهات ذات صلة
* فيديو V4 لجهاز PCA9685 بـ 32 سيرفو مع ESP32: https://youtu.be/JFdXB8Za5Os
* فيديو V3 عن كيفية التحكم في 32 محرك سيرفو عبر PCA9685: https://youtu.be/6P21wG7N6t4
* فيديو V2 لجهاز PCA9685 بثلاث طرق مختلفة للتحكم في محركات السيرفو: https://youtu.be/bal2STaoQ1M
* فيديو V1 مقدمة لجهاز PCA9685 للتحكم في 16 سيرفو: https://youtu.be/y8X9X10Tn1k
*
* كتبها أحمد شمشيري لقناة فيديو Robojax www.Robojax.com
* التاريخ: 17 فبراير 2020، في أجاكس، أونتاريو، كندا
*
* أو قم بالتبرع باستخدام باي بال http://robojax.com/L/?id=64
*
* هذا الكود هو "كما هو" بدون ضمان أو مسؤولية. حر للاستخدام طالما أنك تحتفظ بهذه الملاحظة سليمة.*
* تم تحميل هذا الكود من Robojax.com
* هذا البرنامج هو برنامج مجاني: يمكنك إعادة توزيعه و/أو تعديله وفقًا لشروط رخصة جنو العمومية كما نشرتها مؤسسة البرمجيات الحرة، سواء الإصدار 3 من الرخصة، أو (حسب اختيارك) أي إصدار لاحق.
*
* يتم توزيع هذا البرنامج على أمل أن يكون مفيدًا، لكن بدون أي ضمان؛ بدون حتى ضمان ضمناً لجودة المنتج أو ملاءمته لهدف معين. انظر رخصة جنو العمومية للحصول على مزيد من التفاصيل.
*
* يجب أن تكون قد تلقيت نسخة من رخصة جنو العمومية مع هذا البرنامج. إذا لم يكن الأمر كذلك، انظر <https://www.gnu.org/licenses/>.
* /
* ////////////////////// تم بدء إعدادات PCA9685
*/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// تمت تسميته بهذه الطريقة، فهو يستخدم العنوان الافتراضي 0x40
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // كم عدد السيرفو المتصل؟
// اعتمادًا على نوع السيرفو الخاص بك، قد تختلف قيم الحد الأدنى والحد الأقصى لعرض النبضة.
// أريد أن تكون هذه صغيرة/كبيرة قدر الإمكان دون أن تصل إلى النهاية الصلبة.
// لتوسيع النطاق الأقصى. سيتعين عليك تعديلها حسب الحاجة لتتناسب مع المحركات التي تستخدمها.
// لدي!
// شاهد الفيديو V1 لفهم السطرين أدناه: http://youtu.be/y8X9X10Tn1k
#define SERVOMIN 125 // هذا هو عدد طول النبضة 'الحد الأدنى' (من أصل 4096)
#define SERVOMAX 575 // هذه هي 'الحد الأقصى' لعدد طول النبضة (من أصل 4096)
int servoAngle =0;
int servoStep = 10;
int stepDelay = 50; // ٥٠ مللي ثانية
int servoAngleMin =0;
int servoAngleMax = 180;
// زاوية الحد الأدنى لكل سيرفو
int allServoMin[]={
0, 0, 0, 0, 0, 0, 0, 0, // 1 إلى 8
0, 0, 0, 0, 0, 0, 0, 0, // ٩ إلى ١٦
0, 0, 0, 0, 0, 0, 0, 0, // ١٧ إلى ٢٤
0, 0, 0, 0, 0, 0, 0, 0}; // ٢٥ إلى ٣٢
// القيمة القصوى لكل سيرفو
int allServoMax[]={
180, 180, 180, 180, 180, 180, 180, 180, // 1 إلى 8
180, 180, 180, 180, 180, 180, 180, 180, // ٩ إلى ١٦
180, 180, 180, 180, 180, 180, 180, 180, // ١٧ إلى ٢٤
180, 180, 180, 180, 180, 180, 180, 180}; // ٢٥ إلى ٣٢
// الموقع الابتدائي للسيرفوهات
int allServoPosition[] ={
0, 0, 0, 0, 0, 0, 0, 0, // 1 إلى 8
0, 0, 0, 0, 0, 0, 0, 0, // ٩ إلى ١٦
0, 0, 0, 0, 0, 0, 0, 0, // ١٧ إلى ٢٤
0, 0, 0, 0, 0, 0, 0, 0}; // ٢٥ إلى ٣٢
int servoNumber = 100; // سيرفو للتحريك
int buttonPushed =0;
int allServo =0;
void handleServo(); // هذا هو نموذج دالة محددة في نهاية هذا الكود
int angleToPulse(int ang); // هذا هو نموذج دالة محددة في نهاية هذا الكود
// //////////////////////انتهى PCA9685
#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); // تعمل السيرفو التناظرية بتحديثات تبلغ حوالي 60 هرتز.
board2.setPWMFreq(60);
// الموقع الابتدائي لجميع السيرفوهات
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]) );
}
} // لنهاية
Serial.begin(115200);
Serial.println("32 channel Servo test!");
// تحكم في السيرفو باستخدام ESP32 من Robojax.com
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// انتظر الاتصال
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);
}
// روبيو جاكس PCA9865 تحكم سيرفو 32 قناة
delay(100);
} // إذا تم الدفع
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;
}
/*
* تعامل مع سيرفو()
* قم بتحديث متغير buttonPushed
* لا يُرجع شيء
* كتبها أحمد شمشيري في 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() نهاية
/*
* زاوية إلى نبضة(int ang)
* تأخذ الزاوية بالدرجة وتعيد عرض النبضة
* كما تطبع القيمة على شاشة المراقبة التسلسلية
* كتبها أحمد شمشيري لروبو جكس، Robojax.com
*/
int angleToPulse(int ang){
int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX); // قم بتعيين زاوية الخريطة من 0 إلى 180 إلى الحد الأدنى لل servos والحد الأقصى لل servos
// زاوية:
// سيريل.طباعة(" نبض: ");سيريل.طباعة_سطر(نبض);
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
ملفات📁
لا توجد ملفات متاحة.