در این قسمت از پروژه های آردوینو قصد داریم تا تنها به وسیلهی یک آردوینو و بدون هیچگونه مدار جانبی، فیلترهای بالا گذر، میان گذر، میان ناگذر و فیلتر کالمن را طراحی کنیم! البته در نظر داشته باشید که فیلتر طراحی شده، بیشتر جنبه آموزشی داشته و ممکن است در بعضی موارد پاسخ درستی نداشته باشد. اما به طور کلی، برای درک عملکرد فیلترها میتواند مفید باشد. هدف از این مقاله، بررسی و تست این موضوع است که آیا با آردوینو میتوان یک فیلتر طراحی کرد؟
با این آموزش از سیسوگ همراه باشید.
تفاوت فیلتر دیجیتال با آنالوگ
فیلترهای آنالوگ، فیلترهایی هستند که از قطعات مداری مثل مقاومت، خازن، سلف و آمپلیفایرها ساخته شدهاند. در حالی که فیلترهای دیجیتال، اغلب درون یک تراشه تعبیه شدهاند. مثلاً درون واحد میکروکنترلر، Soc، پردازندهها، DSP و… فیلترهای دیجیتال، در فیلتر کردن بسیار دقیقتر عمل میکنند، اما سیگنال باید بهصورت دیجیتال باشد.
شاید برای شما مفید باشد: پری آمپلی فایر چیست؟
همچنین بخوانید:
طراحی فیلتر در آردوینو
در این مقاله قصد داریم تا فیلترهای بالاگذر، میان گذر، میان نگذر و فیلتر کالمن را به عنوان نمونه، با استفاده از آردوینو طراحی کنیم. در این آموزش ما از یک پتانسیومتر برای تولید سیگنال و از واحد A2D آردوینو برای دریافت و فیلتر مقادیر استفاده میکنیم.
فیلتر بالاگذر
فیلتر بالا گذر بر خلاف فیلتر پایین گذر، فقط سیگنالهای با فرکانس بالا را از خود عبور میدهد و همچنین روش مناسبی برای فیلتر کردن نویزهای فرکانس پایین میباشد.
شاید راه بهتر و کارآمدتری برای طراحی فیلتر بالا گذر وجود داشته باشد، اما در اینجا (آردوینو) میخواهیم ابتدا سیگنال ورودی را از یک فیلتر پایین گذر عبور داده و سپس نتیجه حاصله را از سیگنال اصلی کم کنیم. در این صورت، تنها فرکانسهای بالای سیگنال باقی میماند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //Global Variables int sensorPin = 0; //pin number to use the ADC int sensorValue = 0; //initialization of sensor variable, equivalent to EMA Y float EMA_a = 0.3; //initialization of EMA alpha int EMA_S = 0; //initialization of EMA S int highpass = 0; void setup(){ Serial.begin(115200); //setup of Serial module, 115200 bits/second EMA_S = analogRead(sensorPin); //set EMA S for t=1 } void loop(){ sensorValue = analogRead(sensorPin); //read the sensor value using ADC EMA_S = (EMA_a*sensorValue) + ((1-EMA_a)*EMA_S); //run the EMA highpass = sensorValue - EMA_S; //calculate the high-pass signal Serial.print(sensorValue); Serial.print(" "); Serial.println(highpass); delay(20); //20ms delay } |
برای اجرای این فیلتر، ابتدا مدار زیر را بسته و سپس کد بالا را بر روی آردوینو خود آپلود کنید. دقت داشته باشید که ورودی پایهی A0 آردوینو میباشد. به عنوان مولد سیگنال نیز، میتوانید از یک پتانسیومتر (مثلاً 5 کیلو اهم) استفاده کنید.
برای مشاهده خروجی، از سریال پلاتر خود آردوینو استفاده کنید. برای باز کردن پنجره پلاتر، میتوانید از کلید ترکیبی Ctrl + Shift + L استفاده کرده و یا از طریق منوی زیر اقدام کنید:
Tools -> Serial Plotter
پلاتر آردوینو ابزاری است که به شما این امکان را میدهد که بدون نصب هیچ نرم افزار جانبی، مقادیر آردوینو را بر روی یک نمودار مشاهده کنید. همچنین از دیگر قابلیتهای این ابزار، دریافت و رسم همزمان چند نمودار میباشد.
سیگنال اصلی (آبی) و نتیجه اعمال فیلتر بالا گذر (قرمز) توجه داشته باشید که ممکن است فیلتر صحیح عمل نکرده باشد.
فیلتر میان گذر (باند)
فیلتر میان گذر، همان فیلتری است که یک ایستگاه (باند) مشخص را در رادیو برای شما جدا میکند. ایده ما برای اجرای فیلتر میان گذر، اجرای دو فیلتر EMA مجزا با فرکانسهای قطع متفاوت است. وقتی همزمان دو فیلتر بر روی یک سیگنال قرار دهید، که یکی سیگنال را تا فرکانس بالا عبور داده و دیگری از فرکانس قطع پایین به بعد عبور میدهد، اگر دو سیگنال بهدست آمده را از سیگنال اصلی کم کنیم، سیگنال میان گذر ایجاد میشود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | //Global Variables int sensorPin = 0; //pin number to use the ADC int sensorValue = 0; //initialization of sensor variable, equivalent to EMA Y float EMA_a_low = 0.3; //initialization of EMA alpha float EMA_a_high = 0.5; int EMA_S_low = 0; //initialization of EMA S int EMA_S_high = 0; int highpass = 0; int bandpass = 0; void setup(){ Serial.begin(115200); //setup of Serial module, 115200 bits/second EMA_S_low = analogRead(sensorPin); //set EMA S for t=1 EMA_S_high = analogRead(sensorPin); } void loop(){ sensorValue = analogRead(sensorPin); //read the sensor value using ADC EMA_S_low = (EMA_a_low*sensorValue) + ((1-EMA_a_low)*EMA_S_low); //run the EMA EMA_S_high = (EMA_a_high*sensorValue) + ((1-EMA_a_high)*EMA_S_high); highpass = sensorValue - EMA_S_low; //find the high-pass as before (for comparison) bandpass = EMA_S_high - EMA_S_low; //find the band-pass Serial.print(highpass); Serial.print(" "); Serial.println(bandpass); delay(20); //20ms delay } |
نتیجه فیلتر میان گذر: سیگنال نارنجی مربوط به فیلتر بالا گذر و سیگنال آبی، مربوط به سیگنال میان گذر می باشد.
فیلتر میان ناگذر (Band Stop)
یکی از سختترین فیلترها، فیلتر میان ناگذر است! این فیلتر، فرکانسهای میان فرکانس قطع پایین و فرکانس قطع بالا را عبور نمیدهد. این فیلتر تقریبا ترکیبی از هر دو فیلتر پایین گذر و بالا گذر است. ایده ما برای اجرایی کردن این فیلتر، این است که در آردوینو سیگنال میان گذر شده را از سیگنال اصلی حذف کنیم. در نهایت ما یک فیلتر باندِ معکوس شده داریم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | //Global Variables int sensorPin = 0; //pin number to use the ADC int sensorValue = 0; //initialization of sensor variable, equivalent to EMA Y float EMA_a_low = 0.05; //initialization of EMA alpha (cutoff-frequency) float EMA_a_high = 0.4; int EMA_S_low = 0; //initialization of EMA S int EMA_S_high = 0; int highpass = 0; int bandpass = 0; int bandstop = 0; void setup(){ Serial.begin(115200); //setup of Serial module, 115200 bits/second EMA_S_low = analogRead(sensorPin); //set EMA S for t=1 EMA_S_high = analogRead(sensorPin); } void loop(){ sensorValue = analogRead(sensorPin); //read the sensor value using ADC EMA_S_low = (EMA_a_low*sensorValue) + ((1-EMA_a_low)*EMA_S_low); //run the EMA EMA_S_high = (EMA_a_high*sensorValue) + ((1-EMA_a_high)*EMA_S_high); bandpass = EMA_S_high - EMA_S_low; //find the band-pass as before bandstop = sensorValue - bandpass; //find the band-stop signal Serial.print(sensorValue); Serial.print(" "); Serial.print(EMA_S_low); Serial.print(" "); Serial.println(bandstop); delay(20); //20ms delay } |
سیگنال اصلی (نارنجی)، فیلتر میان نگذر (آبی کم رنگ)، و فیلتر پایین گذر (آبی پر رنگ)
پدیده جالبی که برای فیلتر میان نگذر اتفاق می افتد، نتیجه اعمال پاسخ پله است. در ابتدا، فیلتر سیگنال اصلی را دنبال میکند و بعد از اتمام پاسخ گذرا، کمکم رفتار فیلتر شبیه به فیلتر پایین گذر میشود.
در واقع هدف ما از این مطلب، تنها تست و بررسی موضوع فیلترهای دیجیتال برای آردوینو و ایجاد یک سرگرمی برای درک بهتر فیلترها بود. به همین خاطر، این فیلترها ممکن است گاهی اوقات نتیجه خوبی نداشته باشند. به یاد داشته باشید تأخیرهای بکار رفته در برنامه، هم برای عملیات فیلتر آردوینو و هم برای رسم مفید هستند. (منبع فیلترهای بالا)
فیلتر کالمن
فیلتر کالمن (Kalman Filter) یک تخمین گر است که از تخمین حالت قبل و مشاهده فعلی برای محاسبه تخمین حالت فعلی استفاده میکند و یک ابزار بسیار قوی برای ترکیب اطلاعات در حضور نامعینیها است.
برای اجرای این فیلتر در آردوینو، ابتدا کتابخانه (لایبری) آن را از گیت هاب این پروژه دانلود کرده، سپس همانند کتابخانههای دیگر آن را از مسیر زیر به آردوینو خود اضافه کنید:
Sketch -> Include Library -> Add.ZIP Library
حال، برای استفاده از این کتابخانه در برنامه خود، فایل هدر آن را اضافه کرده، یک شیء از روی آن بسازید و با مقادیر اولیه آن را راه اندازی کنید:
1 2 3 4 | #include "KalmanFilter.h" KalmanFilter filter; // create with default parameters filter.setState( defaultValue ); // setup vith default value |
برای دریافت مقدار آنالوگ از تابع زیر استفاده کنید:
1 | double value = getValueFromSensor(); |
و در نهایت برای دریافت مقدار فیلتر شده، به روش زیر عمل کنید:
1 2 | filter.correct( value ); // add new value from sensor double correctedValue = filter.getState(); // get corrected value |
همچنین میتوانید مثال خود کتابخانه را نیز از مسیر زیر اجرا کنید:
File -> Examples -> KalmanFilter
در نهایت خروجی فیلتر کاملن چیزی شبیه به این خواهد بود:
همچنین از طریق منوی
Sketch -> Include Libary -> Manage Libaries
و یا با استفاده از کلید ترکیبی Ctrl+Shift+I قسمت مدیریت کتابخانه (لایبری) های آردوینو را باز کنید:
اگر در کادر جستجو عبارت “Kalman Filter” را جستجو کنید، میتوانید کتابخانههای زیادی را برای اجرای فیلتر کالمن آردوینو برای ژیروسکوپ، سنسور های بارومتر، دما، شتاب سنج و… پیدا کنید و مثالهای آنها را مطالعه کنید.
امیدوارم این مطلب برای شما مفید بوده باشد. در قسمت بعد، کتابخانه DSp
سلام با تشکر از مطلب خوب و کاربردی شما
آیا برای داشتن نمونه جریان بهتر از موتور هم می توان از این کالمن فیلتر استفاده کرد؟ سنسور جریان نویز زیادی داره و می خواهم نمونه های با کیفیت تری در میکروکنترلر داشته باشم
سلام خدمت اعضای محترم سیسوگ و زئوس
من میخواستم فیلتر کالمن رو برای GPS راه اندازی کنم کتابخانه ای چیزی از این بابت دارین شما
سلام دوست عزیز
نه متاسفانه من از این فیلتر روی gps استفاده نکردم متاسفانه
اتفاقا بدم نمیآد انجامش بدم ولی اگر فرصت پیش بیاد 🙁
سلام و خدا قوت
برای Uno:
nbsp was not declared in this scope&
اصلا این nbsp چی هست؟
ممنون
سلام.
کد html است نه آردوینو!
هنگامی که کد را بر روی سایت قرار میدادم، اشتباها این عبارت وارد کد شده است.
کد را اصلاح کردم.
خیلی ممنون از توجهتون.
سلام، از چه برد آردوینویی استفاده شده است؟؟؟
درود بر شما.
بر روی نانو و Leonardo تست است. اما بر روی برد های دیگه احتمالا مشکل خاصی نخواهد داشت.
تشکر، مطالب بسیار جالبی هست. خواهشمندم آموزشتان را ادامه دهید
سپاس از شما، حتما.
موضوع متفاوت و جالبی بود
ممنون
ادامه بدید
بعضی جاها هم ایراداتی بود که بعدا عرض خواهم کرد
سپاس.
خواهش میکنم.
به روی چشم!
بله، احتمالش هست. صاحب اختیار هستید. بفرمایید.