آموزش آردوینو، پروژهی سوم:
باباطاهرعریان خیلی سال پیش فرموده: چه خوش بی، مهربونی هر دو سر بی / که یک سر مهربونی دردسر بی
با توجه به بیت بعدیِ این دوبیتی، ما حدس میزنیم که باباطاهر توی حال خیلی خوبی بوده! اما امکان نداره ایشون هیچ تصور میکرده که ما امروز، موقع آموزش آردوینو این دوبیتی به کارمون بیاد! تا اینجا ارتباط ما یک سر بی! یعنی فقط با LED ها میتونستیم اطلاعاتی رو از وضعیت خروجیها بهدست بیاریم. ورودیها رو هم باز از خود بورد میگرفتیم که خوب توفیری تو کلیت ماجرا نمیکرد. اما تو پروژهی امروز، ارتباط رو هر دوسر میکنیم.
وسایل مورد نیاز:
- آردوینو
- برد بورد
- LED: سه عدد
- میکرو سوئیچ
- سیم برد بوردی (jumper wire): سه عدد
- مقاومت 330 اهم: سه عدد
شروع:
اول نفرین LED رو بجا میآوریم. توی پروژه ۳ تا LED میگذاریم که قرار هست با استفاده از یک دکمه بهصورت نوبتی روشن و خاموش بشن. توی الکترونیک به این دکمه، نمیگن دکمه! چون کار رو باکلاس جلوه نمیده! اسمش رو گذاشتن “میکرو سوئیچ” که هر کی ندونه فکر میکنه حالا انگار چی هست! این میکرو سوئیچ دوتا پایه داره و این بچه اینقدر خاکی و بیریاس که اصلاً فرقی نمیکنه مثبت رو به کدوم وصل کنی منفی رو به کدوم! این تصویر مداری هست که من طراحی کردم:
با مقاومت، ۳ تا از پایهها رو وصل کردم به ۳ تا LED که پایه زمینشون هم با سیم به زمین بورد متصل شده. از میکرو سوئیچ هم به یکی از دیگه از پایهها ارتباط برقرارشده که ورودی مدار باشه.
هدف این پروژه:
برنامهای که باید مینوشتم به این صورت بود که ابتدا تمام LEDها خاموش باشن. بعد از فشار دادنِ اولین بارِ میکرو سوئیچ، اولی روشن بشه، دومین بار دومی و … . در انتها هم باز همه چراغها خاموش بشن. برنامهای که نوشتم:
int buttonStatus=1; int value; void setup() { pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, INPUT); } void loop() { value=digitalRead(5); if(value==HIGH) { buttonStatus++; if(buttonStatus>=5) buttonStatus=1; delay(300); } digitalWrite(buttonStatus,HIGH); }
رفع اشکالهای کد
کار کرد؟ معلومه که نه! اصلاً اگه کد شما دفعه اول کار کرد حتماً یه مشکلی هست، یا توی شما یا توی کد! اما اینبار بیشازحد انتظار مشکل داشت. تمامی LED ها با همدیگه روشن شدند! که خوب مشخصاً برنامه داشت بدون دلیل وارد اون شرط میشد. بعد از کلی بررسیکردن متوجه شدم میکرو سوئیچها اینقدرها هم سربهزیر نیستن. چیزی به اسم پولآپ وجود داره که قاعدتاً باید اسم یه نوع بیماری باشه! اما اینجوریه که مشخص میکنه تو حالت عادی وقتیکه کلید رو نفشردیم، چه مقداری توی ورودی بره. خوشبختانه آردوینو ما پول آپ رو بهصورت داخلی داره و باید بهش اطلاع بدیم که فعالش کنه. درنتیجه خط زیر باید توی تابع Setup اضافه بشه:
digitalWrite(5, HIGH);
و طبیعتاً حالا که توی حالت عادی مقدار HIGH رو خروجی میده، باید شرط رو عوض کنیم:
if(value==LOW)
پس با مقدار صفر، متوجه فشرده شدن سوئیچ میشیم. اشکال بعدی که خودم باید زودتر حدس میزدم اینهکه وقتی شما مقداری رو توی خروجی یک پایه بورد قرار میدید، طبیعتاً نباید انتظار داشتهباشید توی تکرار بعدی تابع Loop مقدارش پریده باشه! یعنی اگه شما برنامه اصلاحشده بالا رو اجرا کنید، با فشار دادن سوئیچ LED اول روشنشده و با فشاردادن برای بار دوم LED دوم هم به اون ملحق میشه. پس اگه میخواید فقط یک LED روشن بمونه، لازمه قبلی رو خاموشکنید. پس تابع Loop رو به این صورت در میاریم:
void loop() { value=digitalRead(5); if(value==LOW) { buttonStatus++; if(buttonStatus>=5) buttonStatus=1; delay(300); } for(int i=2;i<5;i++) { if(i==buttonStatus) digitalWrite(i, HIGH); else digitalWrite(i, LOW); } }
خوب حالا شد! این تغییرات هدفی که داشتیم رو برآورده میکنه. اما یه تغییر کوچیک دیگه برای باحالتر شدن پروژه اضافه میکنیم: اگه میکرو سوئیچ بهصورت ممتد مثلاً برای دو ثانیه فشرده شد همه LED ها باهم روشن بشه. اینکار بهسادگی دنیای نرمافزار نیست. یهجورایی شما باید دستی حساب کنید که چقدر سوئیچ فشردهشده! شما رو با تابع millis آشنا میکنم. ایشون مقدار زمانِ گذشته از آخرین اجرای بورد رو در واحد میلیثانیه به شما اطلاع میدن. کاری که باید بکنیم اینه که زمانی که سوئیچ فشرده شد، زمان رو بگیریم و زمانی که رها شد، مدتزمان گذشته رو حساب کنیم! به نظر میاد توی آموزش آردوینو روزهای سختی پیش رو داشته باشیم!
کد پروژه بعد از تمام این تغییرات
int buttonStatus=1; int value; int start=-1; int endPress; void setup() { pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, INPUT); digitalWrite(5, HIGH); } void loop() { value=digitalRead(5); if(value==LOW) { if(start==-1)start = millis(); buttonStatus++; if(buttonStatus>=5) buttonStatus=1; delay(300); } else { endPress=millis(); if(start!=-1 && endPress-start>2000) buttonStatus=6; start=-1; } for(int i=2;i<5;i++) { if(i==buttonStatus || buttonStatus==6) digitalWrite(i, HIGH); else digitalWrite(i, LOW); } }
نکات
مقدار ۱- رو به این دلیل قرار دادیم که موقعی که سوئیچ فشردهشده و چندین بار Loop اجرا میشه، هربار مقدار جدیدی نگیره. موقعی که شما فکر میکنید که یک لحظه سوئیچ رو فشار دادید، ممکنه ۱۰۰ دفعه تابع Loop اجرا بشه. برای همین بهمیزانی از delay نیاز دارید.
منبع: سیسوگ