PID Controller

ESP8266 PID

در این مطلب می خواهم کمی در مورد PID صحبت کنم. وقتی می‌گم کمی، یعنی قرار نیست تاریخچه و کلی فرمول براتون ردیف کنم. و فقط می‌خواهم یک توضیح مختصر بدم و کد برنامه را براتون بنویسم.

طبق معمول پروژه‌ای را انجام می‌دادم که احتیاج به PID داشت. یک کتابخانه‌ی خوب هم در آردوینو هست براش. ولی طبق معمول تا نفهمم که این PID چطوری کار می‌کنه و مفهومش چیه اصلا برام جالب نیست. برای همین اول یک خلاصه در مورد PID صحبت کنیم.

 

پیش از PID

ساده ترین روش کنترل یک فرایند نوشتن یک کد شرطی است. برای مثال فرض کنید یک دستگاه تولید جوجه داریم و می‌خواهیم که دمای داخل آن از 30 درجه پایین تر نیاید. برای این کار ما یک هیسترسیز برای دمای مورد نظر در نظر می‌گرفتیم. مثلا 29 و 31. می گفتیم اگر دما از 29 کمتر شد المنت روشن شود و اگر از 31 بیشتر شد المنت خاموش شود. این ساده‌ترین روش بود ولی دما دارای یک نوسان می‌شود و ما بین 29 و 31 در حال نوسان است. ولی شاید ما بخواهیم که دما دقیقا روی 30 درجه ثابت بماند. اگر هیسترسیز را حذف کنیم المنت خیلی سریع خاموش روشن می‌شود. و از نظر مکانیکی امکان پذیر نیست.

 

PID

PID یک روش کنترل فرآیند است. که برعکس روش قبلی، برای کنترلهای آنالوگ کاربرد دارد. مثلا وقتی که المنت ما بجای اینکه فقط امکان خاموش و روشن شدن داشته باشد. امکان تنظیم درجه و شدت داشته باشد. یا برای کنترل شیر آب که در روش قبلی فقط امکان خاموش و روشن کردن بود مثل شیربرقی، در اینجا امکان کم و زیاد کردن شیر وجود داشته باشد.

موردی که من خودم تجربه کردم و بررسی لازم داشت، انتظار ما از کنترل است. در پروژه‌ی من فقط کنترل برای افزایش نیافتن دما بود و اگر دما به هر دلیلی پایین‌تر از دمای مورد نظر ما بود لازم نبود کاری صورت گیرد. فرض کنید با یک فن می خواهیم دمای اطاقی را کنترل کنیم تا دما از 30 بالاتر نرود. ولی اگر پایینتر رفت مثلا شبها لازم نیست کاری صورت گیرد. فقط لازم است از 30 درجه بالاتر نرود. این قسمت را بعدا بیشتر توضیح خواهم داد.

حالا بر می گردیم به توضیح PID. فرض کنید منبع آبی داریم و می خواهیم که سطح آب داخل آن روی سطح مشخصی ثابت بماند، در صورتی که خروجی آب از منبع میزان ثابتی نیست و در بازه های زمانی کم و زیاد می‌شود. شیر ورودی از صفر تا 180 قابل بسته و باز شدن است. اگر بخواهیم بصورت دستی کنترل کنیم. وقتی مصرف آب زیاد میشود و سطح آب پایین می‌آید. اول لازم است شیر ورودی بیشتر از شیر خروجی باز شود تا وقتی که سطح آب به حد انتظار برگردد. و بعد با نزدیک شدن به آن شیر را کمی ببیندیم تا سطح آب با وجود خروج آب از منبع، ثابت بماند. حال می‌خواهیم این کار را PID برای ما انجام دهد.

 

فرمول PID

PID از سه بخش یا پارامتر قابل تنظیم تشکیل شده است. شکل کلی فرمول PID به صورت زیر است.

PID

شرح فرمول PID

  • P اول کلمه‌ی Proportional به معنای متناسب است. P قسمت اول فرمول است که در فرمول دارای یک ضریب به نام Kp است، که از طرف ما مشخص می‌شود. این ضریب در ارور(اختلاف سطح آب با مقدار مد نظر ما) ضرب می‌شود و باعث می‌شود قسمت اول فرمول ما متناسب با ارور افزایش و کاهش یابد. فرض کنید Kp را 2 قرار داده‌ایم و سطح آب 30 سانت پایین‌تر از سطح مورد نظر ما قرار دارد. پس ارور ما می‌شود 30 که در 2 ضرب شده و حاصل 60 می‌شود. پس خروجی تابع ما می‌شود 60. تا اینجا شیر آب ورودی روی 60 درجه قرار می‌گیرد. فرض کنید مقدار آب ورودی از خروجی بیشتر است و ارور ما در حال کم شدن. همینطور که ارور کم می‌شود به جایی می‌رسیم که آب ورودی با خروجی دقیقا برابر می‌شود. مثلا درجه شیر خروجی روی 50 است و وقتی ارور ما به 25 برسد، شیر ورودی هم روی 50 قرار میگیرد. از اینجا به بعد بخش P کاربرد خود را از دست می‌دهد. چرا؟ چون اگر ارور بخواهد کمتر بشود پس درجه شیر ورودی هم کمتر شده و دوباره سطح آب پایین‌تر می‌رود و ارور افزایش پیدا می‌کند. شاید بگویید خب کاری نداره ضریب Kp را یک عدد بیشتر می‌گذاریم. مثلا 10 خوبه؟ باز هم اگر در فرمول جایگزین کنیم، می‌بینیم که وقتی ارور به 5 برسد درجه‌ی شیر ورودی با خروجی برابر شده و ارور ما همچنان باقی می‌ماند. در اینجا است که بخش دوم یا “I” به کمک ما می‌آید.
  • I اول کلمه‌ی Integral است.که در فرمول قسمت دوم است. انتگرال ارور در یک ضریب که با Ki نشان داده شده است و ما تنظیم می‌کنیم، ضرب می‌شود. همانطور که می‌دانید انتگرال اندازه‌ی سطح زیر نمودار است. تا اینجا ارور ما 25 بود. فرض کنید ضریب Ki را هم روی 0.5 تنظیم کرده ایم و بازه زمانی نمونه گیری ما هم دقیقه است. در دقیقه اول ارور ما 25 است که اگر در نیم ضرب کنیم می‌شود 12.5، و این مقدار با مقدار اول فرمول ما یا همان P جمع می‌شود. حاصل می‌شود 62.5 . پس درجه شیر ورودی ما روی 62.5 قرار می‌گیرد. پس مقدار ورودی آب از خروجی بیشتر شده. پس انتظار داریم در دقیقه‌ی دوم مقدار ارور ما باز هم کمتر شود. فرض کنید ارور ما در دقیقه دوم به 10 رسیده باشد. انتگرال نمودار ارور ما می‌شود 25 که از قبل بود بعلاوه‌ی 10 که میشود 35، ضربدر 0.5 میشود 17.5. پس در دقیقه‌ی دوم درجه شیر ما روی 67.5 قرار می گیرد. و همینطور که مشخص است در دقیقه سوم انتظار میره که خطای ما منفی شود و سطح آب از مقدار مد نظر ما بیشتر شود. در اینجاست که مقدار انتگرال ما هم کاهش پیدا می کند. این نوسان در اطراف سطح مورد نظر ما آنقدری ادامه پیدا می کند تا به ثبات برسد. ولی برای اینکه سریعتر به ثبات برسیم به بخش سوم نیاز پیدا می‌کنیم.
  •  اول کلمه‌ی Derivative به معنای مشتق است. که در فرمول قسمت سوم می‌باشد. مشتق هم در یک ضریب به اسم Kd که توسط ما تنظیم می‌شود، ضرب می‌شود. همانطور که می‌دانید مشتق شیب نمودار است و در اینجا شیب نمودار ارور ما می‌باشد. کار اصلی این بخش این است که از نوسانات شدید جلوگیری کند. وقتی ارور ما از 25 در دقیقه‌ اول به 10 در دقیقه‌ی دوم رسید مشتق آن می‌شود 15-.  که اگر ضریب Ki را یک در نظر گرفته باشیم. مقدار خروجی فرمول ما می‌شود 67.5 منهای 15 که میشود 52.5. میبینید که باز شدن شیر کمی آرامتر شد و از شدت آن جلوگیری شد. پس نمودار ارور ما با شیب و شتاب بهتری به سمت صفر میرود.

 

اینکه این سه پارامتر را چه اعدادی بگذاریم بسته به نوع فرآیند ما متفاوت است و باید تجربه کسب کرد.

 

نکته‌: انواع PID داریم و فقط همین یک مدل نیست. در مدلی دیگر مقدار بدست آمده در قسمت اول به عنوان ورودی به دو بخش بعدی داده می‌شود. در اینجا من کد همین طریقی که توضیح دادم را می‌نویسم که ارور حساب می‌شود و بصورت موازی به سه بخش داده می‌شود و حاصل جمع می‌شود.
نکته: یادتونه گفتم شاید در فرآیندی مهم نباشد که مثلا دما اگر پایین آمد؟ در اینجور مواقع ما PID را موقعی وارد جریان کنترل می کنیم که دما از حد مجاز بالاتر رفت. چون اگر از اول PID فعال باشد آنقدر مقدار انتگرال زیاد میشود که کار ثابت نگه داشتن ارور مشکل می‌شود.
نکته: در بعضی از فرآیندها هم می توان اول قسمت P را فعال کرد و وقتی که ارور به مقدار معینی کم شد بعد بخش های بعدی را وارد کرد. کلا خیلی روش های مختلفی برای استفاده از PID  وجود دارد.

 

PID

 

کد PID

در ادامه کد PID را پیاده کرده‌ام.

unsigned long currentTime, previousTime;
double        lastError;
double        setPoint = 30;
double        cumError, rateError;
float         kP = 2,kI = 0.5,kD = 1;

float computePID(float inp){     
  currentTime = millis();                //get current time
  float elapsedTime = (float)(currentTime - previousTime);        //compute time elapsed from previous computation
 
  float error = setPoint - inp;                                // determine error
  cumError += error * elapsedTime;                // compute integral
  rateError = (error - lastError)/elapsedTime;   // compute derivative

  float out = kP*error + kI*cumError + kD*rateError;                //PID output               

  lastError = error;                                //remember current error
  previousTime = currentTime;                        //remember current time

  return out;                                        //have function return the PID output
}




شرح کد

در قسمت اول متغیر های مورد نیاز را تعریف می‌کنیم.

در ادامه تابع محاسبه PID را نوشتم، که زمان سپری شده را حساب می‌کند. سپس ارور را بدست می‌آورد و از روی ارور انتگرال و مشتق را بدست آورده. هر سه را با هم جمع کرده و به عنوان خروجی بر می‌گرداند.

امیدوارم این آموزش مفید بوده باشه.

 

 

دیدگاه ها :

من بات نیستم

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *