آموزش آردوینو، پروژهی سوم
باباطاهر عریان خیلی سال پیش فرموده: چه خوش بی، مهربونی هر دو سر بی / که یک سر مهربونی دردسر بی
با توجه به بیت بعدیِ این دوبیتی، ما حدس میزنیم که باباطاهر توی حال خیلی خوبی بوده! اما امکان نداره ایشون هیچ تصور میکرده که ما امروز، موقع آموزش آردوینو این دوبیتی به کارمون بیاد!
تا اینجا ارتباط ما یک سر بی! یعنی فقط با LED ها میتونستیم اطلاعاتی رو از وضعیت خروجیها بهدست بیاریم. ورودیها رو هم باز از خود بورد میگرفتیم که خوب توفیری تو کلیت ماجرا نمیکرد. اما تو پروژهی امروز، ارتباط رو هر دو سر میکنیم!
شاید برای شما مفید باشد: پروژه های آردوینو
وسایل مورد نیاز
- آردوینو
- بِرِد بورد
- LED، سه عدد
- میکرو سوئیچ
- سیم برد بوردی (jumper wire)، سه عدد
- مقاومت 330 اهم، سه عدد
شروع
اول نفرین LED رو بجا میآوریم. توی پروژه ۳ تا LED میگذاریم که قرار هست با استفاده از یک دکمه بهصورت نوبتی روشن و خاموش بشن.
توی الکترونیک به این دکمه، نمیگن دکمه! چون کار رو باکلاس جلوه نمیده!
اسمش رو گذاشتن “میکرو سوئیچ” که هر کی ندونه فکر میکنه حالا انگار چی هست! این میکرو سوئیچ دوتا پایه داره و این بچه اینقدر خاکی و بیریاس که اصلاً فرقی نمیکنه مثبت رو به کدوم وصل کنی منفی رو به کدوم!
این تصویر مداری هست که من طراحی کردم:
با مقاومت، ۳ تا از پایهها رو وصل کردم به ۳ تا LED که پایه زمینشون هم با سیم به زمین بورد متصل شده. از میکرو سوئیچ هم به یکی از دیگه از پایهها ارتباط برقرارشده که ورودی مدار باشه.
هدف این پروژه
برنامهای که باید مینوشتم به این صورت بود که ابتدا تمام LED ها خاموش باشن. بعد از فشار دادنِ اولین بارِ میکرو سوئیچ، اولی روشن بشه، دومین بار دومی و … . در انتها هم باز همه چراغها خاموش بشن. برنامهای که نوشتم:
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 | 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 اضافه بشه:
1 | digitalWrite(5, HIGH); |
و طبیعتاً حالا که توی حالت عادی مقدار HIGH رو خروجی میده، باید شرط رو عوض کنیم:
1 | if(value==LOW) |
پس با مقدار صفر، متوجه فشرده شدن سوئیچ میشیم.
اشکال بعدی که خودم باید زودتر حدس میزدم اینه که وقتی شما مقداری رو توی خروجی یک پایه بورد قرار میدید، طبیعتاً نباید انتظار داشته باشید توی تکرار بعدی تابع Loop مقدارش پریده باشه!
یعنی اگه شما برنامه اصلاحشده بالا رو اجرا کنید، با فشار دادن سوئیچ LED اول روشنشده و با فشار دادن برای بار دوم LED دوم هم به اون ملحق میشه. پس اگه میخواید فقط یک LED روشن بمونه، لازمه قبلی رو خاموشکنید. پس تابع Loop رو به این صورت در میاریم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 آشنا میکنم. ایشون مقدار زمانِ گذشته از آخرین اجرای بورد رو در واحد میلیثانیه به شما اطلاع میدن. کاری که باید بکنیم اینه که زمانی که سوئیچ فشرده شد، زمان رو بگیریم و زمانی که رها شد، مدتزمان گذشته رو حساب کنیم! به نظر میاد توی آموزش آردوینو روزهای سختی پیش رو داشته باشیم!
کد پروژه بعد از تمام این تغییرات
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 | //By Sisoog 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); } } |
نکات
مقدار 1- رو به این دلیل قرار دادیم که موقعی که سوئیچ فشردهشده و چندین بار Loop اجرا میشه، هر بار مقدار جدیدی نگیره.
موقعی که شما فکر میکنید که یک لحظه سوئیچ رو فشار دادید، ممکنه 100 دفعه تابع Loop اجرا بشه. برای همین به میزانی از delay نیاز دارید.