
آموزش گام به گام آردوینو بخش دوم: مبانی برنامهنویسی آردوینو (زبان C/C++)
در بخش اول، با مفاهیم پایه الکترونیک و راهاندازی آردوینو آشنا شدیم و اولین پروژه خود یعنی چشمک زدن LED را اجرا کردیم. حالا نوبت به یادگیری عمیقتر زبان برنامهنویسی آردوینو میرسد. این بخش، هسته اصلی برنامهنویسی را تشکیل میدهد و شما را با ساختارها و دستورات مهم کدنویسی آشنا میکند.
فهرست محتوای بخش دوم
- فصل ۱: ساختار زبان و توابع پایه
- فصل ۲: متغیرها و انواع داده
- فصل ۳: ساختارهای کنترلی
- فصل ۴: توابع پیشرفته و کتابخانهها
- پروژه عملی پایان بخش دوم
- خلاصه بخش دوم
فصل ۱: ساختار زبان و توابع پایه
۱.۱ آناتومی یک برنامه آردوینو (اسکچ)
همانطور که در بخش اول دیدیم، هر برنامه آردوینو از دو بخش اصلی تشکیل شده است. این ساختار الزامی است و بدون آن برنامه اجرا نمیشود:
|
1 2 3 4 5 6 7 8 9 10 |
void setup() { // این تابع فقط یک بار در ابتدای کار اجرا میشود // کارهای راهاندازی مانند تنظیم حالت پینها در اینجا انجام میشود } void loop() { // این تابع پس از setup بارها و بارها تکرار میشود // برنامه اصلی شما تا زمانی که برد خاموش شود در این حلقه میچرخد } |
۱.۲ توابع پایه کار با پینهای دیجیتال
برای کار با ورودی و خروجیهای دیجیتال، سه تابع اصلی داریم که باید مانند جدول ضرب آنها را حفظ کنید .
تابع pinMode(pin, mode)
این تابع برای تنظیم حالت پینها استفاده میشود و معمولاً در تابع setup قرار میگیرد .
- پارامتر اول (pin): شماره پین مورد نظر (مثلاً ۱۳ برای پین دیجیتال ۱۳)
- پارامتر دوم (mode): حالتی که برای پین تعریف میکنیم:
OUTPUT: برای خروجی (مثل LED)INPUT: برای ورودی (مثل دکمه)INPUT_PULLUP: ورودی با مقاومت داخلی pull-up
|
1 2 3 |
pinMode(13, OUTPUT); // پین ۱۳ به عنوان خروجی pinMode(2, INPUT); // پین ۲ به عنوان ورودی |
این تابع برای تنظیم ولتاژ خروجی پینهایی که به عنوان OUTPUT تعریف شدهاند استفاده میشود .
- پارامتر اول (pin): شماره پین مورد نظر
- پارامتر دوم (value): مقدار ولتاژ خروجی:
HIGH: ولتاژ بالا (۵ ولت در آردوینو Uno)LOW: ولتاژ پایین (۰ ولت)
|
1 2 3 |
digitalWrite(13, HIGH); // پین ۱۳ را روشن (۵ ولت) کن digitalWrite(13, LOW); // پین ۱۳ را خاموش (۰ ولت) کن |
این تابع برای خواندن وضعیت یک پین ورودی استفاده میشود و مقدار HIGH یا LOW را برمیگرداند .
- پارامتر ورودی: شماره پین مورد نظر
- خروجی:
HIGH(۵ ولت) یاLOW(۰ ولت)
|
1 2 |
int buttonState = digitalRead(2); // وضعیت پین ۲ را میخواند |
۱.۳ تابع delay
این تابع برنامه را به مدت مشخصی (به میلیثانیه) متوقف میکند. ۱۰۰۰ میلیثانیه = ۱ ثانیه.
|
1 2 3 |
delay(1000); // یک ثانیه توقف delay(250); // یکچهارم ثانیه توقف |
فصل ۲: متغیرها و انواع داده
متغیرها مکانهایی در حافظه هستند که دادهها را ذخیره میکنند. در آردوینو، قبل از استفاده از هر متغیر باید نوع آن را مشخص کنیم.
۲.۱ انواع داده اصلی
| نوع داده | اندازه | محدوده مقادیر | کاربرد |
|---|---|---|---|
int |
۲ بایت | ۳۲۷۶۷- تا ۳۲۷۶۷ | اعداد صحیح (مثل شماره پینها) |
float |
۴ بایت | ۳.۴-۱۰ × ۳.۴۸- تا ۳.۴-۱۰ × ۳.۴۸ | اعداد اعشاری (مثل دما) |
boolean |
۱ بایت | true یا false | وضعیتهای روشن/خاموش |
char |
۱ بایت | ۱۲۸- تا ۱۲۷ | کاراکترها (حروف) |
byte |
۱ بایت | ۰ تا ۲۵۵ | اعداد کوچک مثبت |
long |
۴ بایت | ۲,۱۴۷,۴۸۳,۶۴۷- تا ۲,۱۴۷,۴۸۳,۶۴۷ | اعداد صحیح بزرگ |
unsigned int |
۲ بایت | ۰ تا ۶۵,۵۳۵ | اعداد مثبت (مثل زمان) |
|
1 2 3 4 5 6 |
int ledPin = 13; // عدد صحیح float temperature = 23.5; // عدد اعشاری boolean ledState = true; // درست یا غلط char initial = 'A'; // کاراکتر byte smallNumber = 100; // بایت |
۲.۲ حوزه عملکرد متغیرها (Scope)
متغیرها دو نوع حوزه عملکرد دارند:
متغیرهای سراسری (Global): خارج از توابع تعریف میشوند و در همه جای برنامه قابل استفاده هستند.
متغیرهای محلی (Local): داخل یک تابع تعریف میشوند و فقط در همان تابع قابل استفاده هستند.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int globalVar = 10; // متغیر سراسری - همه جا قابل استفاده است void setup() { int localVar = 5; // متغیر محلی - فقط در setup قابل استفاده است Serial.begin(9600); Serial.println(globalVar); // ✅ درست کار میکند Serial.println(localVar); // ✅ درست کار میکند } void loop() { Serial.println(globalVar); // ✅ درست کار میکند // Serial.println(localVar); // ❌ خطا! localVar اینجا تعریف نشده } |
۲.۳ آشنایی با آرایهها
آرایه مجموعهای از متغیرها با یک نام و نوع یکسان است. برای دسترسی به هر عضو از اندیس (شماره) استفاده میکنیم که از ۰ شروع میشود .
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// تعریف آرایهای از شماره پینها int ledPins[] = {8, 9, 10, 11, 12}; // دسترسی به اعضا ledPins[0] = 8; // اولین عضو ledPins[4] = 12; // پنجمین عضو // استفاده از آرایه در حلقه for (int i = 0; i < 5; i++) { pinMode(ledPins[i], OUTPUT); // تنظیم همه پینها به عنوان خروجی } |
فصل ۳: ساختارهای کنترلی
ساختارهای کنترلی به ما اجازه میدهند جریان اجرای برنامه را کنترل کنیم.
۳.۱ ساختار شرطی if…else
از این ساختار برای تصمیمگیری بر اساس شرایط استفاده میکنیم.
|
1 2 3 4 5 6 |
if (شرط) { // اگر شرط درست بود، اینجا اجرا میشود } else { // اگر شرط نادرست بود، اینجا اجرا میشود } |
مثال عملی: کنترل LED با دکمه
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const int buttonPin = 2; const int ledPin = 13; int buttonState = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT); } void loop() { buttonState = digitalRead(buttonPin); // خواندن وضعیت دکمه if (buttonState == HIGH) { // اگر دکمه فشار داده شده باشد digitalWrite(ledPin, HIGH); // LED روشن شود } else { // در غیر این صورت digitalWrite(ledPin, LOW); // LED خاموش شود } } |
۳.۲ ساختار switch…case
وقتی چندین حالت مختلف داریم، به جای if…elseهای متعدد از switch استفاده میکنیم.
|
1 2 3 4 5 6 7 8 9 10 11 |
switch (متغیر) { case مقدار۱: // اگر متغیر برابر مقدار۱ بود break; case مقدار۲: // اگر متغیر برابر مقدار۲ بود break; default: // اگر هیچکدام از حالات بالا نبود } |
مثال: کنترل LEDهای مختلف با یک دکمه
|
1 2 3 4 5 6 7 8 9 10 11 |
int buttonState = digitalRead(2); switch (buttonState) { case 1: // اگر دکمه فشار داده شد digitalWrite(13, HIGH); break; case 0: // اگر دکمه رها شد digitalWrite(13, LOW); break; } |
۳.۳ حلقه for
از حلقه for برای تکرار یک بلوک کد به تعداد مشخص استفاده میکنیم .
|
1 2 3 4 |
for (شروع; شرط; گام) { // کدی که تکرار میشود } |
مثال: روشن کردن ۵ LED به صورت متوالی
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int ledPins[] = {8, 9, 10, 11, 12}; void setup() { for (int i = 0; i < 5; i++) { pinMode(ledPins[i], OUTPUT); // تنظیم همه پینها } } void loop() { for (int i = 0; i < 5; i++) { digitalWrite(ledPins[i], HIGH); // LED جاری روشن delay(200); // ۲۰۰ میلیثانیه صبر digitalWrite(ledPins[i], LOW); // LED جاری خاموش } } |
۳.۴ حلقه while
حلقه while تا زمانی که شرط برقرار است، تکرار میشود.
|
1 2 3 4 |
while (شرط) { // کدی که تا برقراری شرط تکرار میشود } |
مثال: منتظر ماندن تا فشار دادن دکمه
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
int buttonState = 0; void setup() { pinMode(2, INPUT); pinMode(13, OUTPUT); } void loop() { buttonState = digitalRead(2); while (buttonState == HIGH) { // تا وقتی دکمه فشار داده شده digitalWrite(13, HIGH); // LED روشن بماند buttonState = digitalRead(2); // دوباره بخوان } digitalWrite(13, LOW); // وقتی دکمه رها شد، LED خاموش شود } |
فصل ۴: توابع پیشرفته و کتابخانهها
۴.۱ نوشتن توابع شخصیسازی شده
گاهی نیاز داریم یک بلوک کد را چند بار در جاهای مختلف برنامه استفاده کنیم. به جای تکرار کد، یک تابع مینویسیم .
ساختار تابع:
|
1 2 3 4 5 |
نوع_خروجی نام_تابع(پارامترها) { // بدنه تابع return مقدار_خروجی; // اگر نوع خروجی void نباشد } |
مثال ۱: تابع بدون خروجی
|
1 2 3 4 5 6 7 8 9 10 11 12 |
void blinkLED(int pin, int duration) { digitalWrite(pin, HIGH); delay(duration); digitalWrite(pin, LOW); delay(duration); } void loop() { blinkLED(13, 500); // چشمک زدن با تأخیر ۵۰۰ میلیثانیه blinkLED(12, 200); // چشمک زدن سریعتر روی پین ۱۲ } |
مثال ۲: تابع با خروجی
|
1 2 3 4 5 6 7 8 9 10 |
int calculateAverage(int a, int b) { int result = (a + b) / 2; return result; // برگرداندن نتیجه } void loop() { int avg = calculateAverage(10, 20); // avg = 15 Serial.println(avg); } |
۴.۲ مفهوم کتابخانهها (Libraries)
کتابخانهها مجموعهای از توابع آماده هستند که کار با قطعات خاص را آسان میکنند. به جای نوشتن کدهای پیچیده برای راهاندازی یک سنسور، کتابخانه مربوطه را فراخوانی میکنیم .
نحوه وارد کردن کتابخانه:
|
1 2 |
#include <نام_کتابخانه.h> |
مثال: استفاده از کتابخانه Servo برای کنترل موتور سروو
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <Servo.h> // وارد کردن کتابخانه Servo myServo; // ایجاد یک شیء از نوع Servo void setup() { myServo.attach(9); // اتصال سروو به پین ۹ } void loop() { myServo.write(90); // چرخاندن سروو به ۹۰ درجه delay(1000); myServo.write(0); // چرخاندن سروو به ۰ درجه delay(1000); } |
نصب کتابخانههای جدید:
- از منوی Sketch → Include Library → Manage Libraries
- در پنجره باز شده، نام کتابخانه مورد نظر را جستجو کنید
- روی Install کلیک کنید
پروژه عملی پایان بخش دوم: چراغ راهنمایی هوشمند
حالا وقت آن رسیده که همه مفاهیم یاد گرفته شده را در یک پروژه عملی ترکیب کنیم.
هدف پروژه: ساخت یک چراغ راهنمایی که با دکمه کنترل میشود. با هر بار فشردن دکمه، سیکل چراغها تغییر کند.
قطعات مورد نیاز:
- برد آردوینو Uno
- ۳ عدد LED (قرمز، زرد، سبز)
- ۳ عدد مقاومت ۲۲۰ اهم
- ۱ عدد پوشباتن (دکمه فشاری)
- ۱ عدد مقاومت ۱۰ کیلو اهم (برای pull-down)
- برد بورد و سیم جامپر
نحوه بستن مدار:
- LED قرمز: پین ۸ ← مقاومت ۲۲۰Ω ← آند LED (پایه بلند) ← کاتد LED (پایه کوتاه) ← GND
- LED زرد: پین ۹ ← مقاومت ۲۲۰Ω ← آند LED ← کاتد LED ← GND
- LED سبز: پین ۱۰ ← مقاومت ۲۲۰Ω ← آند LED ← کاتد LED ← GND
- دکمه: یک پایه به ۵ ولت، پایه دیگر به پین ۲ و از همان پایه یک مقاومت ۱۰k به GND (پیکربندی pull-down)
کد پروژه:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
// تعریف ثابتها const int redPin = 8; const int yellowPin = 9; const int greenPin = 10; const int buttonPin = 2; // متغیرها int buttonState = 0; int lastButtonState = 0; int mode = 0; // حالت فعلی چراغ راهنمایی unsigned long lastDebounceTime = 0; const unsigned long debounceDelay = 50; // تأخیر رفع نویز // آرایهای از پینهای LED int ledPins[] = {redPin, yellowPin, greenPin}; // تابع شخصیسازی شده برای خاموش کردن همه LEDها void allLedsOff() { for (int i = 0; i < 3; i++) { digitalWrite(ledPins[i], LOW); } } // تابع شخصیسازی شده برای تنظیم حالت چراغ void setTrafficLight(int redState, int yellowState, int greenState) { digitalWrite(redPin, redState); digitalWrite(yellowPin, yellowState); digitalWrite(greenPin, greenState); } void setup() { // تنظیم پینهای LED به عنوان خروجی for (int i = 0; i < 3; i++) { pinMode(ledPins[i], OUTPUT); } // تنظیم پین دکمه به عنوان ورودی pinMode(buttonPin, INPUT); // راهاندازی ارتباط سریال برای دیباگ Serial.begin(9600); // حالت اولیه: همه خاموش allLedsOff(); } void loop() { // خواندن وضعیت دکمه با رفع نویز (debounce) int reading = digitalRead(buttonPin); // اگر وضعیت تغییر کرده، تایمر را ریست کن if (reading != lastButtonState) { lastDebounceTime = millis(); } // اگر به اندازه کافی از آخرین تغییر گذشته، وضعیت را بپذیر if ((millis() - lastDebounceTime) > debounceDelay) { // اگر وضعیت واقعاً تغییر کرده if (reading != buttonState) { buttonState = reading; // اگر دکمه فشار داده شده (HIGH) if (buttonState == HIGH) { // تغییر حالت mode++; if (mode > 3) { mode = 0; // برگشت به حالت اول } Serial.print("Mode changed to: "); Serial.println(mode); } } } lastButtonState = reading; // اجرای حالتهای مختلف بر اساس mode switch (mode) { case 0: // حالت عادی چراغ راهنمایی setTrafficLight(HIGH, LOW, LOW); // فقط قرمز delay(3000); setTrafficLight(HIGH, HIGH, LOW); // قرمز و زرد delay(1000); setTrafficLight(LOW, LOW, HIGH); // فقط سبز delay(3000); setTrafficLight(LOW, HIGH, LOW); // فقط زرد delay(1000); break; case 1: // حالت چشمک زن (اخطار) for (int i = 0; i < 5; i++) { setTrafficLight(HIGH, HIGH, HIGH); // همه روشن delay(500); allLedsOff(); // همه خاموش delay(500); } mode = 0; // برگشت به حالت عادی break; case 2: // حالت شب (فقط زرد چشمک میزند) for (int i = 0; i < 10; i++) { digitalWrite(yellowPin, HIGH); delay(200); digitalWrite(yellowPin, LOW); delay(200); } mode = 0; // برگشت به حالت عادی break; case 3: // حالت عابر پیاده (همه قرمز) setTrafficLight(HIGH, LOW, LOW); // فقط قرمز delay(5000); // ۵ ثانیه برای عبور عابر mode = 0; // برگشت به حالت عادی break; } } |
توضیح کد:
- رفع نویز (Debounce): دکمههای مکانیکی هنگام فشار دادن نوساناتی ایجاد میکنند. با استفاده از تکنیک debounce، این نوسانات را فیلتر میکنیم .
- تابع شخصیسازی شده:
allLedsOffوsetTrafficLightتوابعی هستند که نوشتهایم تا کد خواناتر شود. - آرایه: از آرایه
ledPinsبرای مدیریت آسانتر پینها استفاده کردهایم. - ساختار switch: برای مدیریت حالتهای مختلف چراغ راهنمایی از
switchاستفاده شده است. - حلقه for: در حالتهای چشمک زن از حلقه
forبرای تکرار استفاده کردهایم.
خلاصه بخش دوم
در این بخش یاد گرفتیم:
- ساختار یک برنامه آردوینو شامل
setupوloopرا بشناسیم . - با توابع پایه
pinMode،digitalWriteوdigitalReadکار کنیم . - انواع داده مختلف مثل
int،float،booleanوcharرا بشناسیم و استفاده کنیم. - مفهوم متغیرهای سراسری و محلی را درک کنیم.
- با آرایهها برای ذخیره مجموعهای از دادهها آشنا شویم .
- از ساختارهای شرطی
if...elseوswitch...caseبرای تصمیمگیری استفاده کنیم . - با حلقههای تکرار
forوwhileبرنامه را کنترل کنیم . - توابع شخصیسازی شده بنویسیم تا کد ما خواناتر و قابل استفاده مجدد باشد.
- با مفهوم کتابخانهها و نحوه استفاده از آنها آشنا شویم .
- یک پروژه عملی چراغ راهنمایی هوشمند با همه مفاهیم یاد گرفته شده پیادهسازی کنیم.
در بخش سوم، به سراغ کار با ورودی و خروجیهای دیجیتال به صورت پیشرفتهتر میرویم و با مفاهیم جدیدی مثل PWM و سنسورهای دیجیتال آشنا خواهیم شد.






