آیرو — خودآموز رباتیک

فصل ۱ از ۱۱

پیشرفت ترم
۰٪

ترم ۵ · مهندس ربات: C++، کنترل پیشرفته و پروژه نهایی

زبان دوم: چرا و چطور

فصل ۱پیش‌نمایش رایگان
۱۷ دقیقه مطالعه فصل ۱

در این فصل چه می‌سازی#

چهار ترم است که همه‌چیز را با یک زبان ساخته‌ای: MicroPython. با همان یک زبان از یک LED چشمک‌زن شروع کردی و رسیدی به رباتی که خط را دنبال می‌کند، از گوشی فرمان می‌گیرد و با هوش مصنوعی حرف می‌زند. حالا در ترم آخر یک زبان دوم شروع می‌کنیم: C++ — بخوان «سی پلاس پلاس». نترس؛ تو از چیزی که فکر می‌کنی جلوتری. برنامه‌نویسی یعنی متغیر، شرط، حلقه و تابع — و همه‌ی این‌ها را بلدی. امروز فقط زبان عوض می‌شود، نه فکر کردن. مثل راننده‌ای که پشت ماشین تازه‌ای می‌نشیند: دنده جای دیگری است، ولی رانندگی همان است.

مهندس نوجوانِ دوزبانه بین دو حباب گفت‌وگو با برچسب‌های Python و C++، یک ربات دوچرخ در دست، و سه نشان شناور: سرعت، جام مسابقات، و ماژول‌های Arduino

آخر این فصل می‌توانی:

  • سه دلیل یادگیری C++ را بگویی: سرعت اجرا، دنیای مسابقات ربات، و اکوسیستم بزرگ Arduino.
  • با تشبیه «مترجم همزمان در برابر کتاب ترجمه‌شده» توضیح بدهی compile یعنی چه و چرا C++ سریع‌تر است.
  • Arduino IDE و هسته‌ی ESP32 را نصب کنی و برد و پورت درست را انتخاب کنی.
  • ساختار setup/loop را بشناسی و همان Blink ترم ۱ را به C++ ترجمه، کامپایل و روی برد واقعی upload کنی.
  • دو خطای کلاسیک — پورت/برد غلط و سمی‌کالن جاافتاده — را از روی متن پیام رفع کنی و راه برگشت به MicroPython را بلد باشی.

قبل از شروع: چک‌لیست پیش‌نیاز#

قبل از ادامه این سه تا را چک کن — اگر یکی‌شان لنگ می‌زند، اول برگرد همان فصل:

  • از ترم ۱، فصل ۴: Thonny نصب است، درایور USB کار می‌کند و فریمور MicroPython روی بردت Flash شده. خبر خوب: درایور همان است، پورت COM همان است، و راه برگشت به MicroPython هم دقیقاً همان فلش است.
  • از ترم ۱، فصل ۵: Blink را با machine.Pin و time.sleep نوشته‌ای. امروز همان برنامه را به زبان دوم ترجمه می‌کنیم.
  • از ترم ۱، فصل ۷: حلقه‌ی while True — قلب مدل اجرای MicroPython. امروز قِل واقعی loop را می‌فهمی.

لوازم این فصل:

قطعه / ابزار تعداد جایگزین
برد ESP32 DevKit + کابل USB دیتا ۱
Breadboard + LED قرمز + مقاومت ۲۲۰ اهم ۱ همان مدار Blink ترم ۱
سیم جامپر نری-نری ۲
کامپیوتر با اینترنت (برای دانلود IDE و هسته) ۱ مسیر شبیه‌ساز آخر همین فصل

۱. راز سرعت: مترجم همزمان یا کتاب ترجمه‌شده؟#

قبل از نصب هر چیزی، بیا بفهمیم فرق واقعی این دو زبان کجاست — چون همین فرق، جواب سؤال «چرا C++ سریع‌تر است؟» هم هست.

یک سخنران خارجی را تصور کن که برای جمعی فارسی‌زبان حرف می‌زند. راه اول: یک مترجم همزمان کنارش می‌ایستد و جمله‌به‌جمله ترجمه می‌کند. راحت است، همان لحظه جواب می‌گیری، ولی همه‌چیز کُند پیش می‌رود — هر جمله اول باید شنیده، بعد ترجمه، بعد گفته شود. MicroPython دقیقاً همین است: داخل ESP32 تو یک مترجم همزمان زندگی می‌کند که اسمش interpreter است. هر بار برنامه‌ات اجرا می‌شود، این مترجم خط‌به‌خط کد Python تو را می‌خواند و همان لحظه برای تراشه ترجمه می‌کند. برای همین REPL داشتیم: یک خط می‌نوشتی، همان لحظه جواب می‌گرفتی. عالی برای یاد گرفتن — ولی تراشه‌ی بیچاره نصف زورش صرف ترجمه می‌شود.

راه دوم: کتاب سخنران را از قبل، یک بار برای همیشه ترجمه کنی و چاپ‌شده دست مردم بدهی. آماده‌سازی‌اش زمان می‌برد، ولی موقع خواندن دیگر هیچ ترجمه‌ای در کار نیست — با سرعت کامل می‌خوانی. C++ همین‌طور کار می‌کند: برنامه‌ات روی کامپیوتر خودت توسط ابزاری به اسم کامپایلر یک‌بار به زبان مادری تراشه ترجمه می‌شود — به این کار می‌گویند compile — و بعد فایل ترجمه‌شده داخل برد ریخته می‌شود. از آن به بعد، ESP32 فقط اجرا می‌کند؛ بدون مترجم، با تمام سرعت. جلسه‌ی سوم همین ترم، این سرعت را با چشم خودت اندازه می‌گیری.

اما هیچ‌چیز مجانی نیست: هر بار حتی یک حرف از کد عوض شود، باید دوباره compile و upload کنی — و خبری از REPL هم نیست. برای همین MicroPython را کنار نمی‌گذاریم؛ دو ابزار برای دو جور کار: آزمایش سریع و ایده‌پردازی با MicroPython؛ سرعت و کنترل دقیق و مسابقه با C++.

💡 نکته: سه دلیل محکم برای این زبان دوم داشته باش: سرعت (همین برد، ده‌ها برابر تندتر)، مسابقات (دنیای WRO و FTC پر از بردهای خانواده‌ی Arduino و کد C++ است)، و اکوسیستم Arduino (برای تقریباً هر قطعه‌ای یک کتابخانه‌ی آماده هست).

چالش: مترجم کجا، کامپایلر کجا؟

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

۲. خانه‌ی زبان دوم را نصب کن: Arduino IDE#

همان‌طور که خانه‌ی MicroPython برنامه‌ی Thonny بود، خانه‌ی C++ ما محیطی است به اسم Arduino IDE — رایگان، برای ویندوز و مک و لینوکس. نشانی دانلود و نسخه‌ی پیشنهادی را در جزوه‌ی همراه (سایت رسمی) پیدا کن، چون این چیزها عوض می‌شوند. نصبش مثل هر برنامه‌ی دیگری است: Next، Next، Finish.

بازش که می‌کنی، یک صفحه‌ی ساده می‌بینی با دو دکمه‌ی مهم بالای صفحه: یک تیک ✓ یعنی «compile کن» و یک فلش ← یعنی «بفرست توی برد» — به این کار می‌گوییم Upload. به هر برنامه در این محیط می‌گویند Sketch یعنی «طرح».

آناتومی محیط Arduino IDE: نوار بالا با دکمه‌ی تیک برای compile و دکمه‌ی فلش برای Upload، منوهای Board و Port، و دو جعبه‌ی خالی setup و loop در ویرایشگر

اما یک قدم مهم مانده. Arduino IDE از اول فقط بردهای خود Arduino را می‌شناسد؛ اسم ESP32 را که بیاوری، می‌گوید «این کیست؟». باید معرفی‌شان کنیم. این کار با نصب بسته‌ای به اسم هسته‌ی ESP32 انجام می‌شود: بسته‌ای که کامپایلر و ابزار upload مخصوص تراشه‌ی ما را به IDE اضافه می‌کند. دو قدم دارد:

  1. از منوی File گزینه‌ی Preferences را باز کن؛ کادری هست به اسم «Additional boards manager URLs» — نشانیِ داخل جزوه را عیناً همان‌جا کپی کن و OK بزن.
  2. از پنل کناری، Boards Manager را باز کن، در جستجو بنویس esp32، و بسته‌ای که نویسنده‌اش Espressif است را Install کن. این بسته حجیم است — یک کامپایلر کامل داخلش است! — پس چند دقیقه صبر لازم دارد.

نصب که تمام شد، دو انتخاب همیشگی از منوی Tools:

  1. گزینه‌ی Board را بزن و از خانواده‌ی esp32، ESP32 Dev Module را انتخاب کن.
  2. گزینه‌ی Port را بزن و همان پورت COM آشنای ترم ۱ را انتخاب کن.

⚠️ مواظب باش: اگر Thonny باز و به برد وصل است، اول ببندش یا Stop را بزن. پورت مثل گوشی تلفن است: دو نفر هم‌زمان نمی‌توانند با یک گوشی حرف بزنند — یا Thonny به برد وصل است یا Arduino IDE، نه هر دو.

چک کن: در منوی Tools، جلوی Board باید «ESP32 Dev Module» و جلوی Port باید همان COM بردت نوشته شده باشد.

چالش: هسته‌ی ESP32 چه‌کار می‌کند؟

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

۳. دو جعبه‌ی جادویی: setup و loop#

از منوی File گزینه‌ی New Sketch را بزن. اوه — صفحه خالی نیست! از قبل چیزی نوشته شده:

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

این قالب، بزرگ‌ترین فرق فکری امروز است. در MicroPython برنامه مثل دستور پخت بود: از بالا به پایین اجرا می‌شد و اگر تکرار می‌خواستی، خودت با while True حلقه می‌ساختی. دنیای Arduino همان منطق را دارد، فقط از قبل قالب‌بندی‌اش کرده و دو جعبه به تو می‌دهد:

  • جعبه‌ی setup که فقط یک بار موقع روشن شدن (یا ریست) برد اجرا می‌شود — جای کارهای آماده‌سازی، مثل معرفی پایه‌ها.
  • جعبه‌ی loop که بعد از setup، بی‌پایان و پشت‌سرهم اجرا می‌شود — دقیقاً همان while True خودمان، فقط اسم و شکلش فرق دارد!

مثل یک مسابقه‌ی دو: setup یعنی بستن بند کفش و گرم کردن — یک بار. loop یعنی دور زدن پیست — تا وقتی برق هست.

دو چیز ریز دیگر هم در همین قالب می‌بینی. یک: به‌جای تورفتگیِ Python، بدنه‌ی هر بخش بین دو آکولاد { و } می‌نشیند — دیوارهای جعبه. دو: کلمه‌ی void جلوی اسم‌ها یعنی «این بخش چیزی برنمی‌گرداند» — فعلاً همین‌طور بنویس؛ فصل ۳ که توابع C++ را کامل یاد می‌گیریم، دقیق ادایش می‌کنیم. و یک قانون نقطه‌گذاری تازه: هر دستور در C++ با سمی‌کالن ; تمام می‌شود، مثل نقطه‌ی آخر جمله. امروز فقط رعایتش می‌کنیم؛ فصل بعد کامل مالِ تو می‌شود.

چالش: چند بار چشمک؟

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

مدار امروز همان مدار عزیز ترم ۱ است: LED قرمز با مقاومت ۲۲۰ اهم به GPIO 25. اگر هنوز روی Breadboard داری، هیچ‌چیز را عوض نکن — فقط زبان عوض می‌شود!

حالا در ویرایشگر تایپ کن — این برنامه‌ی کامل توست (همین کد در src/blink_cpp.ino کنار درس هم هست):

// Term 5 - Session 01 - Blink dar C++ (tarjome-ye blink-e term 1)
// LED + moghavemat 220 -> GPIO 25 (pin-map-e standard-e dore)

void setup() {
  pinMode(25, OUTPUT);        // pin 25 ra khorooji kon (mesle Pin(25, Pin.OUT))
}

void loop() {
  digitalWrite(25, HIGH);     // LED roshan (mesle led.value(1))
  delay(500);                 // 500 millisanie sabr kon (mesle time.sleep(0.5))
  digitalWrite(25, LOW);      // LED khamush
  delay(500);
}

بیا خط‌به‌خطش را با چیزی که بلدی گره بزنیم:

  • pinMode(25, OUTPUT); همان کاری را می‌کند که Pin(25, Pin.OUT) می‌کرد: به تراشه می‌گوید پایه‌ی ۲۵ خروجی است. چون آماده‌سازی است، جایش در setup است.
  • digitalWrite(25, HIGH); یعنی پایه‌ی ۲۵ را روشن کن — HIGH همان ۱ خودمان است و LOW همان ۰.
  • delay(500); همان time.sleep(0.5) است با یک تفاوت موذی: delay به میلی‌ثانیه کار می‌کند، نه ثانیه! نیم ثانیه یعنی ۵۰۰.

و راستی دیدی import هم نبود؟ pinMode و دوستانش در دنیای Arduino از اول آماده‌اند.

حالا برنامه را روی برد بفرست، قدم‌به‌قدم:

  1. اول دکمه‌ی تیک ✓ را بزن: compile. بار اول، IDE می‌پرسد هر Sketch باید داخل فولدری هم‌نام خودش باشد؛ OK را بزن تا خودش بسازد.
  2. پایین صفحه پیام موفقیت می‌آید: چند درصد از حافظه‌ی برنامه استفاده شده.
  3. حالا دکمه‌ی فلش ← را بزن: upload. پایین صفحه نگاه کن تا برنامه داخل برد ریخته شود.

⚠️ مواظب باش: الان روی برد تو فریمور MicroPython و فایل‌های main.py نشسته‌اند. دکمه‌ی upload آردوینو، برنامه‌ی C++ را جای همه‌ی این‌ها می‌نویسد: بعد از upload، دیگر MicroPython روی برد نیست. نترس! چیزی از دست نمی‌رود، چون همه‌ی کدهای دوره را روی کامپیوترت هم داری، و راه برگشت را آخر همین فصل می‌رویم. برد مثل تخته‌سیاه است — می‌شود پاک کرد و دوباره نوشت، هزار بار.

چک کن: باید LED روی Breadboard چشمک بزند: نیم‌ثانیه روشن، نیم‌ثانیه خاموش. همین الان اولین برنامه‌ی کامپایلی عمرت را نوشتی، ترجمه کردی و روی سخت‌افزار واقعی اجرا کردی!

🔧 اگر کار نکرد: upload رفت ولی LED چشمک نمی‌زند؟ LED جهت دارد — احتمالاً برعکس است: پایه‌ی بلندش باید از راه مقاومت سمت GPIO 25 باشد و پایه‌ی کوتاهش سمت GND. اگر LED خیلی کم‌نور است و اصلاً چشمک نمی‌زند، احتمالاً به عادت Python نوشته‌ای delay(0.5)؛ delay میلی‌ثانیه می‌گیرد، پس بنویس delay(500). و اگر پیام گرفتی 'digitalwrite' was not declared — C++ هم مثل Python به حروف بزرگ و کوچک حساس است: digitalWrite با W بزرگ درست است؛ املای پیشنهادی خود کامپایلر را بپذیر.

قطعه هنوز به دستت نرسیده؟ نگران نباش — یک نکته‌ی مهم درباره‌ی شبیه‌ساز همین‌جاست:

۵. دو خطای کلاسیک را عمداً بساز#

طبق سنت دوره، حالا که کار می‌کند، خرابش کنیم — این دو خطا را بالاخره یک روز می‌بینی و بهتر است اولین بار اینجا باشد، نه وسط پروژه.

خرابکاری اول — پورت غلط: از منوی Tools یک پورت دیگر انتخاب کن که اصلاً وجود ندارد و upload بزن. چیزی شبیه این می‌بینی:

A fatal error occurred: Could not open COM7, the port doesn't exist
Failed uploading: uploading error: exit status 2

بخوانش: «نتوانستم COM7 را باز کنم — چنین پورتی وجود ندارد.» مثل زدنِ زنگِ خانه‌ای که اصلاً وجود ندارد! رفعش یک کلیک است: Tools بعد Port، پورت درست.

خرابکاری دوم — برد غلط: این‌بار پورت درست، ولی از Tools بعد Board به‌جای ESP32 Dev Module عمداً یک برد دیگر (مثلاً Arduino Uno) انتخاب کن. compile شاید حتی رد شود، ولی upload این را می‌دهد:

avrdude: stk500_recv(): programmer is not responding
Failed uploading: uploading error: exit status 1

این غرغرها یعنی: ابزار upload دارد با زبانِ یک برد دیگر با ESP32 حرف می‌زند و جوابی نمی‌گیرد — انگار به تراشه‌ی ما زبانی بیگانه حرف می‌زند! پیام‌ها هر چه باشد، درمان یکی است و از امروز چک‌لیست همیشگی توست: اول Board، بعد Port، بعد Upload. برد را برگردان روی ESP32 Dev Module — دوباره سبز.

خرابکاری سوم — سمی‌کالن جاافتاده: محبوب‌ترین خطای تازه‌کارهای C++. سمی‌کالن آخرِ delay(500); اولی را پاک کن و compile بزن:

error: expected ';' before 'digitalWrite'
   11 |   digitalWrite(25, LOW);
      |   ^~~~~~~~~~~~

نفس عمیق — این متن قرمز را با هم بخوانیم، چون خواندن خطای کامپایلر یک مهارت واقعی است. پیام می‌گوید: «قبل از digitalWrite انتظار یک ; داشتم.» نکته‌ی ظریف را ببین: تو سمی‌کالن خط ۱۰ را پاک کردی، ولی کامپایلر خط ۱۱ را نشان می‌دهد! چرا؟ چون وقتی نقطه‌ی آخر جمله را نگذاری، شنونده تازه وسط جمله‌ی بعدی گیج می‌شود؛ کامپایلر هم جمله‌ی قبلی را ادامه داد تا رسید به جایی که دیگر معنا نداشت. پس قانون طلایی خواندن این خطا: یک خط بالاتر از جای اعلام‌شده را هم نگاه کن. سمی‌کالن را برگردان — سبز.

چالش: اول کدام منو؟

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

۶. یک برد، دو دنیا#

حالا که هر دو نسخه‌ی Blink را دیده‌ای، بیا کنار هم بگذاریمشان — این جدول را در دفترچه‌ی مهندسی‌ات هم بکش، بهترین برگه‌ی تقلبِ حلال این ترم است:

کار MicroPython (ترم ۱) C++ (این فصل)
آماده کردن ابزار پایه‌ها from machine import Pin لازم نیست — از اول آماده است
پایه ۲۵ = خروجی led = Pin(25, Pin.OUT) pinMode(25, OUTPUT);
روشن کردن led.value(1) digitalWrite(25, HIGH);
صبر نیم‌ثانیه time.sleep(0.5) — ثانیه delay(500); — میلی‌ثانیه!
تکرار بی‌پایان while True: + تورفتگی void loop() { } + آکولاد
پایان هر دستور رفتن به خط بعد سمی‌کالن ;

می‌بینی؟ شش خط، شش ترجمه. هیچ فکرِ تازه‌ای اینجا نیست — فقط لهجه عوض شده. برای مقایسه، نسخه‌ی کامل MicroPython همان چشمک این است (از ترم ۱، همان که در آزمایشگاه اجرا می‌شود):

# Term 1 - Session 05 - blink (nosakhe MicroPython baraye moghayese)
from machine import Pin
import time

led = Pin(25, Pin.OUT)

while True:
    led.value(1)
    time.sleep(0.5)
    led.value(0)
    time.sleep(0.5)

و حالا راه برگشت — قولی که دادم. هر وقت خواستی به MicroPython برگردی، Arduino IDE را ببند، Thonny را باز کن و همان مسیر ترم ۱، فصل ۴ را برو: فلش کردن فریمور MicroPython روی برد. دو-سه دقیقه بعد، REPL برمی‌گردد، انگار نه انگار. پس خیالت راحت: هر وقت خواستی MicroPython، فلش کن؛ هر وقت خواستی C++، از آردوینو upload کن. یک برد، دو دنیا — و کلید هر دو دست توست.

یک برد ESP32 در وسط مثل جزیره‌ای بین دو دروازه: دروازه‌ی آبی MicroPython با فلش «فلش فریمور» و دروازه‌ی نارنجی C++/Arduino با فلش «upload اسکچ»، و فلش‌های دوطرفه بالای تصویر که یعنی هر وقت خواستی بین دو دنیا رفت‌وآمد کن

واژه‌های تازه این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
C++ سی پلاس پلاس زبان دوم ما — کامپایلی و سریع، زبان دنیای Arduino
Arduino IDE آردوینو آی‌دی‌ئی محیط نوشتن، compile و upload برنامه‌های C++
Compile کامپایل ترجمه‌ی یک‌باره‌ی کل برنامه به زبان تراشه، روی کامپیوتر
Upload آپلود فرستادن برنامه‌ی ترجمه‌شده داخل برد
Sketch اسکچ اسم هر برنامه در دنیای Arduino
setup سِت‌آپ تابعی که فقط یک بار موقع روشن شدن برد اجرا می‌شود
loop لوپ تابعی که بی‌پایان تکرار می‌شود — همان while True خودمان
Semicolon سمی‌کالن علامت ; — نقطه‌ی پایان هر دستور C++

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

امروز اولین جمله‌هایت را به زبان دوم گفتی. فصل بعد می‌رویم سراغ قواعد دقیق این کشور تازه: جعبه‌های متغیری که رویشان برچسب نوع خورده، ماجرای کامل سمی‌کالن و آکولاد، و اینکه برد چطور با Serial با ما حرف می‌زند. پروژه‌ی دکمه و LED ترم ۱ را هم کامل به C++ ترجمه می‌کنیم — و دو غافلگیری می‌بینی که شاید باورت نشود: یک تقسیمِ ساده که در C++ جواب دیگری می‌دهد، و یک اشتباه تایپی که Python جلویش را می‌گرفت ولی C++ بی‌صدا اجرایش می‌کند!

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.