این کد که نوشتی را دقیق نمی دانم چه انتظار داری انجام دهد! اما در ابتدای کد که اصلا error را محاسبه نکردی که بعدش بخواهی اگر بین 5 و 5- بود یک کارایی بکند؟ (error صفر باقی می ماند)
مباحث پایه ای را دوستمون farzadsw توضیح داد و من چند نکته عملی اضافه می کنم
در کنترلر آنالوگ خیلی ساده زمانی که بخواهی بدون ریاضیات یک کنترلر PID درست کنی روش معمول این است که
در ابتدا با I=0,D=0 شروع می کنی و پارامتر P را در حدی زیاد می کنی که سیستم در حد
مرز شروع به نوسان برسد
بعد پارامتر D را زیاد می کنی تا حدی که یک نوسان کوچولو رخ دهد
در آخر با پارامتر I بازی می کنی تا نوسان از بین برود
تاثیر D در یک کنترلر ساده این است که
سرعت رسیدن به نقطه مورد نظرت را تعیین می کند (که در دنیای فیزیکی چنین المانی وجود ندارد ) و تاثیر I هم این است که
دقت رسیدن نقطه setpoint مورد نظر را تعیین می کند( جبران خطاي ماندگار) بنابراین در مواردی که سرعت رسیدن به نقطه موردنظر مهم نباشد PI کنترلر کافی است.(یعنی اغلب موارد ساده)
مشکل D هم این است که در عمل اگر در محیط نویز شدید باشد D آن را تقویت می کند و در بعضی موارد کل حلقه کنترلر را از کار می اندازد !
در کنترلر دیجیتال هم اصول کار یکی است و برای تحقق PI در حقیقت الگوریتم زیر است
esum = esum + e
y = Kp * e + Ki * Ta * esum
e انحراف از نقطه هدف
esum جمع انحرافهای قبلی از نقطه هدف است .
Ta زمان نمونه برداری است برای تحقق انتگرالگیر (توضیحش کمی ریاضیات می خواد و چون نوشتی هنوز دانشگاه نرفتی توضیح نمی دم یک عدد 1 در ابتدا قرار بده تا بعد اگر عمکرد کنترلر مناسب نبود تغییر بدهی)
این موارد را برای این نوشتم که در نظر داشته باشی اولا چه کنترلری مناسب کارت است و بعد هم وقتی پارامترهای کنترلر را تغییر می دهی چه خروجی را
می توانی انتظار داشته باشی
این کد را با انجام تغییرات مورد نیازت استفاده کن
double esum=0;
double KP=xx;
double KI=xx;
double Ta=xx;
double y;
double PI_Berechnung (double x, double w)
{
e =w-x;
if ((y < 1023)&&(y > 0))
{ // (Anti-Windup)
esum = esum + e;
}
y = (Kp*e)+(KI*Ta*esum);
if (y > 1023)
{
y = 1023;
}
if (y < 1)
{
y = 0;
}
return y;
}
پارامترهای کنترلر را چون از سیستمت اطلاعی ندارم خودت باید تکمیل کنی
نکته مهم استفاده از double است برای تعریف متغیرها چون اگر int تعریف کنی و در محاسبات مثلا 0.5 باشد سیستم به 0 گرد می کند و در نتیجه کنترلر محاسبات درستی انجام نمی دهد.
anti-windup هم در کد که نوشتم برای یک خروجی dac مقادیر دیجیتال بین 0 تا 1023 دسیمال است و ظاهرا در کاربرد که داری می توانی مستقیم 5 و 5- بدهی که آن را هم خودت تغییر بده.
ننوشتی از چه پروسسوری استفاده می کنی به هر حال اگر از میکروهای معمولی است که باید وقفه یک تایمر را برای اجرای این تابع صدا کنی اگر هم از یک پروسسوری که لینوکس روش پورت شده مثل arm یا cortex یا هرچی ... استفاده می کنی که باید یک thread تعریف کنی حقیقت یک پروسس موازی با برنامه اصلی تعریف می شود (مالتی پروسس) که اگر لازم داشتی بعد توضیح می دهم.
البته در یک ربات واقعی سیستم چند ورودی و چند خروجی دارد که ورودیها بر هم تاثیر دارند و بررسی این سیستم ها در کنترل به روش State space تعریف می شود که اگر لازم داشتی بعدا می توان صحبت کرد.