آموزش آردوینو

آموزش عملگرها در آردوینو (ریاضی، مقایسه ای و منطقی)

در این مستند با عملگرهای پرکاربرد در برنامه نویسی آردوینو آشنا می شوید. عملگرهای ریاضی برای محاسبات، عملگرهای مقایسه ای برای مقایسه مقادیر و عملگرهای منطقی برای ترکیب شرط ها استفاده می شوند. با مثال های عملی، نحوه استفاده از عملگرهایی مانند +، -، *، /، %، ==، !=، >، <، &&، || و ! را یاد می گیرید و با اشتباهات رایج در استفاده از آنها آشنا خواهید شد.

سطح مقدماتی

آموزش عملگرها در آردوینو (ریاضی، مقایسه ای و منطقی)

مقدمه

در برنامه نویسی آردوینو، برای انجام محاسبات، مقایسه مقادیر و تصمیم گیری درباره اجرای دستورها از عملگرها (Operators) استفاده می کنیم.

برای مثال، ممکن است بخواهیم:

  • مجموع دو عدد را محاسبه کنیم.
  • بررسی کنیم که دمای سنسور از یک مقدار مشخص بیشتر شده است یا نه.
  • تشخیص دهیم که یک کلید فشرده شده است.
  • بررسی کنیم که چند شرط به صورت هم زمان برقرار هستند.
  • در صورت برقرار بودن یک شرط، موتور یا LED را روشن کنیم.

عملگرها به ما اجازه می دهند چنین منطق هایی را در برنامه پیاده سازی کنیم.

در این آموزش، سه گروه اصلی عملگرها را بررسی می کنیم:

  1. عملگرهای ریاضی
  2. عملگرهای مقایسه ای
  3. عملگرهای منطقی

۱. عملگرهای ریاضی (Arithmetic Operators)

عملگرهای ریاضی برای انجام محاسبات عددی استفاده می شوند.

عملگرکاربردمثالنتیجه
+جمع5 + 38
-تفریق5 - 32
*ضرب5 * 315
/تقسیم6 / 32
%باقی مانده تقسیم7 % 31

مثال جمع و تفریق

int a = 10;
int b = 3;

int sum = a + b;
int difference = a - b;

در این مثال:

  • مقدار sum برابر ۱۳ است.
  • مقدار difference برابر ۷ است.

مثال ضرب

int width = 5;
int height = 4;

int area = width * height;

در این برنامه، مقدار area برابر ۲۰ خواهد بود.

مثال تقسیم

int a = 7;
int b = 2;

int result = a / b;

از آنجا که هر دو متغیر از نوع int هستند، نتیجه تقسیم صحیح خواهد بود و مقدار result برابر ۳ می شود؛ بخش اعشاری حذف می شود.

اگر به نتیجه اعشاری نیاز داشته باشیم، باید از نوع داده مناسب استفاده کنیم:

float a = 7.0;
float b = 2.0;

float result = a / b;

در این حالت، نتیجه تقریبا برابر ۳٫۵ خواهد بود.

نکته مهم: اگر هر دو عملوند تقسیم از نوع صحیح باشند، نتیجه تقسیم نیز معمولا صحیح خواهد بود؛ حتی اگر آن را در یک متغیر float ذخیره کنیم.

برای مثال:

float result = 7 / 2;

نتیجه این عبارت ۳٫۰ خواهد بود، نه ۳٫۵؛ زیرا تقسیم صحیح پیش از ذخیره نتیجه انجام شده است.

شکل صحیح برای دریافت نتیجه اعشاری:

float result = 7.0 / 2;

عملگر باقی مانده تقسیم (%)

عملگر % باقی مانده تقسیم صحیح را برمی گرداند.

int result = 10 % 3;

مقدار result برابر ۱ است؛ زیرا با تقسیم ۱۰ بر ۳، باقی مانده برابر ۱ خواهد بود.

این عملگر برای کارهایی مانند تشخیص زوج یا فرد بودن عدد کاربرد دارد:

int number = 8;

if (number % 2 == 0) {
  // عدد زوج است
}

اگر باقی مانده تقسیم عدد بر ۲ صفر باشد، عدد زوج است.

توجه: عملگر % برای محاسبات معمول با اعداد صحیح استفاده می شود و نباید آن را مانند عملگر باقی مانده در همه زبان ها و برای همه انواع عددی در نظر گرفت.

۲. عملگرهای افزایش و کاهش

در آردوینو می توان مقدار یک متغیر را یک واحد افزایش یا کاهش داد.

عملگرکاربرد
++افزایش مقدار به اندازه یک
--کاهش مقدار به اندازه یک

افزایش مقدار

int counter = 5;

counter++;

پس از اجرای دستور، مقدار counter برابر ۶ خواهد بود.

این دستور معادل زیر است:

counter = counter + 1;

کاهش مقدار

int counter = 5;

counter--;

پس از اجرای دستور، مقدار counter برابر ۴ خواهد بود.

تفاوت پیشوند و پسوند

دو شکل برای افزایش و کاهش وجود دارد:

int a = 5;

int x = ++a;

در این حالت، ابتدا a افزایش پیدا می کند و سپس مقدار آن در x قرار می گیرد. بنابراین هر دو متغیر برابر ۶ می شوند.

اما در مثال زیر:

int a = 5;

int x = a++;

ابتدا مقدار فعلی a در x قرار می گیرد و سپس a افزایش پیدا می کند. در پایان، x برابر ۵ و a برابر ۶ است.

برای شروع یادگیری، بهتر است افزایش یا کاهش متغیرها را در دستورهای جداگانه بنویسید تا ترتیب اجرای برنامه روشن تر باشد.

۳. عملگرهای انتساب

عملگر انتساب مقدار سمت راست را در متغیر سمت چپ قرار می دهد.

عملگر اصلی انتساب = است.

int value = 10;

این دستور مقدار ۱۰ را در متغیر value ذخیره می کند.

نباید عملگر انتساب را با عملگر مقایسه برابری اشتباه بگیریم:

  • = برای انتساب مقدار استفاده می شود.
  • == برای بررسی برابر بودن دو مقدار به کار می رود.

چند عملگر انتساب ترکیبی نیز وجود دارد:

عملگرمعادل
+=a = a + value
-=a = a - value
*=a = a * value
/=a = a / value
%=a = a % value

مثال:

int score = 10;

score += 5;
score -= 2;

پس از اجرای این دستورها، مقدار score برابر ۱۳ خواهد بود.

۴. عملگرهای مقایسه ای (Comparison Operators)

عملگرهای مقایسه ای برای مقایسه دو مقدار استفاده می شوند.

نتیجه این مقایسه ها یک مقدار منطقی است که در زبان C++ به صورت true یا false بیان می شود.

عملگرمعنیمثالنتیجه
==برابر است با5 == 5true
!=برابر نیست با5 != 3true
>بزرگ تر از7 > 3true
<کوچک تر از2 < 4true
>=بزرگ تر یا مساوی5 >= 5true
<=کوچک تر یا مساوی3 <= 5true

مثال مقایسه دو عدد

int temperature = 30;

if (temperature > 25) {
  // دما بیشتر از ۲۵ است
}

در این مثال، چون مقدار temperature برابر ۳۰ است، شرط برقرار خواهد بود.

مثال بررسی برابری

int number = 10;

if (number == 10) {
  // مقدار number برابر ۱۰ است
}

مثال بررسی نابرابری

int sensorValue = 500;

if (sensorValue != 0) {
  // مقدار سنسور صفر نیست
}

عملگرهای مقایسه ای معمولا در دستورهای شرطی مانند if و while استفاده می شوند.

۵. اشتباه رایج: تفاوت = و ==

یکی از خطاهای رایج در برنامه نویسی، اشتباه گرفتن عملگر انتساب = با عملگر مقایسه == است.

مثال:

int number = 5;

if (number = 10) {
  // این شرط به شکل مورد انتظار عدد را مقایسه نمی کند
}

در این کد، عبارت number = 10 مقدار ۱۰ را در متغیر قرار می دهد. چون مقدار حاصل غیرصفر است، شرط نیز درست ارزیابی می شود.

شکل صحیح:

int number = 5;

if (number == 10) {
  // فقط اگر number برابر ۱۰ باشد اجرا می شود
}

به خاطر داشته باشید:

یک علامت مساوی برای انتساب و دو علامت مساوی برای مقایسه هستند.

۶. عملگرهای منطقی (Logical Operators)

عملگرهای منطقی برای ترکیب شرط ها یا معکوس کردن نتیجه یک شرط استفاده می شوند.

سه عملگر اصلی عبارت اند از:

عملگرنامکاربرد
&&ANDدرست بودن هم زمان هر دو شرط
``
!NOTمعکوس کردن نتیجه منطقی

عملگر AND (&&)

عملگر && زمانی نتیجه درست می دهد که هر دو شرط درست باشند.

int temperature = 30;
int humidity = 40;

if (temperature > 25 && humidity < 50) {
  // هر دو شرط برقرار هستند
}

در این مثال، دما بیشتر از ۲۵ و رطوبت کمتر از ۵۰ است؛ بنابراین هر دو شرط برقرارند.

اگر یکی از شرط ها نادرست باشد، نتیجه کل عبارت نادرست خواهد بود.

عملگر OR (||)

عملگر || زمانی درست است که حداقل یکی از دو شرط درست باشد.

int temperature = 35;

if (temperature > 40 || temperature < 0) {
  // دما بالاتر از ۴۰ یا پایین تر از صفر است
}

در این مثال، چون دما ۳۵ است، هیچ کدام از شرط ها برقرار نیستند و بدنه if اجرا نمی شود.

عملگر NOT (!)

عملگر ! نتیجه منطقی یک عبارت را معکوس می کند.

bool doorOpen = false;

if (!doorOpen) {
  // در باز نیست
}

چون doorOpen برابر false است، عبارت !doorOpen درست خواهد بود.

۷. جدول درستی عملگرهای منطقی

در جدول زیر، true به معنی درست و false به معنی نادرست است.

ABA && BAB
falsefalsefalsefalse
falsetruefalsetrue
truefalsefalsetrue
truetruetruetrue

عملگر ! فقط یک مقدار منطقی را دریافت می کند:

A!A
falsetrue
truefalse

۸. ترکیب عملگرها در پروژه های آردوینو

در پروژه های واقعی، معمولا چند نوع عملگر را با هم استفاده می کنیم.

فرض کنید یک سنسور مقدار آنالوگ را از پایه A0 می خواند و می خواهیم وقتی مقدار سنسور از ۶۰۰ بیشتر شد، LED روشن شود.

const int sensorPin = A0;
const int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);

  if (sensorValue > 600) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

  Serial.println(sensorValue);

  delay(100);
}

در این برنامه، عملگر > مقدار سنسور را با عدد ۶۰۰ مقایسه می کند.

اگر مقدار سنسور بیشتر از ۶۰۰ باشد، LED روشن می شود؛ در غیر این صورت، LED خاموش خواهد شد.

۹. استفاده از چند شرط هم زمان

فرض کنید می خواهیم LED فقط زمانی روشن شود که مقدار سنسور در یک محدوده مشخص قرار داشته باشد.

const int sensorPin = A0;
const int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);

  if (sensorValue >= 300 && sensorValue <= 700) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

  Serial.println(sensorValue);

  delay(100);
}

در این مثال، LED فقط زمانی روشن می شود که مقدار سنسور بین ۳۰۰ و ۷۰۰، با احتساب خود این دو عدد، باشد.

عملگر && تضمین می کند که هر دو شرط باید برقرار باشند.

۱۰. ترکیب AND و OR

گاهی لازم است شرط های پیچیده تری بنویسیم.

فرض کنید می خواهیم در صورتی که دما بیشتر از ۳۵ درجه باشد یا مقدار سنسور کمتر از ۱۰۰ باشد، هشدار فعال شود.

if (temperature > 35 || sensorValue < 100) {
  // فعال کردن هشدار
}

در این مثال، برقرار بودن یکی از دو شرط کافی است.

اگر ترکیبی از && و || در یک عبارت استفاده شود، بهتر است برای مشخص کردن ترتیب مورد نظر از پرانتز استفاده کنیم.

if ((temperature > 35 && humidity > 70) || sensorValue < 100) {
  // یکی از دو حالت زیر کافی است:
  // دمای بالا همراه با رطوبت بالا
  // یا مقدار بسیار پایین سنسور
}

پرانتزها خوانایی برنامه را افزایش می دهند و مشخص می کنند کدام شرط ها باید با هم بررسی شوند.

۱۱. ترتیب انجام عملگرها

وقتی چند عملگر در یک عبارت قرار دارند، زبان C++ بر اساس قواعد تقدم عملگرها آنها را ارزیابی می کند.

برای مثال:

int result = 2 + 3 * 4;

نتیجه برابر ۱۴ است؛ زیرا ضرب پیش از جمع انجام می شود.

اما در عبارت زیر:

int result = (2 + 3) * 4;

ابتدا عبارت داخل پرانتز محاسبه می شود و نتیجه برابر ۲۰ خواهد بود.

برای جلوگیری از ابهام، در عبارت های پیچیده از پرانتز استفاده کنید؛ حتی اگر ترتیب انجام عملیات از نظر زبان برنامه نویسی مشخص باشد.

۱۲. نکات مهم درباره تقسیم و مقایسه اعداد اعشاری

تقسیم بر صفر

تقسیم عدد صحیح بر صفر نتیجه معتبر ندارد و می تواند باعث رفتار نامشخص برنامه شود.

بنابراین پیش از تقسیم، صفر نبودن مقسوم علیه را بررسی کنید:

int numerator = 10;
int denominator = 0;

if (denominator != 0) {
  int result = numerator / denominator;
}

در این مثال، چون denominator صفر است، عملیات تقسیم انجام نمی شود.

مقایسه اعداد اعشاری

اعداد نوع float به دلیل نحوه نمایش در حافظه ممکن است با خطای گرد کردن همراه باشند. بنابراین مقایسه مستقیم دو عدد اعشاری با == همیشه بهترین روش نیست.

برای مثال، به جای مقایسه مستقیم دو مقدار اعشاری، در بعضی کاربردها می توان اختلاف آنها را با یک محدوده مجاز مقایسه کرد:

float a = 0.1 + 0.2;
float b = 0.3;

if (abs(a - b) < 0.001) {
  // دو مقدار از نظر کاربردی به هم نزدیک هستند
}

محدوده 0.001 در این مثال صرفا یک مقدار نمونه است و باید با توجه به دقت مورد نیاز پروژه انتخاب شود.

۱۳. نکته مهم درباره عملگرهای منطقی و اتصال شرط ها

در C++، عملگرهای && و || از ارزیابی کوتاه شده یا Short-circuit Evaluation پشتیبانی می کنند.

یعنی ممکن است بخش دوم عبارت فقط زمانی ارزیابی شود که برای تعیین نتیجه نهایی لازم باشد.

برای مثال:

if (denominator != 0 && numerator / denominator > 2) {
  // اجرای دستورها
}

اگر denominator برابر صفر باشد، بخش دوم عبارت ارزیابی نمی شود. این روش در چنین مثال هایی از انجام تقسیم نامعتبر جلوگیری می کند.

در مقابل، از عملگرهای & و | نباید به جای && و || استفاده کرد؛ زیرا آنها عملگرهای متفاوتی هستند و رفتارشان در همه شرایط یکسان نیست.

۱۴. اشتباهات رایج در استفاده از عملگرها

اشتباه اول: اشتباه گرفتن = و ==

if (value = 5) {
}

اگر هدف مقایسه است، باید از == استفاده شود.

اشتباه دوم: استفاده از & به جای &&

if (temperature > 25 && humidity < 60) {
}

برای ترکیب منطقی شرط ها از && استفاده کنید.

اشتباه سوم: فراموش کردن نوع داده

int result = 7 / 2;

نتیجه این عبارت ۳ است، نه ۳٫۵.

برای محاسبه اعشاری از عملوند اعشاری استفاده کنید:

float result = 7.0 / 2;

اشتباه چهارم: تقسیم بر صفر

پیش از تقسیم، مقدار مقسوم علیه را بررسی کنید.

اشتباه پنجم: نوشتن شرط های مبهم

به جای نوشتن یک عبارت طولانی و دشوار، شرط ها را با پرانتز و قالب بندی مناسب بنویسید.

۱۵. تمرین عملی

در این تمرین، یک پتانسیومتر به پایه A0 و یک LED به پایه PWM شماره ۹ متصل می شود.

هدف این است که:

  • مقدار پتانسیومتر خوانده شود.
  • اگر مقدار کمتر از ۳۰۰ بود، LED خاموش شود.
  • اگر مقدار بین ۳۰۰ تا ۷۰۰ بود، LED با روشنایی متوسط روشن شود.
  • اگر مقدار بیشتر از ۷۰۰ بود، LED با روشنایی زیاد روشن شود.

کد زیر را اجرا کنید:

const int sensorPin = A0;
const int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);

  if (sensorValue < 300) {
    analogWrite(ledPin, 0);
  }
  else if (sensorValue >= 300 && sensorValue <= 700) {
    analogWrite(ledPin, 100);
  }
  else {
    analogWrite(ledPin, 255);
  }

  Serial.print("Sensor: ");
  Serial.println(sensorValue);

  delay(100);
}

در این تمرین، عملگرهای <، >=، <= و && را به صورت عملی به کار می برید.

به یاد داشته باشید که در Arduino Uno کلاسیک، analogWrite() روی پایه های PWM مقدار معمولی بین ۰ تا ۲۵۵ دریافت می کند و خروجی PWM تولید می کند.

جمع بندی

عملگرها یکی از پایه های اصلی برنامه نویسی آردوینو هستند:

  • عملگرهای ریاضی برای محاسبات عددی استفاده می شوند.
  • عملگرهای مقایسه ای برای بررسی رابطه بین دو مقدار کاربرد دارند.
  • عملگرهای منطقی برای ترکیب شرط ها و ساخت تصمیم های پیچیده تر استفاده می شوند.
  • عملگرهای انتساب و افزایش و کاهش نیز تغییر مقدار متغیرها را ساده می کنند.

با تسلط بر این عملگرها می توانید برنامه هایی بنویسید که بر اساس مقادیر سنسورها، وضعیت کلیدها و شرایط مختلف، رفتار مناسبی از خود نشان دهند.

نمونه کد :

const int sensorPin = A0;
const int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);

  if (sensorValue < 300) {
    analogWrite(ledPin, 0);
  }
  else if (sensorValue >= 300 && sensorValue <= 700) {
    analogWrite(ledPin, 100);
  }
  else {
    analogWrite(ledPin, 255);
  }

  Serial.println(sensorValue);
  delay(100);
}