
PID Tuning aVT: أداة مفتوحة المصدر لضبط متحكمات PID ومراقبتها في الزمن الحقيقي
المشكلة التي أردت القضاء عليها
كل مهندس ضبط حلقة PID على متحكم دقيق يعرف هذه الدورة جيداً، ولا علاقة لها بنظرية التحكم:
تعديل المعاملات ← إعادة الترجمة ← رفع الكود ← انتظار إعادة تشغيل اللوحة ← إعادة تسليح المحركات ← الاختبار ← ثم من جديد.
كل تعديل على $K_p$ أو $K_i$ أو $K_d$ يكلّفك دقيقة أو أكثر. وفي نظام غير مستقر بطبيعته يكلّفك أيضاً الحالة التي كنت فيها: النظام يسقط، والـ ESC تعيد التسليح، وتبدأ من الصفر. يتحول الضبط إلى تخمين بطيء، وهذا عكس ما يجب أن تكون عليه هندسة التحكم.
بيئات تجارية مثل MATLAB/Simulink وLabVIEW تحل هذه المشكلة، لكنها مقيّدة بالتراخيص وتحبسك داخل منظومتها. ومعظم الأدوات الأكاديمية ومفتوحة المصدر التي راجعتها إما محصورة بالمحاكاة، أو مرتبطة بعتاد محدد، أو تفتقر إلى اتصال ثنائي الاتجاه حقيقي بمعدل بيانات عالٍ.
لذلك بنيت أداتي الخاصة: PID Tuning aVT، أداة سطح مكتب مستقلة ومفتوحة المصدر تتحدث مباشرة مع المتحكم الدقيق، وتغيّر المعاملات أثناء عمل الحلقة، وتعرض لك الاستجابة فوراً.

فلسفة التصميم: المتحكم يبقى حتمياً
تعتمد الأداة مبدأ النمذجة السريعة للتحكم (Rapid Control Prototyping) القائم على فصل صارم بين المضيف والمتحكم:
- المتحكم (Arduino في هذا العمل) يملك حلقة التحكم: يقرأ الحساس، ويحسب قانون PID، ويقود المشغّلات. لا يُسمح لأي شيء من جهة الحاسوب بالدخول إلى هذه الحلقة.
- المضيف (أداة سطح المكتب) يملك كل ما يخص الإنسان: إدخال المعاملات، والعرض المرئي، والتسجيل، والتشخيص.
- رابط تسلسلي ثنائي الاتجاه يصل بينهما: المعاملات والأوامر تنزل، والقياسات تصعد، ولا يقطع أيٌّ منهما المهمة الزمنية الحرجة.
يبدو هذا بديهياً، لكن كثيراً من الأدوات البسيطة تكسره، إما بجعل الحاسوب جزءاً من الحلقة أو بالسماح للواجهة بتعطيل تدفق البيانات.
المعمارية: لماذا كان تعدد الخيوط شرطاً لا خياراً
القاعدة الأولى لأي أداة ضبط حية هي أن الرسم يجب ألا يعطّل الاستقبال أبداً. إذا استغرق تحديث الرسم 30 ms وانتظرته قراءة المنفذ التسلسلي، تبدأ بفقدان العينات. والأداة التي تكذب عليك في استجابة النظام أسوأ من غيابها.
صممت المضيف وفق نمط المنتج–المستهلك متعدد الخيوط:

- خيط الاتصال التسلسلي (المنتج): يقرأ تدفق البايتات الخام، ويعيد بناء الأسطر الكاملة، ويصنّف كل سطر: قياس، أو رسالة معلوماتية، أو تقرير حالة.
- خيط معالجة البيانات: يحوّل القياسات إلى نقاط بيانات مختومة زمنياً ويضعها في
ConcurrentQueue، وللأوامر الصادرة طابور مستقل. - خيط العرض (المستهلك): يسحب البيانات على دفعات حتى 20 عينة في كل دورة رسم، فإذا تأخر الرسم يلحق بالبيانات خلال بضعة إطارات بدل أن تتراكم.
- المسجّل: كاتب غير متزامن مستقل (
BlockingCollectionمع مهمة خلفية)، فلا تلمس عمليات القرص المسار الزمني الحرج أبداً.
هذا الفصل هو السبب الرئيسي في أن الأداة تحافظ على معالجة بمعدل 66 Hz مع 0% فقدان للحزم، كما سترى في قسم التحقق.
بروتوكول بسيط يمكن نقله إلى أي متحكم
تعمّدت أن يكون البروتوكول نصياً، مقروءاً للإنسان، وصغيراً جداً. أي متحكم دقيق يستطيع تنفيذ print() يستطيع التحدث به، ويمكنك تتبعه من أي Serial Monitor.
القياسات (من المتحكم إلى المضيف):
<Time_ms>:<output1>:<output2>
في منصة التوازن، output1 هي الزاوية المقاسة وoutput2 هي إشارة PWM، والمعنى يحدده تطبيقك. الأسطر التي تبدأ بـ >> تُعامل كرسائل معلوماتية (>> System ready.)، وأمر status يعيد كتلة محاطة بـ STATUS_START وSTATUS_END. تستخدم الواجهة هذه الكتلة عند الاتصال لتحميل المعاملات الحالية من المتحكم، فلا يختلف الحاسوب واللوحة أبداً حول القيم الفعّالة.
الأوامر (من المضيف إلى المتحكم): أسطر بسيطة بصيغة key:value:
| المجموعة | الأمر | الوظيفة |
|---|---|---|
| ضبط PID | Kp: / Kpd: | الكسب التناسبي (الجزء الصحيح / العشري) |
| ضبط PID | Ki: / Kid: | الكسب التكاملي (الجزء الصحيح / العشري) |
| ضبط PID | Kd: / Kdd: | الكسب التفاضلي (الجزء الصحيح / العشري) |
| النظام | target: | نقطة الهدف |
| النظام | limit: | حد إشباع خرج PID |
| النظام | baseSpeed: | سرعة الدفع المحايدة |
| النظام | start / stop | التشغيل، أو الإيقاف الطارئ للمحركات |
| النظام | reset | إعادة معايرة حساس IMU |
| النظام | save | حفظ الإعدادات في EEPROM |
| النظام | status / test | تقرير المعاملات / تشغيل التشخيص |
| المراقبة | monitor:on / monitor:off | تفعيل / إيقاف بث القياسات |
Kp:3 ثم Kpd:250 يعتمد على تحليل أعداد صحيحة رخيص (toInt())، ويعيد الكود بناء $K_p = 3.250$ والحلقة مستمرة في العمل. قرار صغير، لكنه يُبقي معالجة الأوامر خارج الميزانية الزمنية لحلقة التحكم.تسجيل جاهز لتعريف الأنظمة
يمكن تسجيل كل جلسة ضبط بنقرة واحدة. يكتب المسجّل كل عينة بالشكل timestamp; setpoint; angle; PWM:
41077;-5;0.46;1187
41383;-5;-1.16;1183
41690;-5;0.69;1178
41994;-5;2.35;1164
42302;-5;-0.04;1162
في نهاية كل تجربة تحدد إن كانت صالحة ✔ أو غير صالحة ✘، فيُعاد تسمية الملف بهذه اللاحقة. عادة صغيرة، لكنها توفّر ساعات من التخمين بعد يوم طويل من التجارب حول أي سجل هو الجيد. وتدخل الملفات مباشرة إلى MATLAB:
data = readmatrix('session_20251013_153200.csv');
t = data(:,1) * 1e-3; % الزمن [s]
y = data(:,3); % الزاوية المقاسة
u = data(:,4); % إشارة التحكم
من هنا يمكنك تعريف النظام (System Identification)، أو مقارنة جولات الضبط، أو رسم أشكال لورقة علمية، وهذا تماماً ما فعلته لأشكال بحثي المنشور.
التحقق، المرحلة الأولى: البرنامج داخل الحلقة (SIL)
قبل أن أثق بالأداة على عتاد حقيقي، أردت قياس الأداة نفسها بمعزل عن المحركات والضجيج وقيود المتحكم الدقيق. بنيت منصة اختبار Software-in-the-Loop: نموذج MATLAB لنظام التوازن بمحركات BLDC، متصل بالأداة عبر جسر تسلسلي افتراضي (COM1 ⇄ COM2، بسرعة 115200 bps)، على حاسوب Windows 10 بمعالج Intel i7-8550U وMATLAB R2024a.
مُثّل النظام بدالة النقل:
$$ G(s) = \frac{0.5\, L\, C_T}{J s^2 + D s} $$حيث $L = 0.301\ \text{m}$ و$C_T = 1.46\times10^{-5}\ \text{N}\cdot\text{s}^2$ و$J = 1.81\times10^{-6}\ \text{kg}\cdot\text{m}^2$ و$D = 0$.
أولاً، كان يجب أن يكون النظام الافتراضي مصدر بيانات موثوقاً. على مدى 25,000 دورة، بلغ متوسط زمن تنفيذ حلقته 0.25 ms، وهو زمن مهمل مقارنة بفترة أخذ العينات البالغة 10 ms (أي 100 Hz):

أُرسل الخرج من حلقة مستقلة حتى لا يؤثر على النموذج، ووصل معدله إلى نحو 70 رسالة في الثانية كحد أعلى:

أما على جهة الأداة، فهذه الأرقام التي تهم:
| المقياس | النتيجة |
|---|---|
| معدل الحلقة المستهدف | 100 Hz |
| معدل المعالجة المقاس | 66 Hz |
| معدل الرسم | 54 Hz |
| فقدان الحزم | 0% |
عالجت الأداة كل عينة أرسلها MATLAB دون استثناء. معدل المعالجة (66 Hz) ومعدل الرسم (54 Hz) متقاربان بما يكفي لئلا يتراكم الطابور في الجلسات الطويلة، و54 Hz أكثر من كافٍ لعين الإنسان أثناء الضبط التفاعلي.


التحقق، المرحلة الثانية: العالم الحقيقي غير المستقر
لا تُثبت الأداة نفسها إلا إذا صمدت على عتاد حقيقي. استخدمت المرحلة الثانية منصة توازن بمحركي BLDC صممتها وبنيتها لهذا الغرض: أرجوحة غير مستقرة بطبيعتها تحاكي ديناميكية الميلان (Pitch) لطائرة بدون طيار ثنائية المراوح.
على العتاد، أدّت الأداة مهمتها: تغيير المعاملات، وتحريك نقطة الهدف، وإعادة معايرة IMU، والإيقاف الطارئ، كلها نُفذت فوراً وظهر أثرها على الرسم في الزمن الحقيقي. لم يعد الضبط اليدوي دورة تعديل–ترجمة–رفع، بل صار حواراً مستمراً مع النظام.
والعرض الحي كشف لي أيضاً ما الذي كان يحدّ من أداء النظام: حلقة تحكم تعمل فعلياً بنحو 33 Hz بدل 100 Hz، وتداخل كهرومغناطيسي شديد من المحركات يشوّه إشارة IMU. هذا تحديداً ما صُممت الأداة لكشفه. القصة الكاملة للعتاد في منشور المنصة.
منشورات مرتبطة ضمن هذه السلسلة
- 🛠️ منصة التوازن بمحركي BLDC: النظام التجريبي: التصميم الميكانيكي، والنمذجة الديناميكية، والتحكم المدمج، وتحليل التداخل الكهرومغناطيسي.
- 📄 البحث المنشور في المجلة التركية للهندسة: الفجوة البحثية، والمنهجية، والنتائج، وطريقة الاستشهاد.
مصممة لتتوسع
طبقة الاتصال مفصولة تماماً عن التحليل والعرض عبر واجهات برمجية (ISerialCommunicator وIDataStreamProcessor وIPlotService). الاتصال التسلسلي مجرد وسيلة النقل الحالية، ويمكن نقل المعمارية نفسها إلى MQTT أو HTTP أو WebSocket للمراقبة عن بُعد دون المساس بنواة التطبيق. ولأن البروتوكول مستقل عن نوع المتحكم، يمكن للأداة نفسها ضبط منصة توازن، أو حلقة سرعة لمحرك DC، أو متحكم حرارة، أو روبوت تتبع خط.
التقنيات المستخدمة
- المضيف: C# / .NET (Windows Forms)، async/await،
ConcurrentQueue،BlockingCollection - المتحكم: Arduino (ATmega328P)، مكتبات
PID_v1وMPU6050_light، وحفظ الإعدادات في EEPROM - التحقق: MATLAB R2024a (نموذج SIL والتحليل)، جسر تسلسلي افتراضي
- الترخيص: مفتوح المصدر. حمّلها من GitHub.