آردوینومقدماتی۸ دقیقه مطالعهArduino IDE 2.x / Uno R3 (avr-gcc)

متغیرها و انواع داده در آردوینو

متغیر و ثابت در زبان C++ آردوینو؛ انواع int و byte و long و float و bool، انتخاب میان const و define، سرریز عدد و یک اسکچ شمارنده با خروجی سریال مانیتور.

آنچه در این درس می‌آموزید

  • متغیر را با نام و نوع درست تعریف کنید و قواعد نام‌گذاری را رعایت کنید
  • نوع دادهٔ مناسب هر مقدار را از میان int و byte و long و float و bool انتخاب کنید
  • ثابت را با const تعریف کنید و بدانید چرا از
  • سرریز int روی Uno را توضیح دهید و در کدتان از آن پیشگیری کنید
نویسنده: تیم داکنامه · بازبینی: ۲۰۲۶-۱۰-۳۱
فهرست مطالب

تا حالا در اسکچ‌ها فقط اعداد ثابت دیدید: پین ۸، تأخیر ۱۰۰۰. برنامهٔ واقعی اطلاعاتی دارد که تغییر می‌کنند — شمارنده، زمان، نتیجهٔ خواندن یک سنسور. در این درس «متغیر» (Variable) را یاد می‌گیرید؛ خانه‌ای نام‌دار در حافظهٔ میکروکنترلر که مقداری از یک نوع مشخص نگه می‌دارد. آردوینو با زبان C++ برنامه‌نویسی می‌شود و انواع دادهٔ آن دقت و محدودهٔ متفاوتی دارند؛ انتخاب اشتباه نوع، رایج‌ترین علت مقادیر عجیب در برنامه‌های مبتدیان است.

تعریف متغیر و قواعد نام‌گذاری

یک متغیر با سه چیز ساخته می‌شود: نوع، نام و مقدار اولیه:

cpp
int counter = 0;        // Declare an int variable named counter
float voltage = 4.85;   // Declare a float variable named voltage

نام متغیر (Identifier) قواعدی دارد: فقط حروف انگلیسی، رقم و خط زیر (_) مجاز است؛ نام با رقم شروع نمی‌شود؛ بزرگی و کوچکی حرف مهم است (count و Count دو متغیر متفاوت‌اند) و نمی‌توانید از کلمات رزروشدهٔ زبان مثل int یا if استفاده کنید. نام را معنادار بگذارید: elapsedMs از x بهتر است، چون سه ماه بعد هم می‌فهمید چیست.

انواع دادهٔ پرکاربرد در Uno

هر نوع، اندازه‌ای از حافظه و محدوده‌ای از مقادیر دارد. روی برد Uno (میکروکنترلر ATmega328P با کامپایلر avr-gcc) این اندازه‌ها به این شکل‌اند:

نوع اندازه محدودهٔ مقادیر کاربرد معمول
int ۲ بایت −۳۲۷۶۸ تا ۳۲۷۶۷ شمارنده، شمارهٔ پین، اعداد کوچک
byte ۱ بایت ۰ تا ۲۵۵ مقادیر کوچک غیرمنفی؛ صرفه‌جویی در حافظه
long ۴ بایت حدود ±۲٫۱ میلیارد زمان بر حسب میلی‌ثانیه، اعداد بزرگ
unsigned long ۴ بایت ۰ تا حدود ۴٫۳ میلیارد شمارندهٔ زمان millis()؛ منفی نمی‌شود
float ۴ بایت اعشاری با حدود ۶ تا ۷ رقم دقت ولتاژ، دما، مقادیر اعشاری
bool ۱ بایت true یا false وضعیت روشن/خاموش، پرچم رویداد

نکتهٔ کلیدی همین جدول است: در برخی رایانه‌ها int چهار بایت است، اما روی Uno فقط ۲ بایت است و پس از ۳۲۷۶۷ سرریز می‌شود. برای زمان بر حسب میلی‌ثانیه (که در چند ساعت به میلیون‌ها می‌رسد) باید unsigned long بگیرید، نه int.

ثابت‌ها: const بهتر از define است

هر مقداری که در طول اجرای برنامه نباید تغییر کند را «ثابت» (Constant) کنید تا کامپایلر از تغییر تصادفی‌اش جلوگیری کند:

cpp
const int LED_PIN = 8;           // Recommended: a typed constant
#define DELAY_MS 1000            // Old style: a text replacement

هر دو کار می‌کنند، اما const بهتر است، به این دلایل:

  • const نوع دارد (int)؛ پس کامپایلر خطای نوع را می‌گیرد. #define فقط متن را جایگزین می‌کند و خطاهایش پیام‌های گیج‌کننده‌ای می‌سازند.
  • const محدوده (Scope) دارد و داخل تابع هم تعریف می‌شود؛ #define از نقطهٔ تعریف تا آخر فایل همه‌جا اثر می‌گذارد.
  • در پیام‌های خطا، نامِ ثابتِ const قابل‌فهم باقی می‌ماند.

در کدهای قدیمی اینترنتی زیاد #define می‌بینید؛ بخوانید و بفهمید، اما در کد خودتان const بنویسید.

اسکچ: شمارندهٔ چشمک‌زن با خروجی سریال

این اسکچ را آپلود کنید و «سریال مانیتور» (Serial Monitor) را از آیکن ذره‌بین در گوشهٔ بالا-راست IDE باز کنید؛ بادریت را همان 9600 که در کد نوشته‌اید انتخاب کنید:

blink-counter.ino
const int LED_PIN = 8;   // External LED on pin 8
const int DELAY_MS = 500;

int count = 0;  // Blink counter, starts at zero

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);  // Start serial communication at 9600 baud
}

void loop() {
  count = count + 1;  // Increase the counter by one
  Serial.print("Count: ");
  Serial.println(count);

  digitalWrite(LED_PIN, HIGH);
  delay(DELAY_MS);
  digitalWrite(LED_PIN, LOW);
  delay(DELAY_MS);
}

توضیح نکته‌های تازه:

  1. count = count + 1; — مقدار فعلی count خوانده می‌شود، یکی اضافه می‌شود و نتیجه دوباره در همان متغیر ذخیره می‌شود. میان‌بر رایج همین خط count++; است.
  2. Serial.begin(9600); — ارتباط سریال را با نرخ ۹۶۰۰ بیت بر ثانیه راه می‌اندازد؛ فقط یک بار در setup().
  3. Serial.print("Count: "); — عبارت را بدون خط جدید چاپ می‌کند؛ Serial.println(count); عدد را می‌چاپد و خط را می‌شکند. جمع این دو، هر چشمک را یک خط می‌کند.

خروجی سریال مانیتور قطعی است و به این شکل ادامه دارد:

خروجی کد

Count: 1 Count: 2 Count: 3 Count: 4

این خط‌ها تا وقتی برد روشن است ادامه پیدا می‌کنند و هر چشمک LED یکی دیگر را اضافه می‌کند.

سرریز و دقت اعشاری

دو تلهٔ عددی که باید از همین حالا بشناسید:

  • سرریز (Overflow) — هر نوع سقفی دارد و عبور از سقف، مقدار را از آن‌سوی محدوده می‌اندازد. یک int با مقدار ۳۲۷۶۷ روی Uno، با یک افزایش به −۳۲۷۶۸ تبدیل می‌شود؛ یعنی شمارندهٔ شما ناگهان منفی می‌شود. راه‌حل: برای مقادیر بزرگ long یا unsigned long بگیرید.
  • دقت float — float اعشاری دقیق نیست و فقط حدود ۶ تا ۷ رقم معنادار دارد. جمع‌کردن پیاپی مقادیر اعشاری کوچک، خطا انباشته می‌کند؛ برای همین است که مقایسهٔ دو float با == معمولاً بی‌جواب می‌ماند و باید اختلاف‌شان را با یک حد کوچک بسنجید.

اشتباهات رایج و عیب‌یابی

خطا یا نشانه علت رایج راه‌حل
expected ';' یا خطای نحو هنگام کامپایل جا انداختن سمی‌کالن یا پرانتز ناقص در خط قبلی شمارهٔ خطِ خطا را ببینید و خط قبلی را چک کنید؛ هر دستور با ; تمام می‌شود
was not declared in this scope نام متغیر غلط تایپ شده یا بعد از استفاده تعریف شده نام را دقیقاً با تعریف مقایسه کنید؛ تعریف متغیر باید قبل از خط استفاده باشد
invalid conversion / خطای نوع ریختن نوع ناسازگار، مثل متن در int نوع متغیر را با مقداری که می‌دهید هماهنگ کنید
شمارنده ناگهان عدد عجیب یا منفی می‌شود سرریز int روی Uno پس از ۳۲۷۶۷ نوع را به long یا unsigned long تغییر دهید
مقایسهٔ دو float جواب درست نمی‌دهد دقت محدود اعشاری اختلاف را با یک آستانهٔ کوچک بسنجید

تمرین‌ها

تمرین

تمرین ۱ — شمارندهٔ بازنشسته‌شونده

اسکچ شمارنده را طوری تغییر دهید که پس از رسیدن شمارنده به ۱۰، در چشمک بعدی از ۱ دوباره شروع کند. خروجی سریال باید فقط اعداد ۱ تا ۱۰ را بی‌نهایت بار تکرار کند.

نمایش راه‌حل

کافی است پس از افزایش، شمارنده را با یک شرط ساده چک کنید؛ در درس بعدی شرط‌ها را کامل می‌خوانید، اما الگوی if (x > 10) همین حالا هم خواناست:

cpp
const int LED_PIN = 8;
const int DELAY_MS = 500;

int count = 0;  // Blink counter, restarts after ten

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

void loop() {
  count = count + 1;
  if (count > 10) {
    count = 1;  // Restart the count after ten blinks
  }
  Serial.print("Count: ");
  Serial.println(count);

  digitalWrite(LED_PIN, HIGH);
  delay(DELAY_MS);
  digitalWrite(LED_PIN, LOW);
  delay(DELAY_MS);
}

خروجی سریال مانیتور قطعی است و این چرخه تا وقتی برد روشن است تکرار می‌شود:

خروجی کد

Count: 1 Count: 2 Count: 3 Count: 10 Count: 1 Count: 2

::: :::

خلاصه

  • متغیر خانه‌ای نام‌دار در حافظه است؛ با نوع و نام و مقدار اولیه تعریف می‌شود.
  • روی Uno مقدار int دو بایت است و پس از ۳۲۷۶۷ سرریز می‌شود؛ زمان میلی‌ثانیه‌ای را با unsigned long نگه دارید.
  • float فقط حدود ۶ تا ۷ رقم دقت دارد و برای مقایسهٔ دقیق مناسب نیست.
  • ثابت‌ها را با const تعریف کنید؛ نوع‌دار و محدود به همان بخش از کد است و خطاها را خواناتر نشان می‌دهد.
  • نام متغیر با رقم شروع نمی‌شود، بزرگی و کوچکی حروف مهم است و نام باید معنا داشته باشد.

حالا می‌توانید داده نگه دارید؛ گام بعدی تصمیم‌گرفتن است: اگر عددی بیشتر از چیزی بود چه؟ در درس بعدی با شرط‌ها و حلقه‌ها برنامه‌ها را هوشمند می‌کنید.

منابع و ارجاع‌ها

درس‌های مرتبط