در جلسات قبلی، استفاده از مبدل آنالوگ به دیجیتال (ADC) در میکروکنترلر STM32 را با هم یاد گرفتیم. در این جلسه میخواهیم به سراغ تکنیک PWM در این میکروکنترلر برویم و یاد بگیریم که چگونه میتوانیم با استفاده از آن شدت نور یک LED و یا سرعت یک فن DC را کنترل کنیم.
میدانیم که سیگنالها دو نوع هستند، آنالوگ و دیجیتال. سیگنالهای آنالوگ دارای ولتاژهایی مانند ۱ ولت، ۳ ولت و … هستند اما سیگنالهای دیجیتال فقط مقادیر ۰ و ۱ را میپذیرند. یعنی ولتاژ آنها یا ۰ و یا ۱ است.
از طرفی خروجی سنسورها سیگنالهای آنالوگ است و چون میکروکنترلرها فقط زبان دیجیتال را میفهمند، پس این سیگنالها ابتدا به کمک مبدلهای ADC به معادل دیجیتال خود تبدیل شده و بعد وارد مرحلهی پردازش با میکروکنترلر میشوند. اما بعد از اینکه پردازش شدند، از آنجایی که قرار است دوباره به دیوایسهایی بروند که آنها نیز با مقادیر آنالوگ کار میکنند و کنترل میشوند، پس مجددا باید از فرمت دیجیتال به آنالوگ برگردانده شوند. برای این تبدیل از روشهایی مانند PWM یا مبدلهای دیجیتال به آنالوگ (DAC) استفاده میکنیم.
مدولاسیون عرض پالس یا PWM چیست؟
PWM روشی برای کنترل دیوایسهای آنالوگ با استفاده از مقادیر دیجیتال است. مثلا کنترل شدت نور یک LED و یا کنترل سرعت یک فن DC.
این دیوایسها با سیگنالهای آنالوگ کار میکنند اما PWM سیگنالهای آنالوگ خالص تولید نمیکند. در حقیقت پالسهایی با عرض بسیار کم تولید میکند که در مجموع شبیه به یک سیگنال آنالوگ به نظر میرسند. این پالسهای کوتاه براساس duty cycle ساخته میشوند.
Duty cycle در PWM
منظور از duty cycle، نسبت زمانی که در آن سیگنال در وضعیت High قرار دارد، به کل زمان یک سیکل است. با این تعریف، واضح است که اگر یک سیگنال همواره یک باشد، duty cycle آن ۱۰۰ درصد و اگر همواره صفر باشد، duty cycle آن صفر درصد است.
Duty Cycle =Turn ON time/ (Turn ON time + Turn OFF time)
PWM در میکروکنترلر STM32
این میکروکنترلر دارای ۱۵ پین PWM و ۱۰ پین ADC است. ۷ عدد تایمر نیز در داخل آن وجود دارند که هر کدام از خروجیهای PWM توسط کانالی که به ۴ عدد از این تایمرها متصل است تولید میشود. رزولوشن PWM در آن ۱۶ بیتی است (یعنی ۲۱۶) و این بدان معناست که شمارندهها (کانتر) و متغیرهای آن میتوانند تا مقدار ۶۵۵۳۵ را بپذیرند.
فرکانس کلاک آن 72MHz است و در نتیجه حداکثر پریود زمانی خروجیهای PWM آن میتواند در حدود ۱ میلی ثانیه باشد.
چند نتیجهی کوتاه از پاراگراف فوق:
- ۶۵۵۳۵ حداکثر سرعت فن DC و حداکثر شدت روشنایی LED را ایجاد میکند. (duty cycle : 100%)
- به همین ترتیب اگر مقدار ۳۲۷۶۷ باشد (تقریبا نصف مقدار ۶۵۵۳۵)، سرعت فن و شدت روشنایی LED نصف مقدار فوق خواهند شد .(duty cycle :50%)
- و مثلا مقداری مانند ۱۳۱۰۷، ۲۰ درصد حالت اول شدت روشنایی و سرعت فن میدهد. (duty cycle : 20%)
در این پروژه ما با استفاده از یک پتانسیومتر، duty cycleهای مختلفی از سیگنال PWM تولید شده توسط STM32 را ایجاد میکنیم تا بتوانیم شدت نور LED و سرعت فن DC را کنترل کنیم. همچنین از یک نمایشگر LCD 16×2 هم استفاده میکنیم که در هر کدام از حالتهای پتانسیومتر، مقدار ADC (عددی بین ۰ تا ۴۰۹۵) و مقدار PWM (عددی بین ۰ تا ۶۵۵۳۵) بر روی آن نمایش داده شوند.
تجهیزات مورد نیاز برای انجام پروژه
- میکرو کنترلر STM32F103C8
- DC fan
- یک IC برای درایور موتور: ULN2003
- LED قرمز رنگ
- LCD 16×2
- پتانسیومتر
- برد بورد
- باتری ۹ ولتی
- سیم جامپر
DC Fan
در اینجا ما از یک فن BLDC که آن را از یک کامپیوتر قدیمی گرفتهایم استفاده میکنیم. از آنجایی که این فن برای کار کردن به تغذیهی خارجی نیاز دارد، از باتری DC نه ولتی (9V) به همین منظور استفاده میکنیم.
ULN2003 Motor Driver IC
این درایور برای به حرکت درآوردن فن استفاده میشود و جهت حرکت آن یک طرفه است. نمای کلی این IC را در تصویر زیر میبینید.
پینهای IN1 تا IN7 پینهای ورودی و OUT1 تا OUT7 خروجیهای متناظر آنها هستند. به پورت COM هم یک منبع ولتاژ مثبت متصل میشود که برای خروجیها لازم است.
LED
در اینجا ما از LED قرمز رنگ استفاده میکنیم که نور ساطع شده از آن رنگ قرمز دارد و البته اصراری بر قرمز بودن آن نیست. شما میتوانید از هر رنگ دلخواه دیگری هم استفاده کنید.
پتانسیومتر
دو عدد پتانسیومتر نیاز داریم، که یکی برای تقسیم ولتاژ در ورودی آنالوگ ADC به میکروکنترلر و دیگری برای تنظیم duty cycle در سیگنال PWM تولید شده است.
پایههای میکروکنترلر STM32
پینهای PWM در نقشهی فوق با علامت شکل موج (~) قابل تشخیص هستند. میبینیم که ۱۵ عدد از این پینها وجود دارد. پینهای ADC هم با رنگ سبز مشخص شدهاند که میبینیم ۱۰ عدد هستند. از این پینها برای دریافت ورودی آنالوگ استفاده میشود.
نقشه مدار و اتصالات
نحوهی اتصال میکروکنترلر STM32 به قسمتهای مختلف مدار به این ترتیب است.
میکروکنترلر به ورودی آنالوگ
پتانسیومتری که در سمت چپ مدار وجود دارد، در نقش یک رگولاتور ولتاژ برای پین ۳.۳ ولت ظاهر میشود. خروجی این پتانسیومتر (که از پایهی وسطی آن گرفته میشود) به یکی از پینهای ADC میکروکنترلر وصل میشود. در اینجا ما آن را به PA4 وصل میکنیم.
میکروکنترلر به LED
خروجی PWM میکروکنترلر (در اینجا PA9) به واسطهی یک مقاومت سری و خازن به پایهی مثبت LDC متصل میشود.
LED به خازن و مقاومت
یک مقاومت با آرایش سری و یک خازن با آرایش موازی به LED متصل میشوند تا سیگنال آنالوگ گرفته شده از PWM را که به صورت آنالوگ کاملی نیست، به صورتی مرتب و تصحیح شده به LED برسانند.
میکروکنترلر به درایور و درایور به فن
یکی از خروجیهای PWM میکروکنترلر (در اینجا PA8) را به یکی از ورودیهای ULN2003 (در اینجا IN1) متصل میکنیم و خروجی متناظر این پین یعنی OUT1 را هم به سیم منفی فن DC.
سیم مثبت فن را هم به پین COM درایور وصل میکنیم. باتری ۹ ولتی هم به پورت COM وصل میشود. پینهای Gnd میکروکنترلر، داریور و سر منفی باتری هم همگی به یک زمین مشترک در مدار وصل میشوند.
میکروکنترلر به LCD
یک پتانسیومتر در سمت راست مدار وجود دارد که کنتراست LCD را تنظیم میکند. جدول فوق چگونگی اتصال میکروکنترلر و LCD را توضیح میدهد.
پروگرم کردن STM32
در این آموزش هم مانند آموزشهای قبلی، میکرو STM32 را از طریق پورت USB و با استفاده از Arduino IDE پروگرم میکنیم. به این ترتیب نیازی به پروگرمر FTDI نخواهیم داشت. اگر طریقهی پروگرم کردن STM32 با استفاده از Arduino IDE را نمیدانید به این لینک مراجعه کنید. روال این کار درست مشابه پروگرم کردن بوردهای آردوینو است.
کد کامل این پروژه را در انتهای آموزش قرار دادهایم.
اما در این کد قرار است چه کاری انجام دهیم؟ میخواهیم یک مقدار آنالوگ را از پین PA4) ADC) بگیریم (این پین به پایهی وسطی پتانسیومتر سمت چپی وصل بود) و سپس مقدار آنالوگ دریافت شده را (که در محدودهی ۰ تا ۳.۳ ولت قرار دارد) به فرمت دیجیتال یا int (عددی بین ۰ تا ۴۰۹۵) تبدیل کنیم. این مقدار دیجیتال سپس تبدیل به یک خروجی PWM میشود که میتوانیم به کمک آن سرعت فن (یا شدت نور LED) را تنظیم کنیم. از LCD هم برای نمایش دادن مقدار ADC و PWM متناظر با آن استفاده میکنیم.
ابتدا باید هدر فایل مربوط به LCD را در کد قرار دهیم و پینهای آن را با کد زیر initialize کنیم. (دربارهی اتصال LCD به STM32 در سایت نوشتیم به طور مفصل بخوانید)
#include <LiquidCrystal.h> // include the LCD library const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD
سپس پینهای استفاده شده را تعریف میکنیم.
const int analoginput = PA4; // Input from potentiometer const int led = PA9; // LED output const int fan = PA8; // fan output
حال در بخش تابع ()setup باید چند پیام اولیه را نمایش دهیم و بعد از چند ثانیه آنها را از روی صفحه پاک کنیم. پین ورودی و خروجی PWM را هم مشخص میکنیم.
lcd.begin(16,2); //Getting LCD ready lcd.clear(); //Clears LCD lcd.setCursor(0,0); //Sets cursor at row0 and column0 lcd.print("CIRCUIT DIGEST"); //Displays Circuit Digest lcd.setCursor(0,1); //Sets Cursor at column0 and row1 lcd.print("PWM USING STM32"); //Displays PWM using STM32 delay(2000); // Delay Time lcd.clear(); // Clears LCD pinMode(analoginput, INPUT); // set pin mode analoginput as INPUT pinMode(led, PWM); // set pin mode led as PWM output pinMode(fan, PWM); // set pin mode fan as PWM output
با استفاده از تابع pinMode(analoginput, INPUT)، پین PA4 را به عنوان ورودی تنظیم میکنیم و LED پین را هم با استفاده از pinMode(led, PWM) به عنوان پین PWM .PWM فن را هم به همین ترتیب تنظیم میکنیم، pinMode(fan, PWM).
در اینجا خروجیهای PWM به PA9) LED) و فن (PA8) متصل هستند.
سپس در بخش تابع حلقه (()loop)، یک سیگنال آنالوگ را از پین PA4) ADC) میخوانیم و آن را در یک متغیر integer ذخیره میکنیم. این متغیر مقدار دریافت شده را با استفاده از دستور زیر، به یک مقدار دیجیتال بین ۰ تا ۴۰۹۵ تبدیل میکند.
int valueadc = analogRead(analoginput);
نکتهای که در اینجا وجود دارد این است که خروجیهای PWM در SM32، همان طور که گفتیم دارای رزولوشن ۱۶ بیتی هستند. یعنی مقادیر آنها بین ۰ تا ۶۵۵۳۵ است. بنابراین باید بین این دو محدوده یک تناظر برقرار کنیم که با استفاده از رابطهی زیر این کار را انجام میدهیم.
int result = map(valueadc, 0, 4095, 0, 65535).
اگر این تبدیل را انجام ندهیم، هر چقدر هم پتانسیومتر را بچرخانیم، نمیتوانیم حداکثر سرعت ممکن برای فن یا حداکثر شدت نور ممکن برای LED را به دست آوریم.
حالا خروجیهای هر کدام از دو PWM را به LED و فن میدهیم؛ دو تابع (pwmWrite(led, result و (pwmWrite(fan, result این کار را برای ما انجام میدهند. و در نهایت با استفاده از دستورات زیر، ورودی ADC و خروجیهای PWM را روی نمایشگر LCD نمایش میدهیم.
lcd.setCursor(0,0); //Sets cursor at row0 and column0 lcd.print("ADC value= "); // prints the words “” lcd.print(valueadc); //displays valueadc lcd.setCursor(0,1); //Sets Cursor at column0 and row1 lcd.print("Output = "); //prints the words in "" lcd.print(result); //displays value result
در ادامه میتوانید به کد کامل و ویدئویی از انجام مراحل پروژه دسترسی داشته باشید.
کد
#include <LiquidCrystal.h> // include the LCD library const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD const int analoginput = PA4; // Input from potentiometer const int led = PA9; // LED output const int fan = PA8; // fan output void setup() { lcd.begin(16,2); //Getting LCD ready lcd.clear(); //Clears LCD lcd.setCursor(0,0); //Sets cursor at row0 and column0 lcd.print("CIRCUIT DIGEST"); //Displays Circuit Digest lcd.setCursor(0,1); //Sets Cursor at column0 and row1 lcd.print("PWM USING STM32"); //Displays PWM using STM32 delay(2000); // Delay yime lcd.clear(); // Clears LCD pinMode(analoginput, INPUT); // set pin mode analoginput as INPUT pinMode(led, PWM); // set pin mode led as PWM output pinMode(fan, PWM); // set pin mode fan as PWM output } void loop() { int valueadc = analogRead(analoginput); //gets analog value from pot and store in variable,converts to digital int result = map(valueadc, 0, 4095, 0, 65535); //maps the (0to4095 into 0to65535) and stores in result variable pwmWrite(led, result); //puts resultin PWM form pwmWrite(fan, result); //puts resultin PWM form lcd.setCursor(0,0); //Sets cursor at row0 and column0 lcd.print("ADC value= "); // prints the words in "" lcd.print(valueadc); //displays value lcd.setCursor(0,1); //Sets Cursor at column0 and row1 lcd.print("Output = "); //prints the words in "" lcd.print(result); //displays value result }
ویدئو
- منبع: ترجمه از سایت circuitdigest.com
امیدواریم آموزش «مدولاسیون عرض پالس یا PWM در STM32» برایتان مفید واقع شده باشد. در ادامه پیشنهاد میکنیم دیگر آموزشهای STM32 را نیز مطالعه کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
سلام
موقع نوشتن برنامه PWM در Arduino ide با ارور ‘PWM’ was not declared in this scope; did you mean ‘PWR’? مواجه میشوم
ممنون میشم منو راهنمایی کنید
با تشکر