PID Tuning aVT: أداة مفتوحة المصدر لضبط متحكمات PID ومراقبتها في الزمن الحقيقي

PID Tuning aVT: أداة مفتوحة المصدر لضبط متحكمات PID ومراقبتها في الزمن الحقيقي

يوليو 6, 2026·
خالد حميدي
خالد حميدي
· 7 دقيقة قراءة

المشكلة التي أردت القضاء عليها

كل مهندس ضبط حلقة PID على متحكم دقيق يعرف هذه الدورة جيداً، ولا علاقة لها بنظرية التحكم:

تعديل المعاملات ← إعادة الترجمة ← رفع الكود ← انتظار إعادة تشغيل اللوحة ← إعادة تسليح المحركات ← الاختبار ← ثم من جديد.

كل تعديل على $K_p$ أو $K_i$ أو $K_d$ يكلّفك دقيقة أو أكثر. وفي نظام غير مستقر بطبيعته يكلّفك أيضاً الحالة التي كنت فيها: النظام يسقط، والـ ESC تعيد التسليح، وتبدأ من الصفر. يتحول الضبط إلى تخمين بطيء، وهذا عكس ما يجب أن تكون عليه هندسة التحكم.

بيئات تجارية مثل MATLAB/Simulink وLabVIEW تحل هذه المشكلة، لكنها مقيّدة بالتراخيص وتحبسك داخل منظومتها. ومعظم الأدوات الأكاديمية ومفتوحة المصدر التي راجعتها إما محصورة بالمحاكاة، أو مرتبطة بعتاد محدد، أو تفتقر إلى اتصال ثنائي الاتجاه حقيقي بمعدل بيانات عالٍ.

لذلك بنيت أداتي الخاصة: PID Tuning aVT، أداة سطح مكتب مستقلة ومفتوحة المصدر تتحدث مباشرة مع المتحكم الدقيق، وتغيّر المعاملات أثناء عمل الحلقة، وتعرض لك الاستجابة فوراً.

الواجهة الرسومية لأداة PID Tuning aVT
الواجهة الرئيسية: الاتصال، ضبط PID الحي (حقل للجزء الصحيح وآخر للعشري)، حدود PWM، زر الإيقاف الطارئ، منزلق نقطة الهدف، لوحة الأوامر، ومسجّل التجارب.

فلسفة التصميم: المتحكم يبقى حتمياً

تعتمد الأداة مبدأ النمذجة السريعة للتحكم (Rapid Control Prototyping) القائم على فصل صارم بين المضيف والمتحكم:

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

يبدو هذا بديهياً، لكن كثيراً من الأدوات البسيطة تكسره، إما بجعل الحاسوب جزءاً من الحلقة أو بالسماح للواجهة بتعطيل تدفق البيانات.


المعمارية: لماذا كان تعدد الخيوط شرطاً لا خياراً

القاعدة الأولى لأي أداة ضبط حية هي أن الرسم يجب ألا يعطّل الاستقبال أبداً. إذا استغرق تحديث الرسم 30 ms وانتظرته قراءة المنفذ التسلسلي، تبدأ بفقدان العينات. والأداة التي تكذب عليك في استجابة النظام أسوأ من غيابها.

صممت المضيف وفق نمط المنتج–المستهلك متعدد الخيوط:

معمارية المنتج–المستهلك متعددة الخيوط لأداة ضبط PID
معمارية البرنامج: خيط الإدخال/الإخراج التسلسلي يصنّف البيانات الواردة ويحللها إلى طوابير آمنة للخيوط، بينما تستهلكها خيوط العرض والتحكم بشكل مستقل.
  • خيط الاتصال التسلسلي (المنتج): يقرأ تدفق البايتات الخام، ويعيد بناء الأسطر الكاملة، ويصنّف كل سطر: قياس، أو رسالة معلوماتية، أو تقرير حالة.
  • خيط معالجة البيانات: يحوّل القياسات إلى نقاط بيانات مختومة زمنياً ويضعها في 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:

المجموعةالأمرالوظيفة
ضبط PIDKp: / Kpd:الكسب التناسبي (الجزء الصحيح / العشري)
ضبط PIDKi: / Kid:الكسب التكاملي (الجزء الصحيح / العشري)
ضبط PIDKd: / Kdd:الكسب التفاضلي (الجزء الصحيح / العشري)
النظامtarget:نقطة الهدف
النظامlimit:حد إشباع خرج PID
النظامbaseSpeed:سرعة الدفع المحايدة
النظامstart / stopالتشغيل، أو الإيقاف الطارئ للمحركات
النظامresetإعادة معايرة حساس IMU
النظامsaveحفظ الإعدادات في EEPROM
النظامstatus / testتقرير المعاملات / تشغيل التشخيص
المراقبةmonitor:on / monitor:offتفعيل / إيقاف بث القياسات
لماذا قسمت المعاملات إلى جزء صحيح وجزء عشري؟ على معالج AVR بثمانية بتات، تحليل الأعداد العشرية من النص بطيء ويستهلك الذاكرة. إرسال 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):

زمن تنفيذ حلقة النظام في اختبار SIL
زمن تنفيذ حلقة نموذج MATLAB على مدى نحو 25,000 دورة (المتوسط 0.25 ms، الأدنى 0.13 ms).

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

معدل إرسال البيانات من MATLAB إلى الأداة
معدل إرسال البيانات من MATLAB مقارنة بالهدف 100 Hz.

أما على جهة الأداة، فهذه الأرقام التي تهم:

المقياسالنتيجة
معدل الحلقة المستهدف100 Hz
معدل المعالجة المقاس66 Hz
معدل الرسم54 Hz
فقدان الحزم0%

عالجت الأداة كل عينة أرسلها MATLAB دون استثناء. معدل المعالجة (66 Hz) ومعدل الرسم (54 Hz) متقاربان بما يكفي لئلا يتراكم الطابور في الجلسات الطويلة، و54 Hz أكثر من كافٍ لعين الإنسان أثناء الضبط التفاعلي.

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

التحقق، المرحلة الثانية: العالم الحقيقي غير المستقر

لا تُثبت الأداة نفسها إلا إذا صمدت على عتاد حقيقي. استخدمت المرحلة الثانية منصة توازن بمحركي BLDC صممتها وبنيتها لهذا الغرض: أرجوحة غير مستقرة بطبيعتها تحاكي ديناميكية الميلان (Pitch) لطائرة بدون طيار ثنائية المراوح.

على العتاد، أدّت الأداة مهمتها: تغيير المعاملات، وتحريك نقطة الهدف، وإعادة معايرة IMU، والإيقاف الطارئ، كلها نُفذت فوراً وظهر أثرها على الرسم في الزمن الحقيقي. لم يعد الضبط اليدوي دورة تعديل–ترجمة–رفع، بل صار حواراً مستمراً مع النظام.

والعرض الحي كشف لي أيضاً ما الذي كان يحدّ من أداء النظام: حلقة تحكم تعمل فعلياً بنحو 33 Hz بدل 100 Hz، وتداخل كهرومغناطيسي شديد من المحركات يشوّه إشارة IMU. هذا تحديداً ما صُممت الأداة لكشفه. القصة الكاملة للعتاد في منشور المنصة.

منشورات مرتبطة ضمن هذه السلسلة


مصممة لتتوسع

طبقة الاتصال مفصولة تماماً عن التحليل والعرض عبر واجهات برمجية (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.