در بخش قبلی با PWM آشنا شدیم و شدت روشنایی یک LED را بهوسیله آن کنترل کردیم. در این بخش از سری آموزش STM32 با توابع LL، قصد داریم به تولید شکل موجهای مختلف بهوسیله PWM بپردازیم، بهعبارتدیگر میخواهیم از PWM بهعنوان یک DAC استفاده کنیم. با سیسوگ همراه باشید.
همانند کنترل شدت روشنایی که در بخش قبل دیدیم، تولید شکل موج نیز توسط کنترل میانگین ولتاژ بهوسیله تغییرات پهنای پالس صورت میگیرد. با این تفاوت که برای ایجاد شکل موجهای غیر از مربعی، میانگین ولتاژ بهصورت متغیر بازمان تنظیم میشود. بهبیاندیگر مقدار میانگین ولتاژ، در هر بازه زمانی و متناسب با شکل موج موردنظر، تغییر خواهد کرد. مثلاً برای یک شکل موج سینوسی مثل تصویر بالا با توجه به فرکانسی که برای شکل موج در نظر داریم و همچنین دقتی که برای تولید شکل موج برای ما مطلوب است ولتاژ خروجی را در بازههای مختلف زمانی تنظیم کنیم (مثلاً بهوسیله یک تابع یا یک Look Up Table).
قبل از وارد شدن به بخش کد این پروژه بیایید باهم نگاهی به اصول اولیه تولید سیگنال و استفاده از فیلتر بیندازیم.
مقدمهای از سیگنال، طیف فرکانسی و فیلتر
برای اینکه بهتر بتوانیم عملکرد تولید موج بهوسیله PWM را متوجه شویم میخواهیم برخی مفاهیم مرتبط در این زمینه را باهم مرور کنیم. این کار را از اصول اولیه سیگنال شروع میکنیم. به هر سیگنال دلخواهی میتوان از حوزه مختلف نگاه کرد؛ حوزه زمان و حوزه فرکانس. همه نمایش زمانی سیگنالها (مثل شکل موج سینوسی که در بالا دیدیم) را بارها و بارها دیدهایم و با آن آشنایی داریم. نمایش زمانی همان نمودار ولتاژ-زمان یک سیگنال است که تغییرات ولتاژ تابع سیگنال را برحسب زمان نشان میدهد. اما حوزه فرکانس چیست و نمایش سیگنال در این حوزه به چه صورت است؟
حوزه فرکانس، فضایی است که در آن توابع ریاضی (یا سیگنالها) بر اساس فرکانس بیان میشوند. برای نمایش یک سیگنال در حوزه فرکانس باید از تبدیل فوریه یا FFT گرفت. بدین طریق اجزاء سازنده سیگنال در حوزه فرکانس را خواهیم داشت. به بیان دیگری میتوان گفت با تبدیل فوریه گرفتن از سیگنال میتوانیم بفهمیم، سیگنال موردنظر در چه فرکانسها یا طیف فرکانسیای مقدار دارد. طبق نظریهی فوریه، هر سیگنالی را میتوان به این طریق به اجزاء فرکانسی سازنده آن تجزیه کرد که به آنها هارمونیک نیز گفته میشود. تعداد این هارمونیکها میتواند یک یا بیشتر باشد. برای روشنتر شدن این موضوع دوباره به همان مثال شکل موج سینوسی برمیگردیم.
یک موج سینوسی از دو جزء تشکیل شده است. یک بخش DC (یا همان آفست سیگنال) و یک بخش AC.
در شکل بالا میتوانیم نمایش حوزه فرکانس سیگنال را در قسمت بالا ببینیم. با FFT گرفتن از سیگنال شکل وسط، یعنی نمایش حوزه فرکانس را خواهیم داشت. میبینیم که جزء DC سیگنال در فرکانس 0 هرتز ظاهرشده است و بخش AC نیز در 1kHz در طیف فرکانسی دیده میشود. به نمودار وسط، نمودار حوزه فرکانس گفته میشود. سؤالی که ممکن است پیش بیاید این است که آیا میتوان هر جزء سازنده این سیگنال را، از کل سیگنال جدا کرد و در اختیار داشت؟ جواب این سؤال مثبت است. همانطور که در قسمت پایین شکل نشانداده شده است، مثلاً میتوانیم بخش DC سیگنال را جدا کنیم. برای این منظور سیگنال سینوسی ابتدا از یک فیلتر پایین گذر (LPF) عبور داده میشود و سپس از آن FFT گرفته میشود. در سمت راست شکل میبینیم که جزء AC سیگنال به شکل محسوسی تضعیفشده است (زیرا فیلتر پایین گذر فرکانسهای پایین را عبور داده است و در محدوده فرکانسی 1kHz که فرکانس جزء AC است تضعیف قابل توجه دارد). پس بدین طریق میتوان بخش DC سیگنال را جدا کرد. در این مثال کاربرد فیلتر کردن و نتیجه آن در حوزه زمان و فرکانس را دیدیم. اکنون میخواهیم کاربرد فیلتر را برای سیگنال PWM بررسی کنیم.
همانطور که قبلاً گفته شد، یک سیگنال PWM درواقع یک موج مربعی است که Duty Cycle آن قابل تنظیم است. حالا اگر بخواهیم در حوزه فرکانس به یک سیگنال PWM نگاه کنیم، طیف فرکانسی وسیعی را مشاهده میکنیم. زیرا چنین شکل موجی از بینهایت هارمونیک مختلف تشکیلشده است. گفتیم بر اساس نظریهی فوریه، هر سیگنالی را میتوان بهصورت مجموعهای از سیگنالهای سینوسی و کسینوسی با فرکانسهای مختلف تجزیه کرد. ازآنجاییکه شکل موج مربعی را بینهایت هارمونیک تشکیل میدهند، با آوردن این سیگنال به حوزه فرکانس چنین چیزی خواهیم دید:
همانطور که در تصویر بالا دیده میشود، به نزدیک شدن شکل موج به موج مربعی، تعداد هارمونیکها بیشتر و بیشتر میشوند و درنهایت در شکل مربعی، تعداد آنها به بینهایت میل میکند. هارمونیکهای سازنده این شکل موجها در تصویر زیر به شکل واضحتری نشان دادهشده است:
و حالا میرسیم به کاربرد فیلتر کردن برای سیگنال PWM. گفتیم که Duty Cycle یک سیگنال PWM در هر بازه زمانی را میتوان ولتاژ میانگین این شکل موج در نظر گرفت. بهعنوانمثال، یک سیگنال PWM با ولتاژ 3.3 ولت و Duty Cycle 50% را میتوان یک ولتاژ میانگین 1.65 ولت در نظر گرفت. هرچند که میدانیم که یک سیگنال ثابت DC نداریم و سیگنال مابین مقدار 0 تا 3.3 ولت در حال تغییر است.
در وسایلی مثل موتورها و اسپیکرها که بهوسیله موج PWM کنترل میشوند، معمولاً یک فیلتر پایین گذر نیز بهکاررفته است. بدینصورت مثلاً یک سرعت یک موتور، متناسب با تغییرات Duty Cycle موج PWM تغییر میکند. به همین صورت اگر بخواهیم بهوسیله PWM یک DAC بسازیم باید از یک فیلتر پایین گذر استفاده کنیم تا هارمونیکهای AC را حذف کنیم.
در تولید یک شکل موج بهوسیله DAC (که در اینجا PWM نقش آن را بازی میکند)، خروجیای برای ما مطلوب است که توسط میانگین ولتاژ PWM تنظیمشده باشد و حداقل ریپل ممکن را داشته باشد. برای رسیدن به این هدف، باید فرکانس PWM تا جای ممکن بالا باشد و همچنین از فیلتر پایین گذری با فرکانس قطع پایین استفاده کنیم. بدین طریق میتوانیم یک ولتاژ DC پایدار (که همان ولتاژ میانگین PWM است را) از خروجی فیلتر پایین گذر دریافت کنیم.
نکتهی بسیار مهمی که در اینجا باید مراقب آن باشیم، این است که فیلتر استفادهشده بهصورتی است که تمامی المانهای AC را از سیگنال خروجی حذف میکند. درنتیجه سوینگ خروجی به خاطر تأثیر ثابت زمانی بالای فیلتر، بسیار کند خواهد بود. بنابراین DAC ای که ساختهایم توانایی تولید سیگنالهای AC، ازجمله سیگنال سینوسی را نخواهد داشت. این مسئله موجب میشود که مجبور شویم برای تولید شکل موج، توازنی میان فرکانس PWM، فرکانس سیگنالهای خروجی و مشخصات فیلتر پایین گذر، توازن برقرار کنیم.
نحوه ساخت DAC به وسیله PWM
اولین مرحله برای ساخت یک DAC بهوسیله PWM، تعیین دقت (Resolution) موردنیاز برای DAC است. با توجه به اینکه دقت DAC، تعداد سطوح ولتاژی است که خروجی آن میتواند داشته باشد و این تعداد سطوح نیز به PWM بستگی خواهد داشت. درواقع دقت PWM تعیین میکند که به چه تعداد Duty Cycle مختلف خواهیم داشت. درنتیجه میتوان گفت که دقت DAC با توجه بهدقت PWM تعریف میشود.
توجه به این نکته حائز اهمیت است که دقت PWM که در دیتاشیت ذکرشده است ثابت نیست. یعنی اینکه دقت PWM در زمان تولید موج تغییر میکند. این تغییر نیز به فرکانس شکل موج تولید وابسته است. هرچقدر که فرکانس شکل موج خروجی بالاتر باشد، دقت کمتر خواهد شد. درنتیجه با توجه به اینکه چه دقتی برای DAC، برای ما مطلوب است میتوانیم یک حاشیه امن برای تعیین حد بالای فرکانس PWM در نظر بگیریم.
همانطور که پیشتر اشاره شد، در تولید شکل موج، حالت ایده آل این است که فرکانس PWM به حدی بالا باشد که درنتیجه فیلتر کردن سیگنال آن، کمترین ریپل ممکن در خروجی را داشته باشد. اما بالا بردن فرکانس PWM موجب کاهش دقت خواهد شد، پس چاره چیست؟
انتخاب فرکانس سیگنال PWM
بهعنوان یک قانون ساده برای انتخاب فرکانس سیگنال PWM، میتوانیم همیشه فرکانس PWM را چند درجه بزرگتر از فرکانس سیگنال خروجی موردنظر انتخاب کنیم. در عبارت زیر، هرچقدر که k بزرگتر باشد، نتیجه مطلوبتر خواهد بود؛
اما همچنان باید توجه داشت که بالا بردن فرکانس PWM موجب کاهش دقت DAC خواهد شد. همانطور که از فرمول زیر هم مشخص است، با بالا رفتن فرکانس PWM به ازای هر فرکانس کلاکی، دقت PWM و درنتیجه دقت DAC کاهش خواهد یافت.
برای تنظیم فرکانس سیگنال خروجی PWM، براساس فرکانس کلاک، میتوان از فرمول زیر استفاده کرد:
در ادامه به جزییات فیلتر پایین گذر مورد نیاز میپردازیم.
طراحی فیلتر پایین گذر RC
مشخصههای دینامیکی DAC ما، توسط فیلتر پایین گذر تعیین میشود. گفتیم که ابت زمانی فیلتر، تأخیر را وارد مدار میکند که سبب میشود سرعت سوینگ DAC کاهش یابد و بدین ترتیب حتی امکان تولید یک شکل موج خاص وجود نداشته باشد. بنابراین در طراحی فیلتر، باید به پارامترهایی توجه کنیم که پاسخ فرکانسی فیلتر را تعیین میکنند. بر همین اساس میتوان سیستم DAC نهایی را به دو نوع DAC استاتیک و DAC دینامیک، تقسیم کرد. در DAC استاتیک از فیلتر پایین گذری با فرکانس قطع بسیار پایین، یعنی در حدود 10 یا 1 هرتز استفاده میشود. در این نوع DAC، سرعت سویینگ خروجی بسیارکم خواهد بود. پس DAC استاتیک برای کاربردهایی مناسب است که نیاز داریم سطوح ولتاژ خاصی را در خروجی تولید کنیم.
در مقابل، DAC دینامیکی دارای فیلتری است که فرکانس سیگنال موردنظر (FBW) را از خود عبور میدهد و فرکانسهای مربوط به هارمونیکهای سیگنال PWM را مسدود میکند. این نوع DAC مناسب تولید شکل موجهای آنالوگ از قبیل موج سینوسی، دندانارهای، مثلثی و … است. برای طراحی چنین فیلتری از فرمول زیر استفاده میشود:
روش صحیح این است که ابتدا مقاومت را براساس قدرت جریان دهی پین GPIO انتخاب کنیم و سپس مقدار خازن را براساس آن، با استفاده از معادله بالا تنظیم کنیم. میزان تضعیف فیلتر را میتوان با استفاده از رابطه زیر حساب کرد. درصورتیکه میزان تضعیف فیلتر کافی نباشد، باید فاکتور k که به آن اشاره شد را افزایش دهیم.
درنهایت باید گفت که طراحی فیلتر براساس نیاز و کاربرد میتواند متفاوت باشد و حتی از فیلترهایی با درجه بالاتر استفاده کرد تا سیگنال خروجی به نحو مطلوبتری فیلتر شود. پس طراحی فیلتر باید با توجه به معیارهای پروژه صورت گیرد.
کنترل ولتاژ خروجی DAC
کنترل ولتاژ خروجی DAC به سادگی و با تغییر Duty Cycle سیگنال PWM صورت میگیرد؛
PWM DAC Output Voltage = 3.3 x (CCRx/ARRx)
بافر در خروجی DAC ساخته شده به وسیله PWM
مثل زمانی که از واحد DAC میکروکنترلر استفاده میکنیم. قرار دادن بافر در خروجی DAC حاضر که وسیله PWM ساختهشده است نیز ضروری است. پس قبل ازآنکه سیگنال را به دستگاه دیگر یا حتی یک بار مقاومتی بفرستیم باید از یک بافر در خروجی استفاده کنیم. استفاده از این بافر موجب پایدار کردن خروجی DAC خواهد شد.
اکنون که با جزییات تولید شکل موج با سیگنال PWM آشنا شدیم، میخواهیم به سراغ میکروکنترلر برویم و چند شکل موج نمونه تولید کنیم.
ایجاد پروژه
مراحل تنظیم قسمتهای مختلف و ایجاد این پروژه دقیقاً مانند بخش قبلی است. دیباگ، کلاک و تایمر را همانند قبل تنظیم کرده و کد پروژه را تولید میکنیم.
نوشتن کد
در این پروژه نیز مثل پروژه بخش قبلی، ابتدا شمارنده و خروجی تایمر 1 را فعال میکنیم، همچنین متغیرها و ثابتهای موردنیاز را تعریف کنیم؛
1 2 3 4 5 6 7 8 9 10 | /* Enable output channel 1 */ LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1); //Enable Timer1's chennel1 /* Enable counter */ LL_TIM_EnableCounter(TIM1); //Enable Timer1's counter LL_TIM_EnableAllOutputs(TIM1); //Enable output for Timer1 #define max 255 //ARR Value int count = 20; //Number of samples |
اکنون میتوانیم یک موج مربعی با فرکانس 281 کیلوهرتز و دیوتی سایکل 50% تولید کنیم و روی اسیلوسکوپ (اتصال پروب به پایه A8)؛
1 2 | /// square wave LL_TIM_OC_SetCompareCH1(TIM1, ((max)/2); |
اما این موج به هیچ تغییری در دیوتی سایکل نیاز ندارد، برای تولید شکل موجهای دیگر مثل مثلثی یا دندانارهای نیاز داریم که میانگین ولتاژ را کنترل کنیم، در کد زیر (در حلقه While(1)) یک شکل موج دندانارهای با فرکانس 50 هرتز را تولید میکنیم؛
1 2 3 4 5 6 | /// sawtooth wave for (int i = 0; i < count; i++) { LL_TIM_OC_SetCompareCH1(TIM1, ((max*i)/count)); LL_mDelay(1); } |
همچنین برای تولید شکل موج مثلثی میتوانیم این کد را در حلقه While(1) بنویسیم:
1 2 3 4 5 6 7 8 9 10 11 | /// triangular wave for (int i = 0;i=<(count-1/2);i++) { LL_TIM_OC_SetCompareCH1(TIM1, ((max*i)/((count-1)/2))); LL_mDelay(150); } for (int i =(count-1/2);i>-1;i--) { LL_TIM_OC_SetCompareCH1(TIM1, ((max*i)/((count-1)/2))); LL_mDelay(150); } |
به کمک PWM، میتوانیم شکل موج سینوسی نیز تولید کنیم. بدین منظور نیاز به یک Lookup table یا جدول مقادیر داریم، که در آن برای هر مقطع زمانی از شکل موج سینوسی، دامنه موردنظر تعریف شود، در اینجا از 64 نمونه برای تشکیل یک دوره تناوب موج سینوسی استفادهشده است. تغییر Duty Cycle سیگنال PWM نیز طبق کد ما، در هر 1 میلیثانیه صورت میگیرد. پس فرکانس شکل موج سینوسی برابر است با:
Fsin = 1/(TDelay*NSamples) = 1 / 64 * 1ms = 15.625 Hz
ما در اینجا Lookup table موج سینوسی را بهصورت زیر تعریف کردهایم (برای تولید چنین Lookup table ای شما میتوانید از یک محاسبهگر مانند این استفاده کنید)؛
1 | const int Sine_Lookup[64] = {0x19,0x1b,0x1e,0x20,0x23,0x25,0x27,0x29, 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x32,0x32, 0x32,0x32, 0x32,0x31,0x30,0x2f,0x2e,0x2c, 0x2b,0x29,0x27,0x25,0x23,0x20,0x1e,0x1b, 0x19,0x17, 0x14,0x12,0xf, 0xd,0xb,0x9, 0x7,0x6,0x4,0x3,0x2,0x1,0x0,0x0, 0x0,0x0,0x0,0x1,0x2,0x3,0x4,0x6, 0x7,0x9,0xb,0xd,0xf,0x12,0x14,0x17}; |
در ادامه و در حلقه While(1) کد زیر را مینویسیم؛
1 2 3 4 5 6 | /// sine wave for (int i = 0; i < 64; i++) { LL_TIM_OC_SetCompareCH1(TIM1, Sine_Lookup[i]); LL_mDelay(1); } |
پس از تولید هرکدام از شکل موجهای بالا، میتوانیم با فرمول گفتهشده برای طراحی فیلتر، یک فیلتر پایین گذر مناسب در خروجی ببندیم و سپس شکل موج خروجی از فیلتر را در اسیلوسکوپ مشاهده کنیم. مثلاً برای موج سینوسی، میتوانیم از یک مقاومت 10 کیلواهمی و یک خازن 100 نانو فاراد استفاده کنیم.
در آخر باید این نکته توجه کرد که تولید شکل موج بهوسیله PWM از روش دیگری غیر این روش پیادهسازی شده در اینجا نیز امکانپذیر است. در آن روش میتوانیم برای زمانبندی سیگنال از DMA استفاده کنیم. با توجه به اینکه در این سری آموزش با DMA کارکردیم، چالش انجام این پروژه با PWM و DMA را به شما واگذار میکنیم.
در این بخش شکل موجهای مختلف را توسط PWM تولید کردیم. در بخش بعدی با چگونگی اتصال تایمرهای 16 بیتی به یکدیگر و ساختن یک تایمر بزرگتر آشنا خواهیم شد.
سلام خدا خیرت بده تشکر از مطالبت
سلام ممنون از مطالبی که به اشتراک میزارید.
بسیار کاربردی بود تشکر
خواهش می کنم
خوشحالیم که تونستیم برای جامعه الکترونیک ایران مفید باشیم