در این پست از سایت اِمیک, با استفاده از برد اردوینو یک مولد یا ژنراتور موج مربعی خواهیم ساخت که دارای قابلیت تغییر فرکانس نیز می باشد. این پروژه را با استفاده از تایمر در برد اردوینو طراحی کرده ایم و ما در این پروژه از برد اردوینو یونو(UNO) و تایمر 0 ان استفاده خواهیم کرد. شما می توانید از هر نوع برد اردوینو که دارای تایمر می باشد, استفاده کنید. قبلا نیز همین پروژه را با استفاده از میکروکنترلر AVR قرار داده بودم که می توانید ان پست را در اینجا مشاهده کنید.
در ابتدا با تایمر/کانتر و رجیسترهای ان در بردهای اردوینو اشنا می شویم و در ادامه شماتیک و کدهای پروژه را بررسی خواهیم کرد.
تایمر/کانتر در آردوینو :
تایمر/کانتر در اردوینو یک بخش سخت افزاری می باشد که وظیفه ان اندازه گیری زمان است. بردهای اردوینو مختلف دارای تعداد تایمر/کانتر مختلفی می باشند به عنوان مثال برد آردوینو Uno که دارای میکروکنترلر ATmega328 است دارای 3 عدد تایمر/کانتر می باشد که با نام های تایمر 0, تایمر 1 و تایمر 2 مشخص می شوند. که تایمرهای 0 و 2 از نوع 8 بیتی هستند و می توانند از 0 تا 255 بشمارند و تایمر 1 از نوع 16 بیتی است و می تواند از 0 تا 65535 بشمارد.
بردهای آردوینو سری MEGA نیز که بر پایهی میکروکنترلرهای ATmega1280 یا ATmega2560 هستند, دارای 6 عدد واحد تایمر/کانتر می باشند که علاوه بر سه تایمری که در بالا معرفی شد دارای تایمر 3 , تایمر 4 و تایمر 5 نیز می باشند که این سه تایمر دیگر, همانند تایمر 1 از نوع 16 بیتی هستند.
برای راه اندازی واحد تایمر/کانتر در بردهای اردوینو باید رجیسترهای ان را با توجه به هدف خود مقدار دهی کنیم که در ادامه با این رجیسترها بیشتر اشنا خواهیم شد.
کاربرد تایمرها:
- تایمر 0 : همانطور که گفته شد این تایمر 8 بیتی هست و در تمام بردهای آردوینو برای شمارش زمان در توابعی مانند delay , millis و micros استفاده میشود. بنابراین در صورتی که رجیسترهای این تایمر تغییر داده شود ممکن است در عملکرد سه تابع گفته شده اختلال بوجود آید.
- تایمر 1 : این تایمر 16 بیتی می باشد و در تمام بردهای آردوینو از تایمر 1 در کتابخانه سروو موتور استفاده میشود (بجز بردهای آردوینو سری مگا که از تایمر ۵ استفاده میشود)
- تایمر 2 : این تایمر نیز 8 بیتی است و در تمام بردهای آردوینو درون تابع Tone استفاده می شود
- تایمر 3 , تایمر 4 و تایمر 5 : این تایمرها 16 بیتی هستند و فقط مربوط به بردهای آردوینو سری MEGA هستند
رجیسترهای واحد تایمر/کانتر در آردوینو:
مهمترین رجیسترهای واحد تایمر/کانتر اردوینو بصورت زیر است که بجای x روبروی هر کدام از رجیسترها باید شماره تایمر مورد نظر قرار داده شود, مثلا برای تایمر 2 رجیستر TCNTx بصورت TCNT2 نوشته می شود.
TCCRx – رجیستر کنترل واحد تایمر/کانتر :
تقسیم فرکانسی و دیگر تنظیمات در این رجیستر تنظیم و ذخیره می شود که در ادامه نحوه تنظیم این رجیستر برای تایمر 2 که در پروژه از ان استفاده شده توضیح داده خواهد شد.
TCNTx – رجیستر شمارنده واحد تایمر/کانتر :
مقدار شمارش شده در هر لحظه در این رجیستر ذخیره میشود و این رجیستر قابل خواندن و نوشتن در هر لحظه می باشد. زمانی که این رجیستر به ماکزیمم مقدار خود رسید که در تایمر 8 بیتی ماکزیمم 255 و در تایمر 16 بیتی ماکزیمم 65535 است, سر ریز شده و دوباره از صفر شروع به شمردن میکند.
OCRx – رجیستر مقایسه ی خروجی :
مقدار این رجیستر دائما با مقدار رجیستر TCNTx مقایسه می شود و در صورت برابری این دو رجیستر, با توجه به مد انتخاب شده اقداماتی انجام می شود. از تطابق این دو رجیستر, برای تولید وقفه خروجی یا تولید یک شکل موج روی پایه OCx (پایه خروجی تایمر مورد نظر) استفاده می شود
TIMSKx – این رجیستر مربوط به فعال و غیرفعال کردن وقفه است
TIFRx – در این رجیستر نیز تنظیمات وقفه ذخیره میشود (رجیستر پرچم وقفه تایمر/کانتر)
مدهای واحد تایمر/کانتر اردوینو:
چندین مد کاری برای واحد تایمر/کانتر وجود دارد که بسته به نیاز خود باید یکی از انها را انتخاب کنیم که این انتخاب مد کاری از طریق رجیستر TCCRx انجام می شود. ما در این پروژه از تایمر 2 در مد CTC برای تولید پالس مربعی استفاده می کنیم که در ادامه نحوه انتخاب این مد کاری توسط رجیستر TCCRx توضیح داده می شود.
در مد CTC ما رجیستر OCRx را به دلخواه مقدار دهی می کنیم, و رجیستر شمارنده TCNTx از صفر یا یک مقدار مشخص شروع به شمارش می کند و زمانی که به مقداری که ما در رجیستر OCRx تعیین کرده ایم رسید, تایمر سرریز کرده و دوباره به مقدار اولیه رجیستر TCNTx برمی گردد. سرریز کردن تایمر باعث تغییر وضعیت پایه OCx و یا ایجاد وقفه تایمر می شود. برای اطلاع بیشتر در مورد عملکرد مدهای مختلف تایمر/کانتر می تونید سرچ کنید.
نحوه تنظیم رجیستر TCCRx :
همانطور که گفته شد از این رجیستر برای انتخاب تقسیم فرکانسی واحد تایمر/کانتر و همچنین انتخاب مد کاری واحد تایمر/کانتر و دیگر تنظیمات استفاده می کنیم. این رجیستر شامل دو قسمت TCCRxA و TCCRxB می باشد که در دو جدول زیر نحوه تنظیم انها توضیح داده شده است.
جدول بالا مربوط به تنظیمات TCCRxA می باشد, البته این جدول مربوط به تایمر 0 می باشد و همانطور که مشاهده می کنید در ابتدای ان نوشته شده TCCR0A ولی تایمر 2 هم که ما در این پروژه از ان استفاده می کنیم دقیقا مشابه تایمر 0 است و تفاوتی ندارند.
همانطور که مشاهده می کنید رجیستر TCCR0A شامل 8 بیت (بیت 0 تا 7) است که ما باید طبق جداول پایین, ان را مقدار دهی کنیم. البته بیت های 2 و 3 فقط خواندنی هستند و ما کاری با انها نداریم. بیت 0 و 1 از رجیستر TCCR0A بهمراه بیت 3 از رجیستر TCCR0B (جدول پایین) مربوط به انتخاب مد کاری واحد تایمر/کانتر هستند که ما در این پروژه از مد CTC استفاده می کنیم, بنابراین طبق جدول مشخص شده برای مد CTC فقط باید بیت WGM01 یا بیت 1 از رجیستر TCCR0A را یک کنیم و بقیه صفر باشند.
بیت های 4 و 5 نحوه عملکرد کانال خروجی OC0B و بیت های 6 و 7 نحوه عملکرد کانال خروجی OC0A را مشخص می کنند. ما در این پروژه فقط نیاز به یکی از این خروجی ها داریم. دو جدول بالای جدول انتخاب مد, مربوط به تنظیم این بیت ها می باشد. ما خروجی OC0A را نیاز نداریم بنابراین هر دو بیت ان را یعنی بیت های 6 و 7 را برابر صفر می گذاریم تا غیرفعال باشد. برای استفاده از خروجی OC0B باید طبق جدول سمت راست, حالت دوم را انتخاب کنیم. بنابراین فقط باید بیت COM0B0 را یک کنیم و بیت بیت COM0B1 صفر باشد.
در نتیجه رجیستر TCCR0A در این پروژه برای انتخاب مد CTC و فعال کردن کانال خروجی OC0B در حالت دوم باید بصورت زیر شود:
1 |
TCCR0A = 0b00010010; |
جدول زیر مربوط به تنظیمات TCCRxB می باشد و همانطور که گفته شد برای تایمر 0 است ولی تایمر 2 هم دقیقا مشابه ان می باشد
از طریق رجیستر TCCR0B ما تقسیم فرکانسی واحد تایمر/کانتر را انتخاب می کنیم که طبق جدول بالا سه بیت 0 و 1 و 2 مربوط به انتخاب مقسم فرکانسی هستند. ما در این پروژه از تقسیم فرکانسی 64 استفاده می کنیم, بنابراین باید بیت های CS00 و CS01 را یک کنیم و بیت CS02 را صفر کنیم.
بیت سوم رجیستر TCCR0B هم که در بالا گفته شد مربوط به انتخاب مد کاری می باشد و توضیح داده شد. بقیه بیت های این رجیستر در این پروژه استفاده نمی شوند و زیاد مهم نیستند و انها را صفر کنید.
در نتیجه رجیستر TCCR0B در این پروژه برای انتخاب تقسیم فرکانسی 64 باید بصورت زیر باشد:
1 |
TCCR0B = 0b00000011; |
پروژه آردوینو مولد موج مربعی با قابلیت تغییر فرکانس:
در این پروژه دامنه ولتاژ خروجی موج مربعی ما 5 ولت خواهد بود و فرکانس ان نیز از حدود 500 هرتز تا 125000 هرتز (125Khz) قابل تنظیم است. البته در شبیه سازی تغییرات فرکانس در این محدوده بود و در عمل که تست کردم فرکانس خروجی از 500 تا حدود 20K تغییر می کرد و فکر میکنم بخاطر خطای پتانسیومتر باشه که البته مهم هم نیست چون فرکانس های بیشتر از 5K هم در شبیه سازی و هم در تست عملی دارای دقت مناسبی نبود و خطای زیادی داشت, بنابراین میشه گفت که فرکانس واقعی که می تونید با این پروژه ایجاد کنید از 500 هرتز تا حدود 5K هرتز می باشد. در ادامه شماتیک این پروژه را مشاهده می کنید و با این پروژه بیشتر اشنا خواهید شد. در انتهای مطلب هم می توانید کلیپ تست عملی پروژه را مشاهده کنید. شماتیک این پروژه بصورت زیر است:
همانطور که مشاهده می کنید خروجی موج مربعی ما پایه 3 برد اردوینو یونو می باشد و با عبارت OUTPUT مشخص شده است. از یک LCD کاراکتری برای نمایش فرکانس خروجی استفاده شده که این LCD به صورت دائم فرکانس خروجی را نمایش می دهد. پتانسیومتر RV1 برای تنظیم روشنایی LCD استفاده شده و در صورتی که نخواستید استفاده کنید باید پایه 3 ال سی دی را به زمین (GND) متصل کنید.
پتانسیومتر RV2 برای تنظیم فرکانس خروجی استفاده شده که با تغییر ان می توانید فرکانس موج مربعی را تغییر دهید. دو سر این پتانسیومتر به مثبت و منفی تغذیه (VCC و GND) متصل شده و با تغییر ان, ولتاژ پایه وسط ان که به پین A0 برد اردوینو یونو متصل است از 0 تا 5 ولت تغییر می کند. پایه A0 برد اردوینو UNO پایه ی ADC0 ان می باشد و ما این ولتاژ پایه وسط پتانسیومتر را توسط ADC اردوینو اندازه گیری می کنیم و با توجه به مقدار این ولتاژ فرکانس موج مربعی توسط برد اردوینو تنظیم می شود.
برنامه اردوینو :
برنامه این پروژه بصورت زیر است و از اونجایی که برخی مواقع با تغییر فرکانس برد اردوینو هنگ می کرد, واچ داگ را هم فعال کردم تا در صورت هنگ کردن برد اردوینو ان را ریست کند و مشکلی پیش نیاد.
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 40 |
//////// WWW.EMIC.IR //////// #include <LiquidCrystal.h> // lcd معرفي کتابخانه // //متصل شود LCD تابع زیر مشخص می کند که کدام پین های اردوینو به// LiquidCrystal lcd(13, 12, 11, 10, 9, 8, 7); #include <avr/wdt.h> //کتابخانه استفاده از واچ داگ را فعال کرده ایم// #define Fclk 16000000 //Fclk برابر قرار دادن فرکانس کاري برد اردوینو که 16 مگاهرتز است با عبارت// #define N 64 //قرار داده ایم N مقسم تايمر را که 64 انتخاب کرده ايم برابر با حرف// void setup() { //اردوینو مشخص میکند ADC دستور زیر مقدار ولتاژ مبنا یا رفرنس را برای کار با واحد// analogReference(DEFAULT); pinMode(A0, INPUT); //اردوینو A0 ورودی کردن پین// pinMode(3, OUTPUT); //خروجی کردن پین مربوط به خروجی تایمر2// lcd.begin(16, 2); // LCD پيکره بندي // //دستورات زیر رجیسترهای فعالسازی تایمر 2 اردوینو هستند که نحوه مقدار دهی انها در توضیحات مطلب گفته شده// TCCR2A = 0; //ریست کردن رجیستر// TCCR2B = 0; //ریست کردن رجیستر// TCCR2A = 0b00010010; //OC0B و فعال کردن کانال خروجی CTC انتخاب مد// TCCR2B = 0b00000011; //انتخاب تقسیم فرکانسی 64// TCNT2 = 0; OCR2A = 0; } void loop() { wdt_enable(WDTO_500MS); //فعال کردن واچ داگ برای ریست برد اردوینو در زمان هنگ کردن// unsigned long F = 0; //تعريف متغير براي ريختن مقادير فرکانس محاسبه شده در ان// unsigned int A = 0; //در ان A0 تعریف متغیر برای ریختن مقادیر خوانده شده از پین انالوگ// A = analogRead(A0) / 4; //A اردوینو و تقسیم کردن ان بر 4 تا در بازه ی 0 تا 255 شود و ریختن ان در متغیر A0 خواندن مقادیر انالوگ از پین// OCR2A = A; //که حاوی عددی بین 0 تا 255 است A با متغیر OCR2A برابر قرار دادن رجیستر// F = Fclk / (2 * N * (OCR2A + 1)); //دستور روبرو فرکانس را براي نمايش روي ال سي دي محاسبه مي کند// lcd.clear(); //پاک کردن ال سی دی کاراکتری// lcd.setCursor(2, 0); //رفتن به ستون 2 و سطر 0 از ال سي دي// lcd.print("F="); //روی ال سی دی =F نوشتن عبارت// lcd.print(F); //نمایش مقدار فرکانس که در بالا بدست اورده بودیم روی ال سی دی کاراکتری// lcd.print(" Hz"); //روی ال سی دی Hz نوشتن عبارت// lcd.setCursor(2, 1); lcd.print("WWW.EMIC.IR"); delay(300); wdt_disable(); //غیرفعال کردن واچ داگ// } |
توضیحات قسمت های مهم برنامه نوشته شده, اگر سوالی داشتید می تونید در قسمت نظرات مطرح کنید.
نکات :
- برای تست پروژه حتما برد اردوینو را با اداپتور راه اندازی کنید (جریان دهی برد اردوینو در حالتی که با کابل usb متصل به کامپیوتر راه اندازی می شود بسیار کم است و جوابگوی برخی پروژه ها نیست)
- برای اشنایی با دستورات مربوط به LCD کاراکتری اینجا کلیک کنید
- برای اشنایی با دستورات و نحوه راه اندازی ADC در آردوینو اینجا کلیک کنید
- برای اشنایی با دستورات مهم برنامه نویسی اردوینو اینجا کلیک کنید
- برای اشنایی با نحوه پروگرام کردن برد اردوینو (ریختن برنامه روی برد) اینجا کلیک کنید
کلیپ تست عملی پروژه :
پسورد فایل زیپ : www.emic.ir
نظر یادتون نره…
با سلام
میخوام فرکانسی دلخواه خودم رو تولید کنم که از 1 هرتز یا 1کیلوهرتز باشه راه حلش چیه ؟؟
ممنون میشم راهنماییم کنید.
سلام میشه از آردوینو سه تا فرکانس مختلف قابل تنظیمخروجی گرفت ؟
به طور همزمان؟؟؟
سلام
ممنون عالی بود.
ماکزیمم فقط به نظرم فرکانس خروجی 250 کیلو هرتز باشه.
روی اسکوپ این طور دیده میشه.
سلام
تشکر از توضیحات خوب شما .من پروژه رو در نرم افزار پروتئوس اجرا کردم و همه چیز طبق فرمایش شما درست کار میکنه اما وقتی پایه شماره 3 رو به اسکوپ متصل میکنم هیچ خروجی نداره.
سلام, در پروتئوس با اسیلوسکوپ خروجی را تست کردم و مشکلی نداشت. ممکنه تنظیمات اسیلوسکوپ در پروتئوس را بخوبی انجام نداده اید
سلام مجدد.
من از مدار و خروجی اسیلوسکوپ اسکرین شات گرفتم ولی متاسفانه نتونستم تو سایت تون بارگذاری کنم.شکل موج پایه های دیگه رو میشه دید ولی این پایه خروجی رو نشون نمیده.اگه ایمیل یا واتس آپ دارید که خدمت شما ارسال کنم .تشکر
ایمیل : emic1395@gmail.com
خیلی پروزه خوبی است من میخواستم تا در attiny پروزه را انجام دهم و کد های پروزه راتغییر دادم وروی attiny فعلا تا 1.5کیلوهرتز کار کرده ممنون از سایت خوبتون
این پروژه با اردینونانو قابل راه اندازی هست
بله قابل راه اندازی است
سلام میشه فرکانس 20khz تا 120khz تولید کرد آخه شما نوشتید خطا داره منظورتونو نگرفتم یعنی بیشتر از 5khz دقتش کم و زیاد میشه.
سلام, برای فرکانس های بالاتر از 5 کیلو خطای زیادی دارد البته من برای تست پروژه از یک پتانسیومتر تریمر معمولی استفاده کردم و باید از مولتی ترن استفاده می کردم. با مولتی ترن مطمئنا می توان فرکانس را دقیق تر تنظیم کرد و خطا کمتر می شود
سلام میشه با اردوینو موج سینوسی هم تولید کنم؟
سلام, توسط یک مدار ساده انتگرال گیر RC می تونید موج مربعی خروجی اردوینو را به سینوسی تبدیل کنید
بسیار عالی.
میشه یه اسیلاتور ۱ تا ۵۰ هرتز با برد اردوینو درست کرد؟ یه مقدار درباره چگونگی این کار توضیح میدین؟
سلام وقتتون بخیر
اگر من بخوام فقط پالس با دستور analogWrite تولید کنم چجوری میتونم پالس رو برابر یک متغیر قرار بدم؟
اینجوری درسته int a=255;
analogWrite(6,a);
و اینکه با چه کلید هایی میتونم علامت سمیکالن و کاما رو تو آردوینو بزارم؟
برای استفاده از خروجی پین سه رو وصل کنیم کافیه
؟؟چون تو کد چیزی مبنی بر محتوای ارسالی به پین3 ندیدم!
بله خروجی پایه 3 (پایه مربوط به تایمر 2 اردوینو) هست
فرکانس را می توان از 1Hz به 1kHz کاهش داد
باریکلا
افرین
به نظرت با تغییرات داخل پروژه می شه یک اسیلوسکوپ فرکانس پایین ساخت
قبلا چند پروژه ساخت اسیلوسکوپ با برد اردوینو دیدم ولی اطلاع زیادی در این مورد ندارم در اینده اگر وقت شد یک پروژه اسیلوسکوپ ساده قرار میدم