مقدمه
همانطور که میدانید، کنترلکنندههای مختلفی در علم مهندسی کنترل ارایه شدهاست. هر کدام از این کنترلکنندهها بسته به نوع کنترل و نیازمندیهای سیستم کنترل، مورد استفاده قرار میگیرند. یکی از بهترین و رایجترین روشهای کنترلی، الگوریتم منطق فازی است که توسط پروفسور لطفیزاده ارایه شد. این الگوریتم بهنوعی بر پایه هوشمصنوعی استوار بوده و با در نظر گرفتن خروجیهای مختلف بهازای شرایط مختلف، بهترین و منعطفترین پاسخدهی به روند کنترل را مهیا میسازد.
در این مطلب قرار است به شما نحوه پیادهسازی کنترلکننده فازی را بر روی میکروکنترلر آموزش داده شود. این عمل به دو روش امکانپذیر میباشد: الف) پیادهسازی کامل منطق فازی (بههمراه تمامی جزئیات که شامل توابع عضویت مختلف میباشد) و ب) پیادهسازی با استفاده از استخراج یک جدول بهعنوان Lookup Table. چنانچه روش اول را بر روی میکروکنترلر پیادهسازی شود، با توجه به محدودیتهای میکروکنترلر از نظر حافظه یا پردازش، ممکن است با مشکلاتی مواجه شود؛ از اینرو، میتوان با استخراج یک Lookup Table بهوسیله مقداردهی (Evaluation) به الگوریتم فازی، این عمل را انجام داد که میزان پردازش و اشغال حافظه بهطور چشمگیری کاهش و البته از طرفی، میزان دقت نیز کاهش خواهد یافت؛ که میتوان با افزایش دقت و تعداد بازهها در دستهبندی مقادیر ورودی، این مشکل را نیز برطرف کرد.
معمولا برای شبیهسازی سیستمهای کنترل، از Simulink (که یکی از ابزارهای قدرتمند نرمافزار متلب MATLAB میباشد) استفاده میشود و با توجه به اینکه بلاک و توابع کنترلکننده فازی در این برنامه بهصورت آماده موجود است، از سختی کار کاسته خواهد شد.
مراحل
1. آمادهسازی ساختار الگوریتم فازی: در ابتدا بایستی پارامترهای الگوریتم فازی مانند: الف) ورودیها و خروجیها (Inputs & Outputs)، ب) توابع عضویت (Membership Functions) و پ) قوانین (Rules) را تعریف کنید. چنانچه این پارامترها را از قبل آماده کردهاید، به مرحله 4 پرش کنید. برای ایجاد یک سیستم فازی جدید، کافیست از GUI مربوط به فازی در نرمافزار متلب اقدام کنید. برای اینکار، در پنجره دستورات (Command Window) عبارت fuzzy
را وارد نمایید. پنجرهای با عنوان Fuzzy Logic Designer گشوده میشود. در حالت پیشفرض، سیستم استنتاج فازی یا همان Fuzzy Inference System یا بهطور مخفف FIS، بر روی Mamadani تنظیم شدهاست. چنانچه نیاز به تغییر این مورد دارید، از نوار ابزار بالا در قسمت File > New FIS، مطلوب خود را انتخاب کنید.
2. تعریفنمودن پارامترهای الگوریتم فازی: توسط Edit > Add Variable ورودی و خروجیها، توسط Edit > Membership Functions توابع عضویت و توسط Edit > Rules قوانین را میتوانید تعریف کنید؛ ضمنا، توسط View > Rules یا View > Surface میتوانید الگوریتم را ارزیابی و عیبیابی (Debug) کنید.
3. استخراج ساختار الگوریتم فازی: در این مرحله بایستی از ساختار الگوریتم موردنظر خود در قالب یک فایل یا یک متغیر خروجی بگیرید. برای اینکار از طریق File > Export اقدام کنید.
4. ایجاد ماتریس Lookup Table: حال کافیست با استفاده از تابع آماده Fuzzy2Lookup (که در بخش دانلود قرار گرفته شدهاست)، الگوریتم فازی را به یک Lookup Table تبدیل کنید. آرگومانهای ورودی و خروجی این تابع بهصورت زیر قابل تعریف میباشد:
function Lookup = Fuzzy2Lookup(FIS, Input)
که در آن:
- FIS همان ساختار الگوریتم بهصورت فایل یا متغیر میباشد.
- Input محدوده مقداردهی را تعیین میکند؛ که شامل یک آرایه سلولی است که در هر سلول آن، مقادیر مقداردهیشده متناظر با شماره ورودی از FIS موجود است.
- Lookup در واقع همان Lookup Table خروجی است.
4.1. آمادهسازی آرگومان FIS: چنانچه ساختار الگوریتم بهصورت فایل میباشد، بایستی آنرا توسط تابع readfis به یک متغیر تبدیل کنید و سپس بهعنوان آرگومان FIS به تابع تحویل دهید؛ در غیر اینصورت، کافیست متغیر FIS واقع در Workspace را بهطور مستقیم به آرگومان مربوطه تحویل دهید.
FIS = readfis('Test');
4.2. آمادهسازی آرگومان ورودی Input: چنانچه خواسته باشید مقادیر ورودی Input را در یک بازه به n مقدار با فاصله یکسان از یکدیگر تقسیم کنید، میتوانید از تابع linspace استفاده نمایید:
Input = {
linspace(-1, 1, 7);
linspace(-1, 1, 7);
};
بهعنوان نمونه، چنانچه خواسته باشید مقادیر ورودی Input را بهطور دلخواه مشخص کنید:
Input = {
[-1 -.9 -.75 -.5 -.2 0 .1 .3 .4 .8 .95];
[-1 -.9 -.75 -.5 -.2 0 .1 .3 .4 .8 .95];
};
بهعنوان نمونه، چنانچه خواسته باشید مقادیر ورودی Input را با یک گام افزایش معین تعریف کنید:
Input = {
-1 : .25 : 1;
-1 : .25 : 1;
};
4.3. پردازش و دریافت جدول: پس از آمادهسازی آرگومانهای ورودی، توسط دستور زیر میتوانید Lookup Table موردنیاز خود را ایجاد کنید:
LookupTable = Fuzzy2Lookup(FIS, Input);
5. تبدیل سیستم فازی به نویسههای کد زبانهای مختلف: همچنین، توسط دستور زیر میتوانید سیستم فازی را بهطور مستقیم به کد قابل پشتیبانی توسط زبان موردنظر خود تبدیل کنید (در حال حاضر تنها تابع تبدیل زبان سی C توسعه داده شدهاست و در آینده احتمال اضافهشدن زبانهای دیگر نیز فراهم آورده میشود):
Snippet = FIS2CArray(FIS, Input, Precision);
که آرگومان سوم یعنی Precision، تعداد ارقام اعشار (دقت) را بهازای هر مقدار از جدول تعیین میکند؛ و نویسههای کد زبان سی C، در متغیر Snippet ذخیره شدهاست که میتوان توسط دستورهای fopen – fprintf – fclose آنرا بر روی یک فایل ذخیره کرد (میتواند بهصورت یک هِدِر فایل Header File در پوشه اصلی پروژه میکروکنترلر ذخیره و استفاده شود).
6. پیادهسازی در IDE میکروکنترلر: پس از درج کدهای تولید شده یا Include کردن هدر فایل در برنامه میکروکنترلر، بایستی روند فراخوانی داده از روی این Lookup Table را با توجه به شرایط فعلی (ورودیهای سنسور و وضعیتهای مختلف) ایجاد کرد. برای درک بهتر موضوع، در ادامه بهصورت پروژه محور در قالب یک پروژه نمونه مراحل آموزش پیش برده میشود.
7. تشکیل ورودیهای الگوریتم فازی در برنامه میکروکنترلر: فرض کنید قرار است دمای یک اتاق کنترل شود. کنترلکننده فازی و پارامترهای مربوط به آن از پیش (طی مراحل 1 الی 5) آمادهسازی شدهاست. کدهای تولیدشده را بهصورت یک هدر فایل در IDE میکروکنترلر include میشود:
#include "Fuzzy.h"
که اجزای مختلف این فایل بهصورت زیر تعریف میشود:
- تعداد شرایط/ستون/سطر موجود در جدول Lookup را بهازای هر ورودی در خود ذخیره کردهاست:
const int InputSize[2] = {10,10};
- شرایط بازهبندیشده مربوط به متغیر ورودی شماره یک (خطا):
float Error_Conditions[10] = {-1.00000,-0.77778,-0.55556,-0.33333,-0.11111,0.11111,0.33333,0.55556,0.77778,1.00000};
- شرایط بازهبندیشده مربوط به متغیر ورودی شماره دو (تغییرات خطا):
float ErrorChangeRate_Conditions[10] = {-1.00000,-0.77778,-0.55556,-0.33333,-0.11111,0.11111,0.33333,0.55556,0.77778,1.00000};
- جدول Lookup برای خروجی شماره یک (سیکلوظیفه دستگاه گرمکننده):
const float Heater_FuzzyRules[10][10] = {{ ... }, ... };
- جدول Lookup برای خروجی شماره دو (سیکلوظیفه دستگاه خنککننده):
const float Cooler_FuzzyRules[10][10] = {{ ... }, ... };
ورودیهای الگوریتم فازی در این پروژه، الف) خطا و ب) تغییرات خطا (مشتق خطا در واحد زمان)، در نظر گرفته شدهاست. خروجیهای این کنترلکننده از دو متغیر به نامهای Heater و Cooler تشکیل شدهاست؛ که هر دو اعدادی در بازه 0 الی 1 بوده و سیکلوظیفه (Duty Cycle) هر کدام از این دو خروجی را مشخص میکند. در گام اول، بایستی روند نمونهبرداری از سنسورها را ایجاد کرد که در این حین، دو متغیر ورودی یعنی خطا و تغییرات خطا تشکیل میشود. روند نمونهبرداری در بازههای زمانی ثابت و مشخص انجام میگیرد؛ لذا، میتوان با استفاده از امکانات شمارندههای (Timers) تعبیهشده در میکروکنترلر و ایجاد یک ISR در کد، همچنین تنظیم زمان سرریز شدن تایمر، بازه زمانی نمونهبرداری موردنظر خود را ایجاد نمایید. مراحل نمونهبرداری از سنسور و تشکیل متغیرهای ورودی بهصورت زیر تعریف شدهاست. البته روش گفتهشده در این مطلب کاملا ساده بیان شدهاست و تنها جنبه آموزشی دارد و استفاده از آن در فرایندهای صنعتی پیشنهاد نمیشود (مگر اینکه از روشهایی نظیر Moving-Average استفاده شود):
1 2 3 4 5 |
setPoint = (200 * (float) read_adc(0) / 1024) - 100; // Current method of raw-sampling is not recommended. Prefer using Moving-Average method. t = setPoint - temp; errorChangeRate = t - error; error = t; |
8. بررسی نقطهکار (Operating Point) ورودیهای فرایند کنترل طبق بازهبندی الگوریتم فازی: اگر به یاد داشته باشید، در مرحله 4.2، دادههای ورودی به بازههای مختلف تقسیمبندی شد و در برنامه میکروکنترلر بایستی شرایط مختلف نقطهکار را در این بازهها مشخص کرد. به بیانی سادهتر، بایستی بررسی کرد که در حال حاضر شرایط ورودی در کدام ناحیه از جدول Lookup Table صدق میکند (تا مقادیر متناظر با این شرایط از جدول استخراج، و در خروجی تحویل داده شود). لازم به ذکر است که در پروژه نمونه بهدلیل وجود دو ورودی (خطا و تغییرات خطا)، نیاز به بررسی دو نقطهکار میباشد. بهطور کلی این بررسی را بایستی بهازای هر ورودی انجام داد تا بتوان مختصات خروجیهای متناظر با این شرایط را از روی جدول استخراج کرد. میتوان بهصورت دستی و یا اتوماتیک (توسط توابع دستساز) این مورد را بررسی کرد؛ که استفاده از روش دوم پیشنهاد میشود. در این خصوص، تابعی دستساز در اختیار شما قرار گرفته میشود:
int getCondition(float value, float conditions[], int size)
که در آن:
- value مقدار فعلی ورودی مربوطه است.
- conditions شرایط تعیینشده (بازهبندی یا تقسیمبندیهای اعمال شده) است.
- size تعداد شرایط موجود در conditions است.
- مقدار خروجی نیز اندیس را باز میگرداند.
نحوه استفاده از این تابع در پروژه نمونه:
errorCond = getCondition(error / 30, Error_Conditions, InputSize[0]);
errorChangeCond = getCondition(errorChangeRate / 2, ErrorChangeRate_Conditions, InputSize[1]);
9. اعمال خروجیهای متناظر به ادوات کنترلی (Actuators): پس از دریافت نقطهکار بهازای هر ورودی (اندیس یا مختصات درایه/سلول در جدول)، میتوان خروجیهای متناظر با آن شرایط را از جدول استخراج کرد و به خروجیها اعمال نمود:
heater = Heater_FuzzyRules[errorCond][errorChangeCond];
cooler = Cooler_FuzzyRules[errorCond][errorChangeCond];
ویدیوهای پیشنمایش
ویدیو پیشنمایش از عملکرد پروژه نمونه در شبیهسازی پروتیوس Proteus
ویدیو پیشنمایش از برنامه GUI تولیدکننده کد
تصویر پیشنمایش از شبیهسازی مدار نمونه در پروتیوس Proteus
بخش دانلود
شامل موارد زیر:
- توابع تبدیل و تولیدکننده کد (بهصورت m-File در متلب)
- برنامه GUI + سورس کد
- فایل شبیه سازی پروژه نمونه با Proteus 8.9
- سورس کد کامل پروژه نمونه به زبان سی C در نرمافزار کدویژن CodeVision AVR
- کد هگز مخصوص پروگرام کردن میکروکنترلر
توجهات:
سلام.
تو توضیحات نوشته شده برنامه GUI به همراه سورس کد آن، من برنامه را خریداری و دانلود کردم بر طبق توضیحات همه چیز بود بغیر از سورس کد GUI .
لطفا راهنمایی بفرمایید.
با تشکر.
با درود؛
برنامه GUI و بهطور کلی برنامههای متلب در بخش دانلود بهصورت رایگان، و تنها فایلهای پروژه نمونه برای خرید قرار داده شده است.