یکی از کاربردیترین ماژولهایی که در بسیاری از امبدد سیستمها از آن استفاده میشود، مبدل آنالوگ به دیجیتال (ADC) است. این مبدل میتواند مقدار ولتاژ آنالوگ را از سنسورهای مختلفی مانند دما، جریان، سنجش میزان شیب و … بخواند و آن را به مقدار معادل دیجیتال تبدیل کند. در این جلسه میخواهیم یاد بگیریم که چگونه در میکروکنترلر STM32 از این ماژول استفاده کنیم و با کمک Energia IDE بتوانیم مقادیر ولتاژ آنالوگ را بخوانیم. برای این کار یک پتانسیومتر کوچک را به بورد STM32 Blue Pill وصل میکنیم و با تغییر درجهی آن مقادیر مختلف ولتاژ آنالوگ را فراهم میکنیم. سپس این مقادیر را به بر روی یک LCD 16×2 نمایش میدهیم.
مقایسهی ماژول ADC در بورد آردوینو و میکروکنترلر STM32
در بوردهای آردوینو یک ADC ماژول ۱۰ بیت، ۶ کانال (در بوردهای Mini و Nano تعداد کانالها ۸ و در بورد مگا (Mega) ۱۶ تا است) داریم که رنج ولتاژ ورودی آن از ۰ تا ۵ ولت است. معنای این حرف این است که چنین ماژولی میتواند ولتاژهای بین ۰ تا ۵ ولت را با اعداد بین ۰ تا ۱۰۲۳ نظیر کند. اما در میکروکنترلر STM32 ماژول ADC به صورت ۱۲ بیت و ۱۰ کانال است و محدودهی ولتاژ ورودی آن از ۰ تا ۳.۳ ولت است. یعنی میتواند ولتاژهای بین ۰ تا ۳.۳ ولت را به اعداد بازهی ۰ تا ۴۰۹۵ نظیر کند.
آشنایی بیشتر با ماژول ADC در میکرو STM32
ADC که در میکرو STM32 وجود دارد، بر اساس اصل successive approximation register) SAR) عمل میکند. بر اساس این اصل، تبدیل ولتاژها آنالوگ به معادل دیجیتال آنها در چند مرحله انجام میشود. تعداد مرحلهها برابر با تعداد بیتهای ADC است و هر مرحله به اندازهی یک کلاک میکرو طول میکشد. به این ترتیب از زمان دریافت مقدار آنالوگ، با هر کلاک یک بیت از نتیجه به خروجی ارسال میشود. ساختار داخلی این ADC هم براساس تکنیک switched-capacitor طراحی شده است.
اگر در این لحظه با میکرو STM32 آشنایی چندانی ندارید، پیشنهاد میکنیم سری به آموزشهای اولیهای که قبلا دربارهی این میکروکنترلر برایتان تدارک دیدهایم بزنید.
رزولوشن ۱۲ بیتی
گفتیم که ADC ما ۱۲ بیتی و دارای ۱۰ کانال است. منظور از داشتن ۱۰ کانال این است که این ماژول ۱۰ پین در اختیار ما قرار میدهد که میتوان با کمک آنها ولتاژ آنالوگ را مشاهده کرد. اما ۱۲ بیتی بودن این ADC بیانگر این است که رزولوشن آن ۱۲ بیت است. یعنی ۲۱۲ (۴۰۹۶) حالت ممکن. این عدد بیانگر تعداد حالاتی است که مبدل میتواند برای نظیر کردن ولتاژها در نظر بگیرد.
یعنی بازهی از ۰ تا ۴۰۹۵ را در نظر میگیرد و با افزایش ولتاژ آنالوگ دریافت شده، عدد نظیر شده را با گامی که مطابق فرمول زیر به دست میآید، افزایش میدهد.
VOLTAGE / STEP = REFERENCE VOLTAGE / 4096 = (3.3/4096= 8.056mV) per unit.
چگونگی تبدیل سیگنال آنالوگ به فرمت دیجیتال
میدانیم که کامپیوترها و مجموعهی دستگاهها و ابزارهای دیجیتال، تنها با مقادیر باینری (۰ و ۱) کار میکنند و همهی اطلاعات را نیز در همین فرمت پردازش و نگهداری میکنند. به همین دلیل است که نیاز داریم سیگنالهای آنالوگ موجود در طبیعت مانند همین ولتاژ را به معادل دیجیتال آنها تبدیل کنیم تا بتوانیم آنها را با استفاده از کامپیوترها و ابزارها پردازش و نگهداری کنیم. نقش مبدلها و میزان دقت آنها در تبدیل نیز در اینجا اهمیت پیدا میکند. میکرو STM و مبدل ADC آن زمانی که یک سیگنال آنالوگ ولتاژ را میخوانند، با استفاده از فرمول زیر آن را تبدیل کرده و در یک متغیر integer ذخیره میکنند.
INPUT VOLTAGE = (ADC Value / ADC Resolution) * Reference Voltage Resolution = 4096 Reference = 3.3V
پایههای مربوط به ADC در میکرو STM32
همان طور که گفتیم این ماژول در میکرو STM دارای ۱۰ پایه است که در تصویر فوق از PA0 تا PB1 قابل تشخیص هستند.
وسایل مورد نیاز برای اجرای پروژه
- میکرو STM32F103C8
- LCD 16×2
- پتانسیومتر 100K
- برد بورد
- سیم رابط
نقشه مدار و توضیح اتصالات
نمودار و اتصالاتی که برای وصل کردن LCD و پتانسیومتر (ورودی آنالوگ) به میکروکنترلر داریم به این ترتیب است.
اتصالات LCD
اتصالات را بر اساس جدول عکس فوق میبندیم. میبینیم که در مدار دو پتانسیومتر وجود دارد؛ اولی که به عنوان مقسم ولتاژ ورودی استفاده میشود و با چرخاندن آن میتوانیم ولتاژهای مختلفی را در رنج ۰ تا ۳.۳ به پین ورودی میکرو ارسال کنیم. (اتصال پایههای پتانسیومتر به این ترتیب است که پایهی سمت چپ آن به ولتاژ مثبت میکروکنترلر (۳.۳ ولت) و پایهی سمت راست به زمین متصل میشود. پایهی وسطی نیز همان است که به پین ورودی سیگنال آنالوگ میکرو (PA7) متصل میکنیم) پتانسیومتر دوم نیز برای تنظیم کنتراست LCD استفاده میشود.
تغذیهی میکروکنترلر نیز از طریق اتصال USB port به یک لپتاپ یا کامپیوتر تامین میشود.
پروگرم کردن STM32 برای خواندن مقادیر ADC
در آموزشهای جلسات قبل، نحوهی پروگرم کردن این میکروکنترلر با استفاده از USB port را با هم آموختهایم. بنابراین و بر اساس مطالبی که در آنجا گفتیم، به پروگرمر FTDI نیاز نداریم. کافیست پورت USB آن را به کامپیوتر متصل کنیم و سپس با استفاده از ARDUINO IDE آن را پروگرم کنیم. این کار بسیار ساده و درست مانند همان روشی است که برای پروگرم کردن خود بوردهای آردوینو استفاده میشود. (نیازی نیست jumper pinهای میکرو را تغییر دهید)
کاری که قرار است در این برنامه انجام دهیم این است که یک مقدار آنالوگ ولتاژ را بخوانیم، مقدار دیجیتال معادل آن را محاسبه کنیم و هر دو مقدار (هم دیجیتال و هم آنالوگ) را بر روی LCD نمایش دهیم.
در ابتدا پینهای LCD را تعریف میکنیم. یعنی مشخص میکنیم که LCD قرار است به کدام پایههای میکرو متصل باشد. (میتوانید بر اساس نیاز خودتان پایههای دیگر را تعریف کنید)
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to
سپس هدر فایل مربوط به LCD را اضافه میکنیم. این هدر فایل کتابخانهای را که در آن چگونگی ارتباط با LCD را به میکرو توضیح میدهد، فراخوانی میکند.
همچنین تابع Liquid Crystal را فراخوانی میکنیم و باید دقت کنیم که همان پینهایی را به آرگومانهای آن بدهیم که در بالا تعیین کردیم.
#include <LiquidCrystal.h> // include the LCD library LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD
در بخش تابع ()setup فقط کافیست که پیام welcome را بر روی LCD نمایش دهیم.
lcd.begin(16, 2); //We are using a 16*2 LCD lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("CIRCUITDIGEST"); //Print this lcd.setCursor(0, 1); //At secound row first column lcd.print("STM32F103C8"); //Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("USING ADC IN");//Print this lcd.setCursor(0,1); //At secound row first column lcd.print("STM32F103C8");//Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen
و در نهایت در بخش تابع حلقه (()loop)، مشخص میکنیم که ولتاژ آنالوگی که به پین PA7 وارد میشود، خوانده شود. همان طور که قبلتر هم گفتیم میکروکنترلر یک ابزار دیجیتال است و نمیتواند مقدار آنالوگی را بخواند. پس با استفاده از همان تکنیک SAR که اشاره کردیم، مقدار موجود را به عددی در بازهی ۰ تا ۴۰۹۵ معادل میکند. به این مقدار به دست آمده، ADC value گفته میشود. برای به دست آوردن آن، کافی است از کد زیر استفاده کنیم.
int val = analogRead(A7); // read the ADC value from pin PA7
تابع ()analogRead را برای خواندن مقدار سیگنال از پین دریافت سیگنال آنالوگ استفاده میکنیم. مقدار خوانده شده را در متغیری به نام val ذخیره میکنیم. نوع این متغیر را integer تعریف میکنیم چون فقط میتواند مقادیرعددی (از ۰ تا ۴۰۹۵) را بپذیرد.
مرحله بعدی این است که مقدار ولتاژ را از روی ADC value محاسبه کنیم. برای این کار از فرمول زیر استفاده میکنیم.
Voltage = (ADC Value / ADC Resolution) * Reference Voltage
در این پروژه، ما از قبل میدانیم که ADC Resolution میکروکنترلرمان ۴۰۹۶ است. ADC Value را هم که در متغیر val ذخیره کردهایم. Refrence Voltage هم ولتاژ کاری میکروکنترلرمان است. میدانیم زمانی که STM32 را با پورت USB به کامپیوتر متصل میکنیم، ولتاژ کاری آن ۳.۳ ولت خواهد بود. هرچند که حتی اگر این نکته را هم به خاطر نداشته باشید، میتوان یک مولتیمتر را بین دو پین Vcc و Gnd بورد میکروکنترلر قرار داد و ولتاژ کاری آن را اندازه گرفت.
به این ترتیب فرمول فوق برای پروژهی ما به این صورت در خواهد آمد.
float voltage = (float(val)/4096) * 3.3;
«فرمولی برای تبدیل ADC value به ولتاژ»
اگر احیانا عبارت float(val) کمی باعث گیج شدنتان شده است؛ باید بگوییم این تابعی است که نوع متغیر val را که int است، به نوع float برمیگرداند. علت این تبدیل این است که ما تنها زمانی میتوانیم val/4096 را در ۳.۳ (که خود از نوع float است) ضرب کنیم، که val/4096 هم float باشد. در غیر این صورت حاصل این ضرب و در نتیجه ولتاژ به دست آمده همواره صفر خواهد بود که قطعاً اشتباه است.
پس از به دست آوردن ولتاژ و ADC value، تنها کاری که باقی مانده است این است که آنها را بر روی LCD نمایش دهیم. کد زیر این کار را برای ما انجام میدهد.
lcd.setCursor(0, 0); // set the cursor to column 0, line 0 lcd.print("ADC Val:"); lcd.print(val); //Display ADC value lcd.setCursor(0, 1); // set the cursor to column 0, line 1 lcd.print("Voltage:"); lcd.print(voltage); //Display voltage
در این بخش هم میتوانید کد کامل پروژه و ویدئوی اجرای آن را ببینید.
کد
#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 analogip = PA7;//Initialize the analog input pin void setup() { lcd.begin(16, 2); //We are using a 16*2 LCD lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("CIRCUITDIGEST"); //Print this lcd.setCursor(0, 1); //At secound row first column lcd.print("STM32F103C8"); //Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("USING ADC IN");//Print this lcd.setCursor(0,1); //At secound row first column lcd.print("STM32F103C8");//Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen } void loop() { int val = analogRead(PA7); // read the ADC value from pin A7 float voltage = (float(val)/4096) * 3.3; //formulae to convert the ADC value to voltage lcd.setCursor(0, 0); // set the cursor to column 0, line 0 lcd.print("ADC Val:"); lcd.print(val); //Display ADC value lcd.setCursor(0, 1); // set the cursor to column 0, line 1 lcd.print("Voltage:"); lcd.print(voltage); //Display voltage }
ویدئو
منبع: ترجمه از سایت circuitdigest.com
امیدواریم آموزش « آموزش راه اندازی ADC در STM32 » برایتان مفید واقع شده باشد. در ادامه پیشنهاد میکنیم دیگر آموزشهای STM32 را نیز مطالعه کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
سلام در قسمت “رزولشن 12 بیتی” مقدار ولتاژ به ازی یک پله ADC را 8.056 میلیوات حساب کردید که اشتباه است و مقدار 805.66 میکرو ولت صحیح میباشد. ممنون از آموزش های خوبتون.
سلام عالی بود….فقط یک سوالی داشتم…اگر که بخوایم ولتاژ برق شهر رو اندازه بگیریم، چگونه باید کار کنیم مراحل رو؟فرمول چگونه میشه؟ آیا بجای ولتاژ Refeenc که در اینجا ۳.۳ ولت بود، باید ۲۲۰ولت بزاریم؟