متغیرها و انواع داده در آردوینو
متغیر و ثابت در زبان C++ آردوینو؛ انواع int و byte و long و float و bool، انتخاب میان const و define، سرریز عدد و یک اسکچ شمارنده با خروجی سریال مانیتور.
آنچه در این درس میآموزید
- متغیر را با نام و نوع درست تعریف کنید و قواعد نامگذاری را رعایت کنید
- نوع دادهٔ مناسب هر مقدار را از میان int و byte و long و float و bool انتخاب کنید
- ثابت را با const تعریف کنید و بدانید چرا از
- سرریز int روی Uno را توضیح دهید و در کدتان از آن پیشگیری کنید
فهرست مطالب
تا حالا در اسکچها فقط اعداد ثابت دیدید: پین ۸، تأخیر ۱۰۰۰. برنامهٔ واقعی اطلاعاتی دارد که تغییر میکنند — شمارنده، زمان، نتیجهٔ خواندن یک سنسور. در این درس «متغیر» (Variable) را یاد میگیرید؛ خانهای نامدار در حافظهٔ میکروکنترلر که مقداری از یک نوع مشخص نگه میدارد. آردوینو با زبان C++ برنامهنویسی میشود و انواع دادهٔ آن دقت و محدودهٔ متفاوتی دارند؛ انتخاب اشتباه نوع، رایجترین علت مقادیر عجیب در برنامههای مبتدیان است.
تعریف متغیر و قواعد نامگذاری
یک متغیر با سه چیز ساخته میشود: نوع، نام و مقدار اولیه:
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) کنید تا کامپایلر از تغییر تصادفیاش جلوگیری کند:
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 که در کد نوشتهاید انتخاب کنید:
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);
}توضیح نکتههای تازه:
count = count + 1;— مقدار فعلیcountخوانده میشود، یکی اضافه میشود و نتیجه دوباره در همان متغیر ذخیره میشود. میانبر رایج همین خطcount++;است.Serial.begin(9600);— ارتباط سریال را با نرخ ۹۶۰۰ بیت بر ثانیه راه میاندازد؛ فقط یک بار درsetup().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) همین حالا هم خواناست:
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تعریف کنید؛ نوعدار و محدود به همان بخش از کد است و خطاها را خواناتر نشان میدهد. - نام متغیر با رقم شروع نمیشود، بزرگی و کوچکی حروف مهم است و نام باید معنا داشته باشد.
حالا میتوانید داده نگه دارید؛ گام بعدی تصمیمگرفتن است: اگر عددی بیشتر از چیزی بود چه؟ در درس بعدی با شرطها و حلقهها برنامهها را هوشمند میکنید.