🐞 ارورهای رایج آردوینو و معنی‌شان: از was not declared in this scope تا avrdude

✍️ تیم ووکوی فارسی ·

دکمه‌ی Verify یا Upload را زدی و پایین Arduino IDE چند خط نارنجی ظاهر شد که با exit status 1 تمام می‌شود. این ارورهای آردوینو ترسناک به نظر می‌رسند، ولی بیشترشان چند الگوی تکراری‌اند و هر کدام دقیقاً می‌گویند کجا را نگاه کنی. در این راهنما متن واقعی و انگلیسی رایج‌ترین خطاهای کامپایل آردوینو را آورده‌ایم، معنی فارسی هر کدام و راه‌حلش را گفته‌ایم و در آخر دو خطای آپلود را هم توضیح داده‌ایم که اصلاً ربطی به کد ندارند.

پیغام خطا را چطور بخوانیم؟

یک خط خطای کامل این شکلی است: sketch.ino:12:5: error: 'ledPin' was not declared in this scope. یعنی در فایل sketch.ino، خط ۱۲، ستون ۵. سه قانون طلایی:

ارورهای کامپایل

۱. 'ledPin' was not declared in this scope

معنی: کامپایلر اسمی را می‌بیند که نمی‌شناسد. علت‌ها: اشتباه تایپی یا بزرگ و کوچکی حروف (ledPin با LedPin فرق دارد)، متغیری که داخل setup تعریف شده و در loop استفاده شده، یا تابع کتابخانه‌ای که #include آن را ننوشته‌ای. راه‌حل: متغیرهای مشترک را بالای برنامه و بیرون از توابع تعریف کن و املای اسم را دقیق چک کن.

۲. expected ';' before '}' token

معنی: انتظار سمی‌کالن داشت ولی به آکولاد (یا کلمه‌ی دیگری) رسید. شکل‌های دیگرش expected ';' before 'delay' و مانند آن است. راه‌حل: آخر خط قبل از جایی که گفته، ; بگذار. یادت باشد بعد از #define و #include سمی‌کالن نمی‌آید.

۳. expected '}' at end of input

معنی: فایل تمام شد ولی یک آکولاد باز هنوز بسته نشده. راه‌حل: با Ctrl+T (فرمت خودکار) کد را مرتب کن؛ جایی که تورفتگی به هم می‌ریزد همان‌جاست. برعکسش، یک آکولاد اضافه، معمولاً expected declaration before '}' token می‌دهد.

۴. fatal error: DHT.h: No such file or directory

معنی: فایل کتابخانه پیدا نشد. راه‌حل: کتابخانه را از Library Manager نصب کن (برای این مثال «DHT sensor library»). اگر نصب است، اسم فایل را دقیق بنویس؛ #include <dht.h> با DHT.h فرق دارد. هشدار Multiple libraries were found هم یعنی دو نسخه از یک کتابخانه نصب است و بهتر است یکی را پاک کنی. راهنمای کتابخانه‌ها در کتابخانه در ووکوی و شبیه‌ساز آمده است.

۵. redefinition of 'void setup()'

معنی: یک چیز دو بار تعریف شده. معمولاً دو برنامه را پشت سر هم چسبانده‌ای و دو setup داری، یا در دو تب پروژه یک تابع تکراری هست. شکل دیگرش redefinition of 'int led' است. راه‌حل: دو برنامه را ادغام کن: فقط یک setup و یک loop، و محتوای هر دو داخل همان‌ها.

۶. invalid conversion from 'const char*' to 'int' [-fpermissive]

معنی: یک متن (داخل گیومه) را در متغیر عددی ریخته‌ای، مثل int x = "5";. راه‌حل: عدد را بدون گیومه بنویس. اگر متن از سریال آمده، با toInt() یا Serial.parseInt() به عدد تبدیلش کن.

۷. too few arguments to function 'void blinkLed(int, int)'

معنی: تابع دو ورودی می‌خواهد و تو یکی داده‌ای. too many arguments هم برعکس آن است. راه‌حل: تعریف تابع را نگاه کن و همان تعداد و همان ترتیب ورودی را بفرست.

۸. 'LiquidCrystal_I2C' does not name a type

معنی: کامپایلر این نوع را نمی‌شناسد. علت: #include کتابخانه را ننوشته‌ای، کتابخانه نصب نیست، یا اسم کلاس را اشتباه نوشته‌ای. راه‌حل: خط include را بالای برنامه بگذار و کتابخانه را نصب کن.

۹. expected unqualified-id before 'if'

معنی: دستوری بیرون از هر تابعی نوشته شده. بیرون از setup و loop فقط تعریف متغیر و تابع مجاز است. اگر digitalWrite را بیرون بنویسی، شکل دیگری از همین خطا را می‌بینی: expected constructor, destructor, or type conversion before '(' token. راه‌حل: دستور را داخل یک تابع ببر؛ معمولاً یک آکولاد زودتر از موقع بسته شده است.

۱۰. stray '\302' in program

معنی: در کد نویسه‌ای هست که کامپایلر نمی‌شناسد. \302 و \240 با هم یعنی «فاصله‌ی نشکن» که از کپی کردن کد از سایت یا PDF می‌آید. \342 معمولاً گیومه‌ی کج (“ ”) یا نیم‌فاصله است و \330 یا \333 یعنی یک حرف یا علامت فارسی، مثل سمی‌کالن فارسی «؛» یا عدد فارسی. راه‌حل: آن خط را کامل پاک کن و با کیبورد انگلیسی دوباره تایپ کن. در کد آردوینو فارسی فقط داخل کامنت یا داخل گیومه مجاز است.

۱۱. missing terminating " character

معنی: یک رشته باز شده و بسته نشده، یا داخل رشته یک گیومه‌ی دوتایی دیگر آمده. راه‌حل: گیومه‌ی پایانی را بگذار. اگر داخل متن گیومه لازم داری (مثلاً در HTML)، از گیومه‌ی تکی ' استفاده کن.

۱۲. lvalue required as left operand of assignment

معنی: چیزی را که نمی‌شود عوضش کرد، سمت چپ = گذاشته‌ای؛ مثل if (5 = x) یا digitalRead(2) = HIGH. راه‌حل: در مقایسه == بنویس.

۱۳. 'class LiquidCrystal_I2C' has no member named 'init'

معنی: کلاس پیدا شد ولی این تابع را ندارد. معمولاً کد برای نسخه‌ی دیگری از همان کتابخانه نوشته شده. راه‌حل: مثال‌های همان کتابخانه‌ای را که نصب کرده‌ای از منوی File و Examples باز کن و اسم تابع را از آنجا بردار؛ مثلاً بعضی نسخه‌ها begin() دارند و بعضی init().

خطاهای آپلود: کد سالم است، ارسال مشکل دارد

۱۴. avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00

همراهش معمولاً avrdude: stk500_recv(): programmer is not responding هم می‌آید. معنی: کامپایل موفق بود ولی کامپیوتر نتوانست با برد حرف بزند. راه‌حل‌ها به ترتیب: در منوی Tools برد و پورت درست را انتخاب کن؛ کابل را عوض کن (بعضی کابل‌ها فقط شارژ می‌کنند)؛ برای بردهای کپی درایور CH340 را نصب کن؛ برای نانوی کپی گزینه‌ی ATmega328P (Old Bootloader) را بزن؛ قطعه‌ای را که روی پین ۰ و ۱ است جدا کن؛ و برنامه‌ای که پورت سریال را گرفته ببند. برای ESP32 داستان فرق دارد: خطای آپلود ESP32 را ببین.

۱۵. Sketch too big و Low memory available

خطای کامل‌تر text section exceeds available space in board است. معنی: برنامه از ۳۲ کیلوبایت حافظه‌ی اونو بزرگ‌تر شده. هشدار Global variables use 95% of dynamic memory هم یعنی ۲ کیلوبایت رم دارد پر می‌شود و برنامه ممکن است عجیب رفتار کند. راه‌حل: متن‌های ثابت را داخل F("...") بنویس، آرایه‌های بزرگ را کوچک کن، کتابخانه‌های بی‌استفاده را حذف کن و برای پروژه‌ی خیلی بزرگ سراغ آردوینو مگا برو.

یک برنامه‌ی تمیز، با یادداشت خطاها

این برنامه بدون خطا کامپایل می‌شود. کامنت هر خط می‌گوید اگر آن جزئیات را جا بیندازی، کدام ارور را می‌گیری. در سریال مانیتور عدد ۱ را بفرست تا LED یک بار چشمک بزند.

// Compiles cleanly. Each comment names the error you get without that detail.
const int LED_PIN = 13;              // declared above setup: no "was not declared"

void blinkLed(int pin, int times) {  // two parameters: call it with two arguments
  for (int i = 0; i < times; i++) {  // no ; after the for (...)
    digitalWrite(pin, HIGH);
    delay(200);
    digitalWrite(pin, LOW);
    delay(200);
  }
}                                    // every { has its }: no "expected '}' at end of input"

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  int count = 3;                     // a number, not "3": no "invalid conversion"
  blinkLed(LED_PIN, count);          // both arguments: no "too few arguments"
  Serial.println(F("Send 1 to blink"));  // F() keeps the text in flash, saves RAM
}

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();          // type code with an English keyboard: no "stray"
    if (c == '1') {                  // == compares; = here would be a bug, not an error
      blinkLed(LED_PIN, 1);
    }
  }
}

تمرین خطاها در شبیه‌ساز

بهترین راه برای نترسیدن از ارورها این است که خودت عمداً بسازی‌شان. در شبیه‌ساز تینکرکد فارسی برنامه‌ی بالا را در مود آردوینو بچسبان، بعد یک سمی‌کالن را پاک کن یا اسم متغیر را عوض کن و ببین چه می‌شود. اجرای معمولی شبیه‌ساز پیغام ساده‌شده می‌دهد؛ ولی گزینه‌ی «اجرای واقعی» کد را با کامپایلر واقعی آردوینو (avr-gcc) کامپایل می‌کند و همان پیغام‌های Arduino IDE را با شماره‌ی خط و ستون نشان می‌دهد، به‌علاوه‌ی حجم دقیق برنامه. خواندن و نوشتن کد برای اونو رایگان است و «اجرای واقعی» به اشتراک Plus نیاز دارد؛ توضیح کاملش در کامپایل و اجرای واقعی آنلاین است. در شبیه‌ساز خطای آپلود هم پیش نمی‌آید چون کابل و پورتی در کار نیست؛ پس اول کد را آنجا درست کن و بعد سراغ برد واقعی برو.

برای مرور ساده‌تر، فهرست خطاهای رایج آردوینو به زبان ساده و تعریف کامپایل را هم ببین.

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

اگر کامپایل شد ولی کار نکرد

از اینجا به بعد کامپایلر دیگر کمکی نمی‌کند؛ اشکال در منطق یا سیم‌کشی است. فهرست کامل این حالت‌ها در کد آردوینو کار نمی‌کند؟ ۱۵ علت رایج آمده است. پروژه‌های آماده برای تمرین را هم در صفحه‌ی آردوینو پیدا می‌کنی.

برنامه را در تینکرکد فارسی کامپایل کن 🐞

سؤال‌های رایج

exit status 1 در آردوینو یعنی چه؟

یعنی کامپایل شکست خورد. خود این پیغام علت را نمی‌گوید؛ چند خط بالاتر را نگاه کن و اولین خطی را که کلمه‌ی error دارد بخوان.

چرا با کپی کردن کد از سایت یا تلگرام ارور stray می‌گیرم؟

در متن کپی‌شده نویسه‌های نامرئی یا فارسی مثل فاصله‌ی نشکن، نیم‌فاصله، سمی‌کالن فارسی یا گیومه‌ی کج آمده است. آن خط را پاک کن و با کیبورد انگلیسی دوباره تایپ کن.

ارور avrdude not in sync خطای کد من است؟

نه. کد کامپایل شده و مشکل در ارسال به برد است: پورت یا برد اشتباه، کابل فقط شارژ، درایور CH340 یا انتخاب Old Bootloader برای نانوهای کپی.

مقاله‌های مرتبط

📈

سریال مانیتور و نمودار سریال آردوینو در شبیه‌ساز آنلاین

🐞

دیباگ قدم‌به‌قدم کد آردوینو در شبیه‌ساز آنلاین: بریک‌پوینت و دیدن متغیرها

🔧

کد آردوینو کار نمی‌کند؟ ۱۵ علت رایج، از سیم‌کشی تا تغذیه، با راه‌حل هر کدام

🆚

آردوینو اونو، نانو یا مگا؟ مقایسه‌ی کامل و راهنمای انتخاب برد

همه‌ی آموزش‌های برنامه‌نویسی و عیب‌یابی آردوینو ← · همه‌ی مقاله‌ها