دليل التحكم بالسيرفو مع Arduino: SG90 وPWM وPCA9685

يحتوي هذا المقال على روابط تسويق بالعمولة مُعلَّمة بعلامة *. بصفتي شريكًا في برنامج Amazon Associates، أربح من عمليات الشراء المؤهلة، دون أي تكلفة إضافية عليك. يساعد ذلك على إبقاء الشروحات مجانية.

يُحمَّل الفيديو من YouTube (Google)، وقد يضع ملفات تعريف الارتباط (Cookies). سياسة الخصوصية

ملخص سريع

يشرح هذا الدليل كيف تعمل محركات السيرفو المخصصة للهواة وإشارة PWM (تعديل عرض النبضة) التي تتحكم بها. ويقارن بين SG90 وMG996R، ثم يبني ثلاثة مشاريع: Sweep، والتحكم بمقاومة متغيرة (Knob)، ومحركَي سيرفو على لوحة PCA9685، وهي لوحة قيادة سيرفو بـ 16 قناة. ويتضمن الدليل كودًا مُختبَرًا للمشاريع الثلاثة.

يدور السيرفو إلى الزاوية المطلوبة منه ويثبت عندها. ولهذا الغرض تُستخدم محركات السيرفو في الأذرع الروبوتية، وحوامل الكاميرا من نوع pan-tilt (التي تدير الكاميرا إلى الجانبين وإلى الأعلى والأسفل)، وأقفال الأبواب الآلية. ومن المشكلات المعتادة لدى المبتدئين الاهتزاز (Jitter، أي أن السيرفو يرتعش بدل أن يثبت في مكانه)، والتوصيلات الخاطئة، وتحميل مزود الطاقة فوق طاقته. ويعرض الفيديو في أعلى هذه الصفحة المشاريع وهي تعمل.

كيف تعمل محركات السيرفو

يدور محرك التيار المستمر العادي ما دام موصولًا بالطاقة. أما السيرفو فيضيف إليه مستشعر موضع ودائرة تحكم، فيتحرك إلى الزاوية التي تحددها له ويبقى عندها. ويُسمّى هذا التحكمَ ذا الحلقة المغلقة (Closed-loop Control): يقيس السيرفو موضعه بنفسه ويصحح الفرق بينه وبين الهدف. ومن الاستخدامات المعتادة الأخرى آليات التوجيه وحوامل الكاميرا المثبِّتة (Gimbal، وهي حوامل تحافظ على ثبات الكاميرا).

داخل محرك سيرفو للهواة

يتكون سيرفو الهواة من أربعة أجزاء:

  • محرك التيار المستمر: يحوّل الطاقة الكهربائية إلى حركة دوران.
  • مجموعة التروس: تروس تخفيض (بلاستيكية في SG90 ومعدنية في MG996R) تحوّل سرعة دوران المحرك العالية بوحدة RPM (دورة في الدقيقة) إلى دوران أبطأ بعزم دوران (قوة التدوير) أكبر عند عمود الخرج.
  • المقاومة المتغيرة (Potentiometer): مقاومة متغيرة متصلة بعمود الخرج، تُبلغ دائرة التحكم بالزاوية الحالية للعمود.
  • دائرة التحكم: لوحة PCB صغيرة (لوحة دوائر مطبوعة). تقارن الموضع المستهدف، الذي ترسله لوحة Arduino على شكل إشارة PWM (سلسلة من النبضات المضبوطة التوقيت)، بقراءة المقاومة المتغيرة، وتشغّل المحرك حتى يتطابق الاثنان.
Intact hobby servo next to a disassembled one, showing the DC motor, gear train and potentiometer
سيرفو سليم وسيرفو مفكك.
Disassembled servo: gear train, control board and potentiometer
سيرفو مفكك تظهر أجزاؤه الداخلية.

فككت السيرفو الظاهر في هذه الصور بنفسي لأُظهر أجزاءه الداخلية.

التحكم ذو الحلقة المغلقة

تنفّذ دائرة التحكم هذه الحلقة باستمرار:

  1. ترسل لوحة Arduino إشارة PWM ترمّز الزاوية المستهدفة.
  2. تقيس دائرة التحكم عرض النبضة وتستنتج منه الموضع المستهدف.
  3. تقرأ المقاومة المتغيرة لتعرف الموضع الحالي للعمود.
  4. إذا اختلف الموضعان، تشغّل محرك التيار المستمر باتجاه الهدف.
  5. عندما يتطابقان، يتوقف المحرك ويثبت السيرفو في موضعه.

يواصل السيرفو تصحيح نفسه ويحافظ على الزاوية المطلوبة تحت الحمل، ما دام الحمل أقل من عزم الدوران المقنَّن له.

Block diagram of the servo's closed-loop position control
التحكم في موضع السيرفو بحلقة مغلقة.

إشارة PWM الخاصة بالسيرفو

تضبط لوحة Arduino زاوية السيرفو بإشارة PWM، وهي سلسلة من النبضات الرقمية بتردد ثابت. ويرمّز عرض النبضة، أي المدة التي تبقى فيها الإشارة في الحالة HIGH خلال كل نبضة، قيمة الزاوية.

تتوقع محركات سيرفو الهواة ترددًا قدره 50 Hz، أي نبضة واحدة كل 20 ms. والمهم في كل دورة مدتها 20 ms هو الجزء HIGH منها فقط. النطاق الاسمي من 1.0 إلى 2.0 ms، لكن كثيرًا من محركات سيرفو الهواة تحتاج إلى نحو 0.5 إلى 2.5 ms لتغطية 180° كاملة. ويختلف النطاق الدقيق من طراز لآخر. وتستخدم مكتبة Arduino Servo افتراضيًا النطاق من 544 إلى 2400 µs.

PWM waveform at 50 Hz: the pulse width sets the servo angle
إشارة PWM للتحكم في السيرفو بتردد 50 Hz.

عرض النبضة وموضع السيرفو

دورة العمل (Duty Cycle) هي نسبة الزمن الذي تكون فيه الإشارة HIGH من كل دورة مدتها 20 ms. ويبيّن الجدول العلاقة بين عرض النبضة والزاوية ودورة العمل؛ وتختلف القيم الدقيقة باختلاف طراز السيرفو.

عرض النبضةموضع السيرفودورة العمل عند 50 Hz
0.5 ms0° (الحد الأدنى، لبعض محركات السيرفو)2.5 %
1.0 ms0° (الحد الأدنى القياسي)5 %
1.25 ms45°6.25 %
1.5 ms90° (وضع المنتصف)7.5 %
1.75 ms135°8.75 %
2.0 ms180° (الحد الأقصى القياسي)10 %
2.5 ms180° (الحد الأقصى، لبعض محركات السيرفو)12.5 %

تولّد مكتبة Arduino Servo هذه النبضات نيابةً عنك. فعندما تستدعي servo.write(90)، ترسل المكتبة نبضة مدتها نحو 1.5 ms (أي 1472 µs مع الحدود الافتراضية) بتردد 50 Hz، فيتحرك السيرفو إلى المنتصف. وتحتاج إلى معرفة عروض النبضات عند استكشاف أخطاء الاهتزاز وإصلاحها، أو عند ضبط نطاقات مخصصة، أو عند استخدام لوحة PCA9685.

SG90 مقابل MG996R: أي سيرفو لأي مهمة

السيرفو المصغّر SG90 والسيرفو القياسي MG996R نوعان شائعان من محركات سيرفو الهواة في مشاريع Arduino. ويُعطى عزم الدوران بوحدة kg·cm: فالقيمة 1.8 kg·cm تعني أن السيرفو يستطيع حمل 1.8 kg على ذراع رافعة يبعد 1 cm عن العمود. اختر بحسب عزم الدوران والحجم والمتانة.

SG90 micro servo with horn attached
السيرفو المصغّر SG90 مع ذراع السيرفو (Horn)، وهو الذراع الذي يُركَّب على عمود الخرج.
المواصفاتسيرفو مصغّر SG90سيرفو MG996R
عزم التوقف (عزم الدوران الذي يتوقف عنده المحرك عن الدوران)1.8 kg·cm عند 4.8 V، و2.2 kg·cm عند 6 V9.4 kg·cm عند 4.8 V، و11 kg·cm عند 6 V
جهد التشغيلمن 4.8 إلى 6 Vمن 4.8 إلى 7.2 V
تيار اللاحمل (التيار أثناء دوران السيرفو دون حمل)100 mA220 mA عند 4.8 V، و250 mA عند 6 V
تيار التوقف (التيار الذي يسحبه المحرك عندما يُعاق دورانه)650 mA2.5 A عند 6 V
سرعة التشغيل0.1 s لكل 60° عند 4.8 V0.17 s لكل 60° عند 4.8 V
الوزن9 g55 g
نوع التروستروس بلاستيكيةتروس معدنية
مدى الدوران180°180°
الاستخدام المعتادالمشاريع الخفيفة، وحوامل pan-tilt، والروبوتات الصغيرةالأذرع الروبوتية، والمفاصل عالية الحمل، ومركبات RC (المتحكَّم بها لاسلكيًا)
المزايارخيص، وخفيف الوزن، ومنخفض استهلاك الطاقةعزم دوران عالٍ، وتروس معدنية متينة
العيوبعزم دوران منخفض، وقد تنكسر أسنان التروس البلاستيكيةأثقل وزنًا، ويسحب تيارًا أعلى، وأغلى ثمنًا

تستند قيم عزم الدوران وتيار التوقف لـ MG996R، وعزم دوران SG90 عند 4.8 V، وسرعتا الطرازين إلى أوراق البيانات (Datasheets) الصادرة عن TowerPro. أما بقية القيم فهي أرقام نموذجية يذكرها البائعون.

استخدم SG90 عندما يكون الوزن والمساحة محدودين والحمل خفيفًا. واختر MG996R عندما يقترب الحمل من عزم التوقف لـ SG90 البالغ 1.8 kg·cm. وأستخدم النوعين معًا في ذراع روبوتية بست درجات حرية (6-DOF) (أي ستة مفاصل) من بنائي. تحرّك ثلاثة محركات MG996R القاعدة والكتف والمرفق، وهي المفاصل التي تحمل وزن الذراع، وتحرّك ثلاثة محركات SG90 المعصم والقابض الأخف وزنًا. واختر مزود الطاقة بحيث يوفّر التيار الكلي الذي تسحبه جميع محركات السيرفو.

أجهزة اختبار السيرفو

يفحص جهاز اختبار السيرفو (Servo Tester) محرك السيرفو دون الحاجة إلى Arduino أو أي كود. تحرّك هذه الوحدات الرخيصة السيرفو عبر مداه كاملًا أو إلى موضع تضبطه بمقبض دوّار. ويحتوي كثير منها أيضًا على وضع محايد يُخرج نبضة مدتها 1.5 ms، فتستطيع ضبط كل سيرفو في منتصف مداه قبل تركيب ذراع السيرفو.

Servo tester module
وحدة اختبار السيرفو.

تغذية محركات السيرفو بالطاقة بأمان

لا تغذِّ محركات السيرفو من الطرف 5 V في Arduino. قد يعمل منه سيرفو SG90 واحد بحمل خفيف؛ أما عدة محركات سيرفو أو حمل أثقل فتحمّله فوق طاقته.

لماذا لا يكفي الطرف 5 V في Arduino

عند التغذية عبر USB، تستطيع لوحة Uno توفير نحو 500 mA إجمالًا، وهو حد يفرضه المصهر (Fuse) الخاص بمنفذ USB في اللوحة. وعند التغذية عبر مقبس البرميل (Barrel Jack، وهو مقبس التيار المستمر الدائري في Uno)، يأتي جهد 5 V من منظم الجهد المدمج في اللوحة. ويسخن هذا المنظم عند تيارات أقل كثيرًا من تياره المقنَّن البالغ 1 A إذا كان جهد الدخل 9 V أو أكثر. يسحب سيرفو SG90 واحد ما يصل إلى 650 mA عند التوقف، ويسحب MG996R ما يصل إلى 2.5 A. وعندما يطلب السيرفو تيارًا أكبر مما تستطيع اللوحة توفيره، ينخفض جهد خط 5 V للحظة. ويُسمّى هذا الانخفاض القصير في الجهد Brownout، وهو يعيد تشغيل Arduino أو يجعله يتصرف على نحو غير منتظم.

مزود طاقة خارجي

استخدم مزود طاقة منفصلًا بجهد من 5 إلى 6 V. واختر قدرته بحسب مجموع تيارات التوقف لجميع محركات السيرفو: 650 mA لكل SG90 و2.5 A لكل MG996R. يسحب محركا SG90 ما يصل إلى 1.3 A، فيكفي محوّل 5 V بتيار 2 A. وتحتوي ذراعي الروبوتية بست درجات حرية (6-DOF) على ثلاثة محركات MG996R وثلاثة SG90: 3 × 2.5 A + 3 × 0.65 A = 9.45 A. لذلك تتضمن قائمة قطعها مزود طاقة 5 V بتيار 10 A.

قواعد التوصيل:

  • أرضي مشترك: صِل الأرضي (GND، وهو مرجع 0 V) لمزود الطاقة الخارجي بأحد أطراف GND في Arduino. فمن دون أرضي مشترك لا يكون لإشارة PWM مرجع، ولا يستجيب السيرفو.
  • خطوط تغذية منفصلة: يُوصَل السلك الأحمر للسيرفو بالطرف الموجب لمزود الطاقة الخارجي، لا بالطرف 5 V في Arduino.
  • الإشارة والأرضي فقط: باستثناء الأرضي المشترك، السلك الوحيد بين Arduino والسيرفو هو سلك الإشارة (PWM).
  • المكثف: ضع مكثفًا كهروليتيًا سعته 470 µF (بجهد مقنَّن 10 V أو أكثر) على تغذية السيرفو، بين خطها الموجب وGND، وقريبًا من محركات السيرفو. فهو يقلل قمم الجهد المفاجئة والاهتزاز. وللمكثف الكهروليتي قطبية ثابتة: يُوصَل الجانب المعلَّم بشريط علامة السالب إلى GND.

مرجع سريع لاستهلاك التيار

طراز السيرفوتيار اللاحملتيار التوقفمزود الطاقة لسيرفو واحد
SG90100 mA650 mA5 V، بتيار 1 A على الأقل
MG996R220 mA2500 mA6 V، بتيار 3 A على الأقل

تسحب ستة محركات SG90 عند التوقف 6 × 650 mA = 3.9 A.

أسلاك السيرفو الثلاثة

تستخدم جميع محركات سيرفو الهواة القياسية موصلًا بثلاثة أسلاك:

الطرفالإشارةلون السلك
1الأرضي (GND)أسود أو بني
2الطاقة (VCC، من 4.8 إلى 6 V)أحمر
3إشارة التحكم (PWM)برتقالي أو أصفر

تستخدم معظم محركات السيرفو ترتيب الأطراف هذا: الأرضي عند إحدى الحافتين، والطاقة في المنتصف، والإشارة عند الحافة الأخرى. وإذا لم تكن متأكدًا، فراجع ورقة بيانات السيرفو.

المشروع 1: حركة المسح بالسيرفو (Sweep)

يحرّك برنامج Sweep (والـ Sketch هو برنامج Arduino) السيرفو ذهابًا وإيابًا بين 0° و180°. فهو يتيح لك التحقق من التوصيلات ويعرّفك بمكتبة Servo.

القطع المطلوبة

  • Arduino Uno (أو أي لوحة Arduino).
  • سيرفو مصغّر SG90 (أو ما يماثله).
  • مزود طاقة خارجي 5 V للسيرفو (يُنصح به).
  • لوحة تجارب (Breadboard) وأسلاك توصيل (Jumper).

توصيلات Sweep

سلك السيرفويتصل بـ
بني أو أسود (GND)GND في Arduino وGND في مزود الطاقة الخارجي
أحمر (VCC)الطرف الموجب لمزود الطاقة الخارجي 5 V
برتقالي أو أصفر (الإشارة)الطرف الرقمي 9 في Arduino
Wiring diagram: SG90 servo connected to the Arduino, signal wire on pin 9
توصيلات المشروع 1: سلك إشارة SG90 على الطرف 9.

كود Sweep

افتح Arduino IDE وانتقل إلى File > Examples > Servo > Sweep، أو انسخ الكود أدناه. يأتي مثال Sweep مرفقًا بمكتبة Servo.

/* Sweep
 by BARRAGAN http://barraganstudio.com
 This example code is in the public domain.
 modified 8 Nov 2013
 by Scott Fitzgerald
 https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
 */
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0;    // variable to store the servo position
void setup() {
    myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
void loop() {
    for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        myservo.write(pos);              // tell servo to go to position in variable 'pos'
        delay(15);                       // waits 15 ms for the servo to reach the position
    }
    for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
        myservo.write(pos);              // tell servo to go to position in variable 'pos'
        delay(15);                       // waits 15 ms for the servo to reach the position
    }
}

كيف يعمل كود Sweep

برنامج Sweep قصير، ويستخدم الدوال الأساسية لمكتبة Servo:

  • يستورد السطر #include مكتبة Servo، التي تولّد نبضات PWM نيابةً عنك.
  • ينشئ السطر Servo myservo; كائنًا من النوع Servo. ويمكنك إنشاء ما يصل إلى 12 كائنًا من النوع Servo على Arduino Uno.
  • يطلب السطر myservo.attach(9); من المكتبة إخراج النبضات على الطرف الرقمي 9.
  • يحرّك السطر myservo.write(pos); السيرفو إلى الزاوية المخزّنة في المتغير pos، من 0 إلى 180.
  • تزيد حلقتا for الزاوية خطوةً خطوة من 0 إلى 180 ثم تعيدها إلى 0، مع تأخير 15 ms في كل خطوة حتى يتمكن السيرفو من المتابعة.

إذا لم يبلغ السيرفو مداه الكامل، فاضبط حدود النبضات في attach() (انظر قسم استكشاف الأخطاء وإصلاحها) وتحقق من مزود الطاقة. والاهتزاز عند الموضعين الطرفيين يعني عادةً أن السيرفو لا يستطيع فيزيائيًا بلوغ هاتين الزاويتين، فيضغط عندئذٍ على المصدّ الميكانيكي (End Stop)، أي الحد الفيزيائي لمسار حركة عمود الخرج.

المشروع 2: التحكم في السيرفو بمقاومة متغيرة (Knob)

يضيف برنامج Knob مقاومة متغيرة كمُدخل: فبتدويرها تضبط زاوية السيرفو. يقرأ البرنامج مُدخلًا تناظريًا ويحوّله بالتناسب إلى زاوية. وتستخدم الأذرع الروبوتية التي يُتحكَّم بها بالمقاومات المتغيرة الطريقة نفسها.

القطع المطلوبة

  • Arduino Uno (أو أي لوحة Arduino).
  • سيرفو مصغّر SG90 (أو ما يماثله).
  • مقاومة متغيرة 10 kΩ.
  • مزود طاقة خارجي 5 V للسيرفو (يُنصح به).
  • لوحة تجارب (Breadboard) وأسلاك توصيل (Jumper).

توصيلات Knob

المكوّنالطرف أو السلكيتصل بـ
طرف GND في السيرفو (بني أو أسود)GNDGND في Arduino وGND في مزود الطاقة الخارجي
طرف VCC في السيرفو (أحمر)VCCالطرف الموجب لمزود الطاقة الخارجي 5 V
إشارة السيرفو (برتقالي أو أصفر)الإشارةالطرف الرقمي 9 في Arduino
الطرف 1 في المقاومة المتغيرةالطرف الخارجيArduino 5 V
الطرف المنزلق للمقاومة المتغيرة (Wiper)الطرف الأوسطالطرف التناظري A0 في Arduino
الطرف 3 في المقاومة المتغيرةالطرف الخارجيArduino GND
Wiring diagram: SG90 servo and potentiometer connected to the Arduino
توصيلات المشروع 2: الطرف المنزلق للمقاومة المتغيرة على A0، وإشارة السيرفو على الطرف 9.

كود Knob

افتح File > Examples > Servo > Knob في Arduino IDE، أو استخدم الكود أدناه.

/*
 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott http://people.interaction-ivrea.it/m.rinott
 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
 */
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
int potpin = A0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin
void setup() {
    myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
void loop() {
    val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
    val = map(val, 0, 1023, 0, 180);     // scale it for use with the servo (value between 0 and 180)
    myservo.write(val);                  // sets the servo position according to the scaled value
    delay(15);                           // waits for the servo to get there
}

كيف يعمل كود Knob

يستخدم البرنامج ثلاث دوال:

  • تقرأ الدالة analogRead(A0) الجهد على الطرف الأوسط للمقاومة المتغيرة وتُعيد قيمة من 0 إلى 1023. فمحوّل ADC (المحوّل التناظري الرقمي) في Uno دقته 10 بت، ما يعطي 1024 خطوة.
  • تحوّل الدالة map(val, 0, 1023, 0, 180) النطاق من 0 إلى 1023 بالتناسب إلى نطاق من 0 إلى 180 درجة.
  • ترسل الدالة myservo.write(val) الزاوية إلى السيرفو.

للحصول على تحكم أدق، استخدم myservo.writeMicroseconds() بدلًا من myservo.write(). فهي تضبط عرض النبضة مباشرةً بالميكروثانية، مثلًا من 1000 إلى 2000، ما يعطي خطوات أكثر من مقياس 0 إلى 180 درجة.

إذا أصدر السيرفو طنينًا عند طرفي مساره، فضيّق نطاق الخرج، مثلًا map(val, 0, 1023, 10, 170). وإذا لم يبلغ المدى الكامل، فتحقق مما إذا كانت المقاومة المتغيرة تصل إلى 0 و1023. أضف Serial.begin(9600) إلى setup() وSerial.println(val) مباشرةً بعد سطر analogRead()، قبل أن تُكتب نتيجة map() فوق القيمة المخزّنة في val. عندها تعرض الشاشة التسلسلية (Serial Monitor) في Arduino IDE القيم الخام بينما تدير المقاومة المتغيرة إلى طرفيها. واستخدم القيمتين الدنيا والعليا اللتين قستَهما نطاقًا لدخل الدالة map().

لوحة PCA9685 (16 قناة سيرفو)

باستخدام مكتبة Servo، تستطيع لوحة Uno قيادة ما يصل إلى 12 محرك سيرفو من أي أطراف رقمية. وتستخدم المكتبة Timer1، وهو أحد المؤقتات العتادية في Uno، لضبط توقيت النبضات. وما دامت محركات السيرفو مربوطة بالمكتبة (attached)، لا تعمل الدالة analogWrite() (دالة خرج PWM، المستخدمة مثلًا لتعتيم LED) على الطرفين 9 و10. والمقاطعة (Interrupt) توقف البرنامج الرئيسي مؤقتًا كي يُنفَّذ الكود الحساس للتوقيت، مثل توقيت السيرفو، فورًا. أما المكتبات التي تعطّل المقاطعات، مثل SoftwareSerial أو Adafruit NeoPixel، فتؤخر نبضات السيرفو وقد تسبب الاهتزاز. وتتجنب لوحة PCA9685 هذه القيود.

PCA9685 board with 16 servo channels
لوحة PCA9685.

شريحة PCA9685

شريحة PCA9685 هي وحدة قيادة PWM بـ 16 قناة ودقة 12 بت (4096 خطوة في كل دورة). وتتواصل مع Arduino عبر I2C، وهو ناقل بسلكين (SDA للبيانات وSCL لإشارة الساعة) يمكن أن تتشاركه عدة أجهزة. وتولّد الشريحة إشارات PWM الـ 16 كلها عتاديًا، فتبقى أطراف Arduino وTimer1 حرة، ولا يستطيع أي كود آخر تأخير النبضات. وفي استخدامات الهواة تُركَّب الشريحة على لوحة توسعة (Breakout Board)، وهي لوحة صغيرة تسهّل توصيل أطراف الشريحة. ويمكنك توصيل ما يصل إلى 62 لوحة PCA9685 بناقل I2C واحد، لكل منها عنوانها الخاص، ما يعطي نظريًا 992 قناة.

استخدم لوحة PCA9685 عندما يزيد عدد محركات السيرفو على اثنين أو ثلاثة، أو عندما تحتاج إلى أطراف Arduino وTimer1 لمهام أخرى. أما لمحرك أو محركين، فالتحكم المباشر يكفي.

توصيلات لوحة PCA9685

  • VCC: تغذية المنطق (3.3 V أو 5 V من Arduino). وهي تغذي شريحة PCA9685 فقط، لا محركات السيرفو.
  • GND: الأرضي. ويجب أن يكون مشتركًا مع Arduino ومزود طاقة السيرفو.
  • SDA: خط بيانات I2C. صِله بالطرف A4 في Arduino (Uno) أو بالطرف SDA.
  • SCL: خط ساعة I2C. صِله بالطرف A5 في Arduino (Uno) أو بالطرف SCL.
  • V+: مدخل تغذية السيرفو. صِل هنا مزود طاقة خارجيًا بجهد من 5 V إلى 6 V. وهو يغذي قنوات السيرفو الـ 16 كلها.
  • OE: تمكين الخرج (Output Enable). اتركه غير موصول (فهو مسحوب داخليًا إلى LOW) لتبقى جميع المخارج فعّالة.

المشروع 3: محركا سيرفو مع PCA9685 ومقاومات متغيرة

يتحكم هذا المشروع في محركي سيرفو كلٍّ على حدة باستخدام لوحة PCA9685 ومقاومتين متغيرتين.

القطع المطلوبة

المكوّنالكمية
Arduino Uno1
لوحة PCA96851
سيرفو مصغّر SG90 (أو ما يماثله)2
مقاومة متغيرة 10 kΩ2
مزود طاقة خارجي 5 V أو 6 V (بتيار 2 A على الأقل)1
لوحة التجارب (Breadboard) وأسلاك التوصيل (Jumper)حسب الحاجة

توصيلات المشروع 3

التوصيلمنإلى
بيانات I2Cالطرف A4 في Arduino (SDA)PCA9685 SDA
ساعة I2Cالطرف A5 في Arduino (SCL)PCA9685 SCL
تغذية المنطقArduino 5 VPCA9685 VCC
أرضي مشتركArduino GNDGND في PCA9685 وGND في مزود الطاقة الخارجي
تغذية السيرفوالطرف الموجب لمزود الطاقة الخارجي 5 Vمربط V+ في PCA9685
السيرفو 1موصل بـ 3 أطرافالقناة 0 في PCA9685
السيرفو 2موصل بـ 3 أطرافالقناة 15 في PCA9685
الطرف المنزلق للمقاومة المتغيرة 1الطرف الأوسطالطرف A0 في Arduino
الطرف المنزلق للمقاومة المتغيرة 2الطرف الأوسطالطرف A1 في Arduino
الأطراف الخارجية للمقاومة المتغيرةالأطراف الخارجيةالطرفان 5 V وGND في Arduino

تعمل أي قناتين؛ فالمعامل الأول للدالة pwm.setPWM() في الكود هو الذي يحدد القناة.

Wiring diagram: PCA9685 board on the Arduino I2C pins, two servos on channels 0 and 15, two potentiometers on A0 and A1
توصيلات المشروع 3: محركا سيرفو على لوحة PCA9685، ومقاومتان متغيرتان على Arduino.

كود المشروع 3

يحتاج البرنامج إلى مكتبة Adafruit PWM Servo Driver. ثبّتها من مدير مكتبات Arduino (Library Manager) (ابحث عن “Adafruit PWM Servo Driver”). يقرأ الكود المقاومتين المتغيرتين ويحوّل قيمتيهما بالتناسب إلى أطوال نبضات:

/**
 * Author: Omar Draidrya
 * Date: 2024/05/05
 * This code controls servos using the PCA9685 PWM driver and potentiometers.
 */
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// Initialize the PCA9685 using the default address (0x40).
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

void setup() {
    Serial.begin(9600);   // Start serial communication for debugging purposes.
    pwm.begin();          // Initialize the PCA9685 module.

    // Set the frequency to 50 Hz, good for servo control.
    pwm.setPWMFreq(50);  // standard servo refresh rate

    // Setup the analog pins as input.
    pinMode(A0, INPUT);
    pinMode(A1, INPUT);
}

void loop() {
    // Read the potentiometers.
    int potVal0 = analogRead(A0);  // Read the first potentiometer.
    int potVal1 = analogRead(A1);  // Read the second potentiometer.

    // Map the potentiometer values to servo pulse lengths.
    int servoPos0 = map(potVal0, 0, 1023, 150, 600); // Change values 150 to 600 depending on your servo specifications.
    int servoPos1 = map(potVal1, 0, 1023, 150, 600);

    // Set the servo positions.
    pwm.setPWM(0, 0, servoPos0);   // Set servo on channel 0.
    pwm.setPWM(15, 0, servoPos1);  // Set servo on channel 15.

    delay(20);  // Small delay to reduce jitter.
}

قيم نطاق النبضات في PCA9685

القيمتان 150 و600 في سطري map() ليستا درجات زاوية ولا ميلي ثوانٍ، بل هما قيمتا عدّ PWM بدقة 12 بت (تُسمّى أيضًا ticks) من أصل 4096 قيمة في كل دورة (20 ms عند 50 Hz): فالقيمة 150 تعادل نحو 0.73 ms، والقيمة 600 نحو 2.93 ms. تحوّل map() كل قراءة للمقاومة المتغيرة إلى قيمة عدّ ضمن هذا النطاق، وترسل setPWM() هذه القيمة إلى قناة السيرفو.

اعتبر القيم من 150 إلى 600 نطاقًا مبدئيًا. فحدّه الأعلى البالغ 2.93 ms أطول من الحد الأقصى البالغ 2.5 ms في الجدول أعلاه. ضيّق النطاق حتى يتوقف السيرفو عن الطنين عند كلا الطرفين. المذبذب الداخلي في الشريحة ليس دقيقًا تمامًا، لذا قد تختلف عروض النبضات الفعلية عن هذه القيم ببضعة في المئة. تشغّل نسخة المقاومات المتغيرة من ذراعي الروبوتية بست درجات حرية (6-DOF) لوحة PCA9685 بتردد 60 Hz بدلًا من 50 Hz، وتحوّل القيم إلى نطاق من 125 إلى 575 خطوة عدّ. عند 60 Hz يكون الزمن الدوري 16.67 ms، أي أن خطوة العدّ الواحدة تساوي 16.67 ms / 4096 = 4.07 µs، ويقابل هذا النطاق نحو 0.51 إلى 2.34 ms.

لاختبار التجهيز، ارفع الكود إلى اللوحة وأدِر كل مقاومة متغيرة ببطء. يجب أن يتبع كل سيرفو المقاومة المتغيرة الخاصة به. إذا لم يتحرك أحد محركات السيرفو، فافحص توصيلات I2C وتأكد من أن مزود الطاقة الخارجي موصول بالطرف V+ على لوحة PCA9685.

استكشاف الأخطاء وإصلاحها

اهتزاز السيرفو أو ارتعاشه

السبب: ينخفض جهد التغذية في كل مرة يسحب فيها السيرفو ذروة تيار. الحل: استخدم مزود طاقة منفصلًا يوفر تيارًا كافيًا، ومكثفًا سعة 470 µF على طرفي تغذية السيرفو. إذا تحركت عدة محركات سيرفو في الوقت نفسه وأُعيد تشغيل Arduino، فاجعل أسلاك تغذية السيرفو قصيرة وسميكة لتقليل هبوط الجهد.

وقد يكون السبب أيضًا كودًا آخر يؤخّر مقاطعات المؤقت (Timer Interrupts) التي تعتمد عليها مكتبة Servo. الحل: أزل المكتبة المتعارضة أو استخدم لوحة PCA9685 التي تولّد النبضات على مستوى العتاد.

السيرفو لا يتحرك

افحص بهذا الترتيب:

  1. سلك الإشارة موصول بالطرف المحدد في servo.attach(pin).
  2. طرف GND في Arduino وطرف GND في مزود طاقة السيرفو موصولان ببعضهما. فمن دون أرضي مشترك، يتجاهل السيرفو الإشارة أو يتحرك بشكل غير منتظم.
  3. مزود الطاقة مُشغَّل ويوفر جهدًا من 4.8 إلى 6 V عند السيرفو.
  4. يضمّن برنامج Arduino (Sketch) الملف Servo.h ويستدعي servo.attach() داخل setup().

ارتفاع حرارة السيرفو

ترتفع حرارة السيرفو عندما يتوقف قسرًا (Stall): أي عندما يثبّت موضعه أمام حمل يتجاوز عزم الدوران المقنَّن له ويسحب تيار التوقف طوال الوقت، ما يسخّن المحرك. خفّف الحمل الميكانيكي، أو استخدم سيرفو بعزم دوران أكبر، أو افصل السيرفو في الكود (detach) عندما لا يحتاج إلى تثبيت موضعه.

يؤدي استدعاء servo.detach() إلى إيقاف النبضات، فيتوقف تشغيل المحرك وقد تنخفض حرارته. لكن السيرفو لا يعود عندها يثبّت موضعه: فالمفصل المحمَّل، مثل كتف الذراع الروبوتية، سيسقط. لذا ادعم المفصل أو حرّكه إلى وضع الراحة قبل فصل السيرفو.

دوران محدود أو نطاق نبضات خاطئ

إذا لم يصل السيرفو إلى 0° أو 180°، فالسبب على الأرجح حدود النبضات في الكود، لأن لكل طراز من السيرفو نطاقًا مختلفًا قليلًا. عند التحكم المباشر من Arduino، حدّد حدودًا مخصصة باستخدام servo.attach(pin, minPulse, maxPulse)، مثل servo.attach(9, 500, 2500). القيمة الافتراضية في المكتبة من 544 إلى 2400 µs. وسّع النطاق بخطوات صغيرة وتوقف فور أن يبدأ السيرفو بالطنين عند أحد الطرفين. أما مع لوحة PCA9685 فاضبط حدود العدّ في أسطر map() بدلًا من ذلك. عند 50 Hz تساوي 2.5 ms قيمة 512 خطوة عدّ (2.5 / 20 × 4096)، لذا أبقِ الحد الأعلى عند 512 أو أقل واختبر كل طرف ببطء.

الأسئلة الشائعة

كم عدد محركات السيرفو التي يمكنني التحكم بها باستخدام لوحة Arduino Uno واحدة؟

حتى 12 سيرفو باستخدام مكتبة Servo القياسية. تستخدم المكتبة مؤقتًا واحدًا (Timer1 في Uno) لجميع محركات السيرفو، لذلك لا تعمل الدالة analogWrite() على الطرفين 9 و10 ما دامت هناك محركات سيرفو مربوطة عبر attach(). ولعدد أكبر من محركات السيرفو، تضيف لوحة PCA9685 عدد 16 قناة.

هل يمكنني استخدام محرك السيرفو من دون مكتبة؟

نعم، باستخدام digitalWrite() و delayMicroseconds()، لكن التوقيت يكون أقل دقة ويحجز وحدة المعالجة المركزية (أي أن المعالج ينتظر ولا يستطيع فعل أي شيء آخر). في المشاريع الفعلية استخدم مكتبة Servo؛ فالتوقيت اليدوي مفيد أساسًا لفهم الإشارة.

هل يمكنني تغذية السيرفو من بطارية 9 V؟

تتجاوز بطارية 9 V حد 6 V الذي تتحمله معظم محركات السيرفو المخصصة للهواة، ولا تخزّن إلا نحو 500 mAh، ولا تستطيع توفير ذروات التيار التي يحتاجها السيرفو. استخدم مزود طاقة بجهد 5 V مقنّنًا لتيار التوقف الخاص بالسيرفو.

كيف أتحكم في سيرفو الدوران المستمر باستخدام Arduino؟

يدور سيرفو الدوران المستمر من دون نقطة توقف نهائية، لذلك يحدد عرض النبضة السرعة والاتجاه بدلًا من الزاوية. النبضة بطول 1.5 ms توقف المحرك، والنبضات الأقصر تديره في اتجاه، والأطول في الاتجاه الآخر. وتبقى مكتبة Servo صالحة للاستخدام: servo.write(90) يوقفه، و servo.write(0) يعني السرعة القصوى في اتجاه، و servo.write(180) السرعة القصوى في الاتجاه الآخر.

هل يمكنني التحكم في السيرفو عبر بلوتوث باستخدام Arduino؟

نعم. باستخدام وحدة بلوتوث HC-05 أو HC-06 ترسل أوامر الزوايا من هاتف أو حاسوب، فيستقبلها Arduino عبر الاتصال التسلسلي ويحرّك السيرفو. ويوضّح دليل وحدة البلوتوث HC-05 الذي كتبته طريقة الإعداد.

المكتبات والكود

  • Servo.h: مدمجة في Arduino IDE ولا تحتاج إلى تثبيت. تُستخدم في المشروع 1 (Sweep) والمشروع 2 (Knob).
  • Adafruit PWM Servo Driver: ثبّتها من مدير مكتبات Arduino (ابحث عن “Adafruit PWM Servo Driver”). تُستخدم في المشروع 3.
  • Wire.h: مدمجة في Arduino IDE. وهي ضرورية للاتصال عبر I2C مع لوحة PCA9685.

البرامج الثلاثة (Sketches) كاملة في هذا المقال. أما كود مشاريعي الأخرى فمتاح على GitHub.

الدروس التالية

3 رأي حول “Arduino Servo Control Guide: SG90, PWM, and PCA9685”

أضف تعليق