آردوینومقدماتی۱۰ دقیقه مطالعهArduino IDE 2.x / Uno R3

شرط‌ها و حلقه‌ها در آردوینو

تصمیم‌گیری و تکرار در C++ آردوینو؛ if و else، عملگرهای مقایسه و منطقی، switch، حلقه‌های for و while و do-while با یک پروژهٔ چراغ راهنما روی سه LED.

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

  • با if و else و عملگرهای مقایسه و منطقی تصمیم‌گیری در کد را پیاده کنید
  • انتخاب میان چند حالت مشخص را با switch انجام دهید و break را جا نیندازید
  • حلقه‌های for و while و do-while را در جای درست به‌کار ببرید
  • یک توالی چراغ راهنما را با حلقه و شرط روی سه LED بسازید
نویسنده: تیم داکنامه · بازبینی: ۲۰۲۶-۱۰-۳۱
فهرست مطالب

برنامه‌های تاکنون خط‌به‌خط از بالا به پایین اجرا می‌شدند. برنامهٔ واقعی دو چیز بیشتر نمی‌خواهد: تصمیم (اگر چنین بود، آن کار را بکن) و تکرار (این کار را ده بار انجام بده). در این درس «دستور شرطی» (Conditional) و «حلقه» (Loop) را در زبان C++ یاد می‌گیرید و در پایان یک چراغ راهنمای سه‌رنگ با سه LED می‌سازید که توالی‌اش با حلقه و شرط نوشته شده است.

تصمیم با if و else

«دستور if» یک شرط می‌گیرد؛ اگر درست باشد، بلوک کد داخل آکولاد اجرا می‌شود:

cpp
if (count > 10) {
  count = 0;  // Reset the counter when it passes ten
}

شرط با «عملگرهای مقایسه» (Comparison Operators) ساخته می‌شود:

عملگر معنی مثال
== برابر است با x == 5
!= نابرابر است با x != 0
< و > کوچک‌تر / بزرگ‌تر x < 100
<= و >= کوچک‌تر یا مساوی / بزرگ‌تر یا مساوی x >= 3

چند شرط را با «عملگرهای منطقی» (Logical Operators) ترکیب می‌کنید: && یعنی و (هر دو باید درست باشند)، || یعنی یا (دست‌کم یکی)، و ! یعنی نقیض. با else if و else هم زنجیرهٔ گزینه‌ها می‌سازید:

cpp
if (temperature > 30) {
  // Hot path
} else if (temperature > 15) {
  // Mild path
} else {
  // Cold path
}

انتخاب چندگانه با switch

وقتی یک متغیر را با چند مقدار مشخص مقایسه می‌کنید، «دستور switch» از زنجیرهٔ بلند else if خواناتر است:

cpp
switch (mode) {
  case 1:
    // Fast mode
    break;
  case 2:
    // Slow mode
    break;
  default:
    // Unknown mode
    break;
}

هر case یک مقدار ممکن است و break اجرای switch را تمام می‌کند. بدون break، اجرا به case بعدی می‌ریزد و همهٔ بلوک‌های پایینی پشت‌سرهم اجرا می‌شوند — خطایی که کامپایلر نمی‌گیرد و فقط رفتار عجیب برنامه نشان می‌دهد. default هم جای حالت‌های پیش‌بینی‌نشده است.

تکرار با for و while و do-while

سه حلقه، یک هدف: تکرار. تفاوت در شرایط استفاده است:

  • for — وقتی تعداد تکرار از قبل معلوم است. سرِ حلقه سه بخش دارد: مقدار اولیه، شرط ادامه و گام. مثلاً for (int i = 1; i <= 5; i++) پنج بار اجرا می‌شود؛ i از ۱ شروع می‌شود، تا وقتی کوچک‌تر یا مساوی ۵ است ادامه می‌یابد و هر بار یکی زیاد می‌شود. دقت کنید حلقهٔ i < 5 با شروع از صفر هم پنج بار می‌زند؛ مرزِ شرط را همیشه دو بار چک کنید تا یکی کم یا زیاد نشود.
  • while — وقتی تعداد تکرار معلوم نیست و فقط شرط مهم است؛ شرط قبل از هر دور چک می‌شود و ممکن است اصلاً اجرا نشود.
  • do-while — مثل while است، اما شرط بعد از هر دور چک می‌شود؛ پس دست‌کم یک بار حتماً اجرا می‌شود.

یک حالت خاص مهم است: while (true) یعنی حلقهٔ همیشگی. در برنامهٔ رایانه‌ای این معمولاً باگ است، اما روی میکروکنترلر معنی دارد: دستگاه نباید خاموش شود و باید همیشه در حال پاسخ‌دادن باشد. در واقع loop() در اسکچ آردوینو خودش همین حلقهٔ همیشگی است که پشت‌صحنه اجرا می‌شود؛ گاهی هم داخل کد از while (true) برای «ایست تا وقتی رویداد رخ دهد» استفاده می‌کنیم، مثل انتظار برای اتصال سنسور.

پروژه: چراغ راهنما با سه LED

ابزارهای مورد نیاز

قطعه مقدار / مشخصات تعداد
برد آردوینو Uno ATmega328P ۱
LED قرمز ۵ میلی‌متری ۱
LED زرد ۵ میلی‌متری ۱
LED سبز ۵ میلی‌متری ۱
مقاومت ۲۲۰ اهم (هر LED یکی) ۳
برد سرهم‌بندی و سیم رابط نری به نری ۱ برد، حدود ۸ سیم

هر LED مثل درس مدار خارجی به یک مقاومت ۲۲۰ اهم نیاز دارد؛ ولتاژ مستقیم هر سه رنگ حدود ۲ ولت است و با فرمول R=Vs−VfIR = \frac{V_s - V_f}{I} همان ۳۰۰ اهمِ حساب‌شده و انتخاب استاندارد ۲۲۰ اهم به‌کار می‌آید.

سیم‌کشی، همان الگوی همیشگی:

از به
پین ۸ آردوینو مقاومت ۲۲۰ اهم، سپس آند LED قرمز
پین ۹ آردوینو مقاومت ۲۲۰ اهم، سپس آند LED زرد
پین ۱۰ آردوینو مقاومت ۲۲۰ اهم، سپس آند LED سبز
کاتد هر سه LED ریل زمین بردبورد
پین GND آردوینو ریل زمین بردبورد

اسکچ کامل:

traffic-light.ino
const int RED_PIN = 8;     // Red LED
const int YELLOW_PIN = 9;  // Yellow LED
const int GREEN_PIN = 10;  // Green LED

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(YELLOW_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
}

void loop() {
  // Green phase: blink twice, then stay on longer
  for (int i = 1; i <= 2; i++) {
    digitalWrite(GREEN_PIN, HIGH);
    if (i == 2) {
      delay(1500);  // The last flash stays on longer
    } else {
      delay(300);
    }
    digitalWrite(GREEN_PIN, LOW);
    delay(300);
  }

  // Yellow phase: short warning
  digitalWrite(YELLOW_PIN, HIGH);
  delay(1000);
  digitalWrite(YELLOW_PIN, LOW);

  // Red phase: stop
  digitalWrite(RED_PIN, HIGH);
  delay(2500);
  digitalWrite(RED_PIN, LOW);
}

توضیح نکته‌های کلیدی:

  1. سه ثابت با نام رنگ، شمارهٔ پین‌ها را نگه می‌دارند؛ خواندن و تغییر کد را ساده می‌کند.
  2. حلقهٔ for (int i = 1; i <= 2; i++) فاز سبز را دقیقاً دو بار تکرار می‌کند.
  3. شرط if (i == 2) در دور آخر حلقه، مدت روشنی را طولانی‌تر می‌کند؛ ترکیب حلقه و شرط در یک توالی واقعی.
  4. دقت کنید == مقایسه است، نه =؛ این دو را در بخش خطاها جدا می‌کنیم.
  5. هر فاز با خاموش‌کردن LED خودش تمام می‌شود، پس در هر لحظه فقط یک رنگ روشن است.

نتیجهٔ فیزیکی: سبز دو بار کوتاه می‌زند و یک‌ونیم ثانیه می‌ماند، زرد یک ثانیه روشن می‌شود و بعد قرمز دو‌ونیم ثانیه؛ سپس کل چرخه از اول. الگوی همان چراغ‌های خیابان، به‌دست کد شما.

خطاهای رایج

سه خطای کلاسیک این درس:

  • = به‌جای == — علامت = مقدار می‌دهد و == مقایسه می‌کند. شرط if (x = 5) همیشه درست از آب درمی‌آید، چون مقدار ۵ را در x می‌ریزد؛ متغیر شما بی‌سروصدا تغییر می‌کند و شرط بی‌معنا می‌شود.
  • جا انداختن break در switch — اجرا به caseهای بعدی می‌ریزد و چند بلوک پشت‌سرهم اجرا می‌شوند؛ بدون هیچ پیام خطایی.
  • مرز حلقه (Off-by-one) — for (int i = 0; i <= 5; i++) شش بار می‌زند، نه پنج بار؛ چون شرط شامل خود ۵ هم هست. تصمیم بگیرید شمارش از صفر است یا یک و شرط را با آن هماهنگ کنید.

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

خطا یا نشانه علت رایج راه‌حل
شرط همیشه درست به نظر می‌رسد و متغیر بی‌دلیل تغییر می‌کند استفاده از = به‌جای == داخل if مقایسه را با == بنویسید؛ بعضی‌ها برای پیشگیری، عدد را سمت چپ می‌گذارند: if (2 == i)
چند حالتِ switch پشت‌سرهم اجرا می‌شوند نبود break در انتهای هر case هر case را با break ببندید، مگر عمداً خواسته باشید سرریز شود
حلقه یک بار کم یا زیاد اجرا می‌شود مرز اشتباه: <= به‌جای < یا برعکس تعداد دقیق تکرار را با یک شمارنده در سریال مانیتور چاپ و شرط را اصلاح کنید
حلقه هیچ‌وقت تمام نمی‌شود و بقیهٔ کد اجرا نمی‌شود شرط حلقه هیچ‌وقت غلط نمی‌شود (مثلاً متغیر داخل حلقه تغییر نمی‌کند) مطمئن شوید متغیرِ شرط داخل حلقه به‌روز می‌شود؛ i++ را حذف نکرده باشید
LEDها با هم روشن می‌شوند یا هیچ‌کدام خطای سیم‌کشی یا شمارهٔ پین نادرست جدول سیم‌کشی را سطر‌به‌سطر چک کنید و شمارهٔ پین‌ها را با ثابت‌های کد تطبیق دهید

تمرین‌ها

تمرین

تمرین ۱ — فاز زرد دوم

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

نمایش راه‌حل

فقط یک بلوک زرد دوم با زمان‌های جدید، بین فاز قرمز و فاز سبز اضافه می‌شود؛ حلقهٔ سبز دست نمی‌خورد:

cpp
const int RED_PIN = 8;
const int YELLOW_PIN = 9;
const int GREEN_PIN = 10;

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(YELLOW_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
}

void loop() {
  for (int i = 1; i <= 2; i++) {
    digitalWrite(GREEN_PIN, HIGH);
    if (i == 2) {
      delay(1500);
    } else {
      delay(300);
    }
    digitalWrite(GREEN_PIN, LOW);
    delay(300);
  }

  digitalWrite(YELLOW_PIN, HIGH);
  delay(1000);
  digitalWrite(YELLOW_PIN, LOW);

  digitalWrite(RED_PIN, HIGH);
  delay(2500);
  digitalWrite(RED_PIN, LOW);

  // Second yellow phase before green starts again
  digitalWrite(YELLOW_PIN, HIGH);
  delay(500);
  digitalWrite(YELLOW_PIN, LOW);
}

توالی تازه: سبز، زرد، قرمز، زردِ کوتاه، و بازگشت به سبز. چون loop() همیشه از اول اجرا می‌شود، چرخه بی‌پایان تکرار می‌شود.

:::

خلاصه

  • if و else if و else مسیر اجرا را بر پایهٔ شرط عوض می‌کنند؛ مقایسه با == است، نه =.
  • && و || و ! شرط‌ها را ترکیب می‌کنند و switch انتخاب میان چند مقدار مشخص را خواناتر می‌کند؛ هر case به break نیاز دارد.
  • for برای تعداد معلوم، while برای شرط-محور و do-while برای اجرای دست‌کم یک بار؛ مرز حلقه را دوبار چک کنید.
  • while (true) روی میکروکنترلر معنا دارد: دستگاه باید همیشه پاسخ‌گو بماند؛ loop() خودش همین حلقهٔ همیشگی است.
  • چراغ راهنمای شما ترکیب حلقه و شرط در یک پروژهٔ واقعی بود.

کد چراغ راهنما همهٔ منطقش در loop() بود و تکرار داشت؛ در درس بعدی یاد می‌گیرید چنین بخش‌هایی را به توابع منتقل کنید تا کد کوتاه‌تر، تمیزتر و قابل‌استفاده‌تر شود.

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

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