آموزش آردوینو

آموزش ورودی و خروجی آنالوگ در آردوینو

در این آموزش با ورودی آنالوگ، مبدل آنالوگ به دیجیتال (ADC)، تابع analogRead() و خروجی PWM با تابع analogWrite() آشنا می شوید. با مثال های عملی یاد می گیرید مقدار پتانسیومتر را بخوانید، اطلاعات را در Serial Monitor نمایش دهید و شدت نور LED را کنترل کنید. همچنین تفاوت خروجی PWM با ولتاژ آنالوگ واقعی و تفاوت قابلیت های Arduino Uno و ESP32 را بررسی می کنیم.

سطح مقدماتی

آموزش ورودی و خروجی آنالوگ در آردوینو؛ analogRead و analogWrite

در پروژه های آردوینو همیشه با وضعیت های روشن و خاموش سروکار نداریم. گاهی لازم است مقدار یک ولتاژ را اندازه گیری کنیم یا شدت نور LED را به تدریج تغییر دهیم. برای این کار با ورودی آنالوگ و خروجی های قابل تنظیم آشنا می شویم.

در این آموزش، دو تابع پرکاربرد را بررسی می کنیم:

  • analogRead() برای خواندن مقدار ورودی آنالوگ
  • analogWrite() برای تولید خروجی PWM در بردهایی که از این قابلیت پشتیبانی می کنند

مثال های اصلی بر اساس Arduino Uno نوشته شده اند. در بردهای دیگر مانند ESP32، محدوده ADC، پایه های قابل استفاده و روش تولید PWM ممکن است متفاوت باشد.

۱. تفاوت سیگنال دیجیتال و آنالوگ

سیگنال دیجیتال در ساده ترین حالت دو وضعیت منطقی دارد:

  • HIGH
  • LOW

اما سیگنال آنالوگ می تواند در یک محدوده، مقدارهای ولتاژ مختلفی داشته باشد.

برای مثال، اگر یک پتانسیومتر به تغذیه و زمین متصل شود، با چرخاندن محور آن می توان ولتاژ خروجی را به تدریج تغییر داد. این ولتاژ می تواند توسط ورودی آنالوگ آردوینو اندازه گیری شود.

کاربردهای رایج ورودی آنالوگ عبارت اند از:

  • خواندن پتانسیومتر
  • اندازه گیری ولتاژ خروجی برخی حسگرها
  • اندازه گیری ولتاژ باتری با مدار تقسیم ولتاژ مناسب
  • تشخیص تغییرات شدت نور با حسگرهای آنالوگ
  • خواندن خروجی آنالوگ حسگرهای دما

از خروجی PWM نیز می توان برای کنترل شدت نور LED یا سرعت بعضی موتورها از طریق مدار درایور مناسب استفاده کرد.

۲. ورودی آنالوگ چیست؟

ورودی آنالوگ به آردوینو اجازه می دهد ولتاژ یک پایه را اندازه گیری کند.

در Arduino Uno معمولی، ورودی های آنالوگ با نام هایی مانند A0، A1، A2 و غیره مشخص شده اند.

این ورودی ها به مبدل آنالوگ به دیجیتال یا ADC متصل هستند. ADC ولتاژ ورودی را به یک عدد دیجیتال تبدیل می کند تا برنامه بتواند با آن کار کند.

دقت ADC در Arduino Uno

در Arduino Uno مبتنی بر ATmega328P، تابع analogRead() معمولا عددی بین ۰ تا ۱۰۲۳ برمی گرداند. این مبدل ۱۰ بیتی است و در حالت معمول، ورودی را به ۱۰۲۴ سطح عددی تقسیم می کند.

به طور تقریبی:

ولتاژ ورودیمقدار خوانده شده
نزدیک ۰ ولت۰
حدود ۱٫۲۵ ولت۲۵۶
حدود ۲٫۵ ولت۵۱۲
حدود ۳٫۷۵ ولت۷۶۷
نزدیک ۵ ولت۱۰۲۳

این اعداد تقریبی هستند و به ولتاژ مرجع ADC، ولتاژ واقعی ورودی و شرایط مدار بستگی دارند.

نکته مهم: پایه های آنالوگ Arduino Uno را نباید با ولتاژی بالاتر از محدوده مجاز آن ها تغذیه کنید. در برد Uno معمولی، محدوده اندازه گیری پیش فرض معمولا از GND تا ولتاژ مرجع نزدیک ۵ ولت است. این موضوع برای بردهای ۳٫۳ ولتی مانند بسیاری از بردهای ESP32 متفاوت است.

۳. تابع analogRead()

تابع analogRead() ولتاژ ورودی آنالوگ را اندازه گیری می کند و نتیجه را به صورت یک عدد برمی گرداند.

ساختار تابع:

analogRead(pin);

پارامتر pin شماره یا نام پایه آنالوگ است.

مثال:

int sensorValue = analogRead(A0);

در این مثال، مقدار ورودی پایه A0 خوانده و در متغیر sensorValue ذخیره می شود.

برای استفاده از analogRead() معمولا نیازی نیست پایه را با pinMode() روی INPUT تنظیم کنید؛ پایه های آنالوگ در حالت پیش فرض برای ورودی مناسب هستند. با این حال، اگر از پایه ای در نقش دیجیتال استفاده می کنید، باید تنظیمات مناسب همان کاربرد را انجام دهید.

۴. مثال عملی اول: خواندن پتانسیومتر

پتانسیومتر یک مقاومت متغیر است که می تواند ولتاژ خروجی قابل تنظیمی تولید کند. در این تمرین با چرخاندن محور پتانسیومتر، عددی که آردوینو می خواند تغییر می کند.

قطعات مورد نیاز

  • یک برد Arduino Uno
  • یک پتانسیومتر، برای مثال ۱۰ کیلو اهم
  • یک بردبرد
  • سه سیم جامپر

اتصال مدار

پتانسیومتر معمولا سه پایه دارد:

  1. پایه اول را به 5V وصل کنید.
  2. پایه دوم، یعنی پایه وسط یا خروجی متغیر را به A0 وصل کنید.
  3. پایه سوم را به GND وصل کنید.

در این مدار، ولتاژ خروجی پتانسیومتر با چرخاندن محور تغییر می کند.

کد برنامه

const int potPin = A0;
int potValue = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  potValue = analogRead(potPin);

  Serial.println(potValue);

  delay(100);
}

بررسی برنامه

  • Serial.begin(9600); ارتباط سریال را با سرعت ۹۶۰۰ بیت بر ثانیه آغاز می کند.
  • analogRead(potPin); مقدار ورودی آنالوگ را می خواند.
  • Serial.println(potValue); عدد خوانده شده را در Serial Monitor نمایش می دهد.
  • delay(100); بین دو بار خواندن، حدود ۱۰۰ میلی ثانیه مکث می کند.

پس از آپلود برنامه، Serial Monitor را باز کنید و سرعت آن را روی 9600 قرار دهید. با چرخاندن پتانسیومتر باید عدد نمایش داده شده تغییر کند.

تمرین: بررسی کنید وقتی محور پتانسیومتر در ابتدا، وسط و انتهای مسیر قرار دارد، چه عددهایی مشاهده می کنید.

۵. تبدیل مقدار analogRead به ولتاژ

در Arduino Uno با مرجع پیش فرض نزدیک ۵ ولت و مقدار ADC بین ۰ تا ۱۰۲۳، می توان ولتاژ ورودی را به صورت تقریبی محاسبه کرد:

Voltage = ADC value × Reference Voltage / 1023

برای مثال، اگر مقدار خوانده شده ۵۱۲ باشد:

Voltage ≈ 512 × 5.0 / 1023

Voltage ≈ 2.50V

کد نمونه

const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int rawValue = analogRead(sensorPin);

  float voltage = rawValue * (5.0 / 1023.0);

  Serial.print("ADC = ");
  Serial.print(rawValue);

  Serial.print(" | Voltage = ");
  Serial.println(voltage, 2);

  delay(500);
}

این محاسبه تقریبی است. اگر ولتاژ مرجع واقعی دقیقا ۵ ولت نباشد، مقدار ولتاژ محاسبه شده نیز اختلاف خواهد داشت.

هشدار: این مثال برای Arduino Uno معمولی است. آن را بدون بررسی محدوده ADC و ولتاژ مرجع به ESP32 یا بردهای دیگر منتقل نکنید؛ بسیاری از ورودی های ESP32 برای ولتاژ ۵ ولت طراحی نشده اند.

۶. خروجی PWM چیست؟

تابع analogWrite() در Arduino Uno معمولی، ولتاژ آنالوگ واقعی تولید نمی کند؛ بلکه یک سیگنال دیجیتال PWM تولید می کند.

PWM مخفف Pulse Width Modulation یا مدولاسیون پهنای پالس است.

در PWM، پایه خروجی با سرعت مشخصی بین وضعیت روشن و خاموش تغییر می کند. با تغییر نسبت زمانی که خروجی در وضعیت HIGH قرار دارد، می توان توان متوسط تحویلی به بار را کنترل کرد.

این نسبت را چرخه کاری یا Duty Cycle می نامند.

برای مثال:

  • چرخه کاری نزدیک ۰٪: خروجی بیشتر زمان خاموش است.
  • چرخه کاری حدود ۵۰٪: خروجی تقریبا نیمی از زمان روشن است.
  • چرخه کاری نزدیک ۱۰۰٪: خروجی بیشتر زمان روشن است.

در کنترل روشنایی LED، چشم انسان معمولا این تغییرات سریع را به صورت تغییر شدت نور درک می کند.

۷. تابع analogWrite()

در Arduino Uno، تابع analogWrite() برای تولید PWM روی پایه های پشتیبانی شده استفاده می شود.

ساختار تابع:

analogWrite(pin, value);
  • pin: شماره پایه دارای قابلیت PWM
  • value: مقدار چرخه کاری مورد نظر

در Arduino Uno معمولی، مقدار PWM از ۰ تا ۲۵۵ است:

مقدارمفهوم تقریبی
۰خروجی خاموش
۶۴چرخه کاری حدود ۲۵٪
۱۲۸چرخه کاری حدود ۵۰٪
۱۹۲چرخه کاری حدود ۷۵٪
۲۵۵خروجی کاملا روشن

این مقادیر برای PWM هشت بیتی در Arduino Uno هستند. در بعضی بردهای دیگر، محدوده مقدار و روش تنظیم PWM متفاوت است.

در Arduino Uno، پایه های PWM با علامت ~ روی برد مشخص می شوند. در مدل رایج Uno مبتنی بر ATmega328P، این پایه ها شامل 3، 5، 6، 9، 10 و 11 هستند.

نکته: analogWrite() را نباید با analogRead() اشتباه بگیرید. اولی خروجی PWM ایجاد می کند و دومی مقدار ورودی آنالوگ را می خواند.

۸. مثال عملی دوم: کنترل شدت نور LED با analogWrite()

در این مثال، با تغییر مقدار PWM شدت نور LED تغییر می کند.

قطعات مورد نیاز

  • Arduino Uno
  • یک LED
  • یک مقاومت ۲۲۰ یا ۳۳۰ اهم
  • بردبرد
  • سیم جامپر

اتصال مدار

  1. پایه PWM شماره ۹ را به یک سر مقاومت وصل کنید.
  2. سر دیگر مقاومت را به آند LED وصل کنید.
  3. کاتد LED را به GND وصل کنید.

مقاومت باید به صورت سری با LED قرار گیرد تا جریان محدود شود.

کد برنامه

const int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  analogWrite(ledPin, 0);
  delay(1000);

  analogWrite(ledPin, 64);
  delay(1000);

  analogWrite(ledPin, 128);
  delay(1000);

  analogWrite(ledPin, 192);
  delay(1000);

  analogWrite(ledPin, 255);
  delay(1000);
}

نتیجه برنامه

شدت نور LED به صورت مرحله ای تغییر می کند. در مقدار ۰، LED خاموش است و در مقدار ۲۵۵، خروجی در بیشترین سطح PWM قرار می گیرد.

مقادیر میانی، شدت نور متفاوتی ایجاد می کنند؛ اما روشنایی درک شده توسط چشم لزوما متناسب و خطی با مقدار PWM نیست.

نکته: این مثال برای پایه PWM شماره ۹ در Arduino Uno نوشته شده است. هر پایه دیجیتال Uno قابلیت PWM ندارد.

۹. مثال عملی سوم: کنترل شدت نور LED با پتانسیومتر

اکنون دو مفهوم ورودی آنالوگ و خروجی PWM را ترکیب می کنیم.

در این مدار، آردوینو مقدار پتانسیومتر را می خواند و بر اساس آن شدت نور LED را تنظیم می کند.

اتصال مدار

  • پایه وسط پتانسیومتر به A0
  • دو پایه کناری پتانسیومتر به 5V و GND
  • پایه PWM شماره ۹ به مقاومت سری LED
  • کاتد LED به GND

کد برنامه

const int potPin = A0;
const int ledPin = 9;

int potValue = 0;
int pwmValue = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  potValue = analogRead(potPin);

  pwmValue = map(potValue, 0, 1023, 0, 255);

  analogWrite(ledPin, pwmValue);

  Serial.print("Potentiometer = ");
  Serial.print(potValue);

  Serial.print(" | PWM = ");
  Serial.println(pwmValue);

  delay(20);
}

بررسی کد

تابع map() مقدار را از یک بازه به بازه دیگر تبدیل می کند.

در این مثال:

  • مقدار ورودی ۰ به PWM برابر ۰ تبدیل می شود.
  • مقدار ورودی ۱۰۲۳ به PWM برابر ۲۵۵ تبدیل می شود.
  • مقادیر بین این دو، به صورت متناسب به محدوده PWM تبدیل می شوند.

تابع map() مقدار را به صورت عدد صحیح محاسبه می کند و نتیجه آن لزوما گرد کردن دقیق ریاضی نیست.

با چرخاندن پتانسیومتر، مقدار PWM تغییر می کند و LED کم نور یا پرنور می شود.

۱۰. تفاوت analogRead و analogWrite

ویژگیanalogRead()analogWrite()
عملکردخواندن ورودی آنالوگتولید خروجی PWM در بردهای پشتیبانی شده
جهت دادهاز مدار به آردوینواز آردوینو به مدار
مثال در Unoخواندن پتانسیومتر از A0کنترل LED با پایه PWM
محدوده رایج در Uno۰ تا ۱۰۲۳۰ تا ۲۵۵
نیاز به پایه مخصوصورودی آنالوگ مناسبپایه دارای قابلیت PWM

به خاطر داشته باشید که خروجی PWM، ولتاژ آنالوگ واقعی نیست. اگر به ولتاژ آنالوگ واقعی نیاز دارید، باید از بردی با DAC یا از مدار مناسب دیگری استفاده کنید. فیلتر پایین گذر می تواند در شرایط مناسب میانگین سیگنال PWM را به ولتاژی تقریبا آنالوگ تبدیل کند، اما طراحی آن به بار و دقت مورد نیاز وابسته است.

۱۱. تفاوت Arduino Uno و ESP32

مفهوم ورودی آنالوگ و PWM در بردهای مختلف مشابه است، اما جزئیات فنی یکسان نیستند.

Arduino Uno

  • ADC معمولی ۱۰ بیتی با مقدارهای ۰ تا ۱۰۲۳
  • ولتاژ مرجع پیش فرض نزدیک ۵ ولت
  • پایه های PWM مشخص شده با علامت ~
  • analogWrite() با مقدار معمول ۰ تا ۲۵۵

ESP32

  • بسیاری از مدل های ESP32 دارای ADC با وضوح اسمی ۱۲ بیت هستند، اما مقدار خوانده شده، محدوده قابل اندازه گیری و دقت واقعی به مدل و تنظیمات وابسته است.
  • ورودی های GPIO در بسیاری از مدل ها برای منطق ۳٫۳ ولت طراحی شده اند و نباید مستقیما به ۵ ولت متصل شوند.
  • روش تولید PWM در نسخه های مختلف Arduino-ESP32 ممکن است با Arduino Uno متفاوت باشد. در نسخه های جدیدتر، API مربوط به LEDC نیز رایج است.
  • شماره پایه های قابل استفاده برای ADC و PWM به مدل دقیق برد بستگی دارد.

اگر قصد دارید همین مثال ها را روی ESP32 اجرا کنید، ابتدا مدل برد و نسخه هسته Arduino-ESP32 را مشخص کنید و کد را بر اساس مستندات همان نسخه بررسی کنید.

۱۲. اشتباهات رایج

استفاده از پایه نامناسب برای PWM

در Arduino Uno معمولی، همه پایه های دیجیتال قابلیت PWM ندارند.

راه حل: پایه های دارای علامت ~ را بررسی کنید.

اتصال ولتاژ بالاتر از محدوده مجاز به ورودی آنالوگ

این اشتباه ممکن است به میکروکنترلر آسیب برساند.

راه حل: پیش از اتصال حسگر یا باتری، ولتاژ خروجی آن را اندازه بگیرید و در صورت نیاز از تقسیم ولتاژ یا مدار واسط مناسب استفاده کنید.

فراموش کردن مقاومت سری LED

حتی اگر شدت نور با PWM کنترل شود، LED همچنان به محدود کردن جریان نیاز دارد.

راه حل: مقاومت سری مناسب را بر اساس ولتاژ و جریان هدف انتخاب کنید.

اشتباه گرفتن محدوده ADC و PWM

در Arduino Uno، analogRead() معمولا عددی بین ۰ تا ۱۰۲۳ و analogWrite() عددی بین ۰ تا ۲۵۵ می گیرد.

راه حل: در صورت تبدیل مقدار ورودی به خروجی، از نگاشت درست مانند تابع map() استفاده کنید.

انتظار ولتاژ آنالوگ واقعی از analogWrite()

خروجی PWM یک موج دیجیتال با چرخه کاری قابل تنظیم است.

راه حل: اگر ولتاژ آنالوگ واقعی لازم است، از DAC یا مدار تبدیل مناسب استفاده کنید.

نوسان عدد ورودی

مقادیر ADC ممکن است به دلیل نویز، سیم کشی نامناسب یا ناپایداری منبع تغییر کنند.

راه حل: سیم کشی را کوتاه و مناسب نگه دارید، زمین مشترک را بررسی کنید و در صورت نیاز از روش های فیلتر نرم افزاری یا سخت افزاری استفاده کنید.

۱۳. تمرین های پیشنهادی

تمرین اول: خواندن مقدار پتانسیومتر

برنامه ای بنویسید که مقدار پتانسیومتر را از A0 بخواند و در Serial Monitor نمایش دهد.

تمرین دوم: محاسبه ولتاژ

کد خواندن پتانسیومتر را تغییر دهید تا علاوه بر مقدار ADC، ولتاژ تقریبی ورودی نیز نمایش داده شود.

تمرین سوم: کنترل نور LED

با استفاده از پتانسیومتر و analogWrite()، شدت نور LED را از کمترین تا بیشترین مقدار کنترل کنید.

تمرین چهارم: تغییر محدوده خروجی

برنامه را تغییر دهید تا مقدار PWM فقط بین ۵۰ و ۲۰۰ تغییر کند. از تابع map() یا یک محاسبه مناسب استفاده کنید.

تمرین پنجم: آزمایش با برد دیگر

اگر برد ESP32 در اختیار دارید، مدل دقیق برد و محدوده مجاز ADC آن را بررسی کنید و سپس برنامه خواندن پتانسیومتر را برای آن سازگار کنید.

جمع بندی

در این آموزش یاد گرفتیم:

  • ورودی آنالوگ برای اندازه گیری ولتاژهای متغیر استفاده می شود.
  • analogRead() مقدار ADC را برمی گرداند.
  • analogWrite() در Arduino Uno معمولی، خروجی PWM ایجاد می کند.
  • با ترکیب پتانسیومتر، analogRead()، تابع map() و analogWrite() می توان شدت نور LED را کنترل کرد.
  • محدوده ولتاژ و قابلیت های ADC و PWM در بردهای مختلف یکسان نیستند.

پس از یادگیری این مفاهیم، می توانید به سراغ خواندن حسگرهای آنالوگ، اندازه گیری ولتاژ باتری با تقسیم کننده ولتاژ و کنترل بارها با PWM بروید.