جلسه نوزدهم : راه اندازی رله

به نام خدا
این جلسه قصد دارم در مورد راه اندازی رله باهاتون صحبت کنم .
قدم اول اصلا این که رله چیه؟ به طور خیلی خیلی خیلی کلی بخوام بگم رله یه سوئیچه . سوئیچ هایی که تو جلسه های قبلی استفاه می کردیم رو یادتونه ؟ اگه قرار بود سوئیچ زده بشه (اصطلاحا میگیم سوئیچ تحریک بشه )، ما باید با انگشت روی دکمه کلید فشار می آوردیم تا زده بشه .
اما رله ها سوئیچ هایی هستن که با یه سری فعل و انفعالات الکترونیکی و مکانیکی کار سوئیچینگ رو انجام میدن. به عبارت دیگه ما برای قطع و وصل کردن سوئیچ داخلی رله نیازی نداریم که با دست فشار بدیم یا هر نوع کار فیزیکی دیگه بکنیم، بلکه با استفاده از میکروکنترلر و کد نویسی این کار رو انجام می دیم.
یه کم واضح تر بگم منظورم چیه :
یه LED رو تصور کنید که می خوایم روشنش کنیم . یه راه حل اینه که دو تا ولتاژ VCC و GND داشته باشیم مثلا باتری (اینجوری:)
AABatteryHolder
خروجی باتری ها رو بزنیم به LED تا روشن بشه برداریم تا خاموش بشه (با رعایت پلاریته وگرنه LED می سوزه ). اینجا ما داریم به صورت فیزیکی LED رو خاموش و رو شن می کنیم . ولی اگه بیایم با استفاده از یه میکروکنترلر مثل آردوینو این عملیات خاموش و روشن شدن LED رو انجام بدیم (مثل پروژه چشمک زن که جلسه پنجم انجام دادیم ) داریم با استفاده از کدنویسی و بدون دخالت فیزیکی این کار رو انجام میدیم.
داستان رله هم همینه . سوئیچ های قبلی که باهاشون کار کردیم برای تحریکشون لازم بود به صورت فیزیکی سوئیچ رو قطع و وصل کنیم ولی اگه همین تحریک با استفاده از میکروکنترلر و بدون دخالت مستقیم دست انجام بشه میشه رله .
این تعریف های ساده ای از رله بود ، اگه قصد دارید خیلی جزئی تر بدونید رله چیه این لینک رو بخونید.

اما بریم سراغ معرفی قسمت های مختلف یه رله که باهشون کار داریم. شما می تونید انواع ماژول های رله رو از اینجا ببینید. مدلی که من امروز باهاش کار می کنم این هست:
KEEPONIC_Relay_5v_2-500x500 همونطور که می بینید این رله 3 قسمت مهم داره که دونه به دونه معرفیشون می کنم :
1 (1)
خب ما توسط این قسمت به رله میگیم خاموش بشه یا روشن بشه. یعنی همون بخش تحریکش در واقع. برای این کنترل یا بازهم می تونیم مثل مثال باتری بریم سیم برداریم و هر موقع خواستیم وصل کنیم و هر موقع نخواستیم قطع کنیم (یعنی به صورت دستی و فیزیکی )، یا این که می تونیم این قسمت رو به یه میکروکنترلر مثل آردوینو وصل کنیم و از طریق دستورهای کدنویسی این کار رو انجام بدیم. اگر دقت کنید این قسمت سه تا پایه داره . یکی DC+ که در واقع همون پایه VCC هست و باید بهش 5 ولت اردوینو رو وصل کنیم. پایه دیگه DC- هست که نقش گراند (GND) رو داره که به پین زمین آردوینو وصلش می کنیم. یه پایه دیگه داره به اسم IN. از طریق این پایه روشن یا خاموش بودن رله کنترل میشه. یعنی کل کاری که ما در کنترل یک رله انجام میدیم اینه که با ولتاژ این پین رله بازی کنیم . چون این بازی کردن یه وضعیت دوحالته هست یعنی خاموش و روشن (معادل 0 و 1 ) ، این پین رله رو به یکی از پین های دیجیتال دلخواه آردوینو وصل می کنیم. شماره پین مهم نیست چون فقط قصد داریم 0 و 1 کنیم و نم یخوایم PWM بدیم. حالا سوالی که پیش میاد اینه که باید به پین رله رو 0 کنیم تا رله روشن شه یا 1 کنیم تا روشن شه ؟ جواب این سوالتون رو تو بخش سوم همین توضیحات خواهم داد.

1 (3)
این قسمت از رله رو باید به وسیله ای وصل کنیم که قصد داریم تحت کنترلش بگیریم. مثلا به یه موتور با LED توان بالا. خب اگه به عکس دقت کنید میبینید که این قسمت از رله سه تا ترمینال داره که به صورت زیر نام گذاری می شن:
1 (3)
پایه normally close پایه ای هست که در حالت عادی که رله خاموشه به پایه common (یعنی پایه کناریش) وصله . این اتصال رو می تونید از طریق یک مولتی متر هم چک کنید. پایه normally open پایه ای هست که وقتی رله روشن میشه به پایه common وصل میشه در این حالت پایه common از پایه normally close جدا میشه که باز هم می تونید از طریق مولتی متر تست بگیرید. در همین حد برای ما کافیه که از این قسمت بگیم و لی اگه سوال دارید که اصلا پایه normally close چیه و چرا در حالت خاموش رله می چسبه به common این لینک رو مطالعه کنید.

1 (2)
این قسمت تعیین میکنیم که سطح تحریکمون high باشه یا low باشه. یعنی چی ؟
یادتونه تو معرفی قسمت یک همین جلسه گفتم حالا برای روشن کردن رله باید به پایه IN صفر بدیم یا یک بدیم؟ توی این قسمت رله داریم همین رو تعیین می کنیم. اگه وضعیت جامپر زرد رنگ به همین صورت الانش باشه (یعنی روی H باشه ) برای روشن کردن رله باید به پایه IN منطق HIGH وصل کنیم اگه وضعیت جامپر رله بر عکس باشه یعنی روی L باشه باید برای روشن کردن رله بهش LOW بدیم. اصطلاحا به حالت اول میگن رله 1 فعاله و به حالت دوم میگن 0 فعاله.

خب این جا معرفی رله تموم شد از اینجا به بعد پروژمون رو انجام میدیم .

************************************************************************************************

خب تو پروژمون قصد داریم فقط رله رو روشن و خاموش کنیم. برای این کار مطابق توضیح زیر مدار رو ببندید:

پایه DC+ رله به پایه 5v آردوینو
پایه DC- رله به پایه GND آردوینو
پایه IN رله به پایه دیجیتال شماره 8 آردوینو (به جای این پین دیجیتال هر پین دیجیتال دلخواه دیگه ای رو هم می تونید استفاده کنید)

سادست دیگه مگه نه ؟
خب حالا میریم سراغ مرحله کد نویسی :
کد زیر رو آپلود کنید تا هر قسمتش رو توضیح بدم :
2016-02-20_15-31-08
قسمت 1 : معرفی پین 8 (پین متصل به رله ) به نام relay_pin
قسمت 2 :کانفیگ ارتباط سریال
قسمت 3 :شرط if . این شرط که در جلسات پیش به تفصیل توضیح داده شده معین می کنه که آیا داده ای در کنسول سریال دریافت شده یا نه.
قسمت 4: :در این خط کد، داده کنسول سریال توسط دستور Serial.read خونده می شه. بعد از آن ،عدد 48 از این داده کم می شه. علت کم شدن عدد 48 چیه ؟
اگه همین کد رو بدون -48 پروگرام کنید و اجرا کنید وقتی تو کنسول عدد 0 تایپ بشه تو خروجی کنسول عدد 48 دیده می شه ( چی شد ؟ من 0 تایپ کردم ولی داره 48 نشون میده ). در صورتی که عدد 9 تایپ بشه در خروجی کنسول عدد 57 دیده می شه. داستان چیه ؟
با کمی جست و جو معلوم می شه که خروجی دستور Serial.read در واقع کد اسکی عدد 0 و 9 هست. یعنی 48 کد اسکی عدد 0 هست و 57 کد اسکی عدد 9 ! یعنی وقتی ما 0 تایپ می کنیم تو ورودی کنسول ، آردوینو میره عدد 48 که معادل کد اسکی 0 هست رو به عنوان خروجی دستور Serial.read تحویل میده.
بنابراین ما برای این که بتونیم از این خروجی اسکی (که مطلوبمون نیست ) به خروجی واقعی خودمون برسیم لازمه از کد اسکی (که الان خروجی دستور Serial.read هست ) عدد 48 رو کم کنیم .به همین سادگی. در نهایت خروجی این خط کد که تو متغیر data ریخته میشه همون عددی هست که ما توی کنسول تایپش کردیم یعنی 0 یا 9 . به نظر من یه بار بدون -48 کد رو تست کنید و ببینید.
قسمت 5 :داده ای که توی کنسول تایپ کردیم تو قسمت خروجی کنسول برامون نشون داده میشه.
قسمت 6 : داده توی متغیر data مستقیما به پین متصل به رله فرستاده میشه.

حالا کد رو تست کنید.
اگه جامپر روی قسمت H باشه وقتی 1 میدید رله روشن میشه و وقتی 0 میدید رله خاموش میشه .
اگه جامپر روی قسمت L باشه وقتی 0 میدید رله روشن میشه و وقتی 1 میدید رله خاموش میشه .

این جلسه هم همینجا تموم شد.
سوالتتون رو تو انجمن بپرسید لطفا .

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

جلسه قبل از کنسول به عنوان خروجی استفاده کردیم یعنی یه سری پیغام رو تو کنسول چاپ کردیم. این جلسه روند معکوس میشه یعنی تصمیم داریم از کنسول به عنوان ورودی استفاده کنیم و از اون داده دریافت کنیم. برای وارد کردن پیغام در کنسول آردوینو از قسمت بالای کنسول استفاده می کنیم. Untitled3-300x229 خب شروع می کنیم به کد نویسی. طبق معمول اول باید نرخ ارتباط سریال رو کانفیگ کنیم. این دفعه Baude Rate رو به جای 9600 روی 115200 تنظیم می کنیم. البته هیچ اصراری نیست که Baude Rate رو تغییر بدید صرفا محظ تنوع این کارو می کنیم.ddهدفمون تو این برنامه این هست که اول از کنسول سریال یه داده دریافت کنیم بعد همون رو توی کنسول چاپ کنیم. روند کد نویسی برای خوندن از کنسول سریال به این صورته که اول چک میکنیم اصلا داده ای برای دریافت وجود داره یا نه! اگر داده ای دریافت شده بود اون رو بر می داریم و توی کنسول چاپ می کنیم اگر نه خب هیچی. 

دستوری که معین میکنه اصن داده برای دریافت وجود داره یا نه Serial.available هست. خروجی این دستور تعداد کاراکترهای دریافتی از کنسوله. برای این که بدونیم اصن داده ای توسط کنسول سریال دریافت شده یا نه کافیه همین دستور رو بنویسیم و چک کنیم که آیا خروجیش بزرگتر از صفر هست یا نه. اگر بزرگتر از صفر بود که یعنی یه داده اومده توکنسول سریال و آماده خوندنه اگر نه یعنی هیچ داده ای دریافت نشده. همین شرطی که میذاریم (خروجی دستور بزرگتر از صفر هست یا نه)  تو عالم کدنویسی یعنی استفاده از دستور if . فرم کد نویسی این دستور میشه این شکلی: Untitled درمورد ساختار دستور if حتما یه مطالعه ای بکنید. حالا فرض کنید شرط if برقرار باشه یعنی تو بافر ارتباط سریال داده وجود داشته باشه، وقتشه که اون داده خونده بشه. بدون شک دستور خوندن باید تو تابع if و درون کروشه های تابع if نوشته بشه چون عملا اگه داده ای برای خوندن وجود نداشته باشه خب خوندنش کار بیخودیه. محل مورد نظر ما توی شکل نمایش داده شده: Untitledو اما قدم نهایی: خوندن داده. دستوری که باهاش می خونیم Serial.read هست. خروجی این دستور یک کاراکتر هست. یعنی وقتی این دستور رو می نویسیم کامپایلر میره اولین کاراکتر عبارت ما رو برمیگردونه. مثلا اگه aftab رو نوشته باشیم با دستورSerial.read کاراکتر a برگردونده میشه.  حالا این که ما چجوری از خروجی این تابع استفاده کنیم باز هم برمیگرده به قوانین برنامه نویسی. یه قانون داریم به نام معرفی متغیر. اگه لینک رو مطالعه کردید میدونید که ما به هر متغیر میتونیم یه مقدار انتساب بدیم. مثلا من متغیرم رو از نوع char در نظر میگیرم. اسمشم میزارم data. حالاباید بهش مقدار بدم. مقدار این متغیر رو خروجی دستور Serial.read (یعنی همون یه کاراکتر) در نظر میگیرم. بنابراین دستور من به فرم زیر در میاد. Untitled الان در حال حاضر در صورتی که داده ای توی بافر سریال وجود داشته باشه توسط دستور Serial.read خونده میشه. خیلی خیلی دقت کنید نوع متغیر رو از نوع char در نظر گرفتیم. در نهایت برای چاپ عدد توی کنسول از دستور ؟؟؟؟؟؟؟؟ استفاده میکنیم. طبق آموزش های جلسه قبل جای علامت سوال ها با دستور Serial.println پر میشه. بنابراین ورژن نهایی کد میشه عکس زیر: Untitled اما کسایی که دقیقن میتونن درک کنن چرا کنار دستور Serial.println یه فلش خورده. جلسه قبل گفتیم فرمت دستور Serial.println اینطوریه که هرچیزی به عنوان آرگومانش بخواد در نظرگرفته بشه باید توی علامت دبل کوتیشن گذاشته بشه (علامت “”) پس چرا الان علامت دبل کوتیشن نذاشتیم ؟ اگه من میخواستم دقیقا عبارت data رو توی کنسول چاپ کنم باید علامت دبل کوتیشن رو رعایت می کردم و کد رو به همون صورت قبل می نوشتم. اما الان قرار نیست همچین کاری بکنم الان data بعنوان یه متغیر تعریف شده و من میخوام مقداری که توی متغیر data هست رو چاپ کنم. طبق قانون دستور Serial.println برای چاپ عبارت داخل یه متغیر (مثل متغیر data) علامت دبل کوتیشن نباید گذاشته بشه. خب کد رو اپلود کنید و کنسول سریال رو باز کنید. الان قسمت بالای کنسول عدد 5 رو تایپ کنید و دکمه send رو بزنید (یا enter کنید).
Untitled
وقتی اینتر کنید باید توی کنسول سریالتون عدد 5 تایپ بشه مثل شکل زیر:
Untitled
یه نکته توی عکسه باید بهش دقت کنید. baud rate روی 115200 باید تنظیم باشه. اگه به اشتباه baude rate رو روی 9600 گذاشته باشید هر چقدر 5 تایپ کنید و enter بزنید فقط یه سری داده پرت و پلا دریافت می کنید بنابراین دقت کنید که baude rate ای که تو دستور Serial.begin انتخاب می کنید با baude rate ای که توی کنسول انتخاب می کنید مساوی باشه.
به همون صورت قبل حرف a رو تو قسمت ورودی کنسول تایپ کنید و اینتر بزنید همون موقع حرف a برای شما تایپ میشه.
حالا قسمت جالب انگیز ماجرا:
بیاید قسمت ورودی کنسول تایپ کنید aftab و اینتر بزنید. وقتی بخواد تو کنسول چاپ کنه با شکل زیر مواجه میشید.
Untitled

خیلی به این قضیه اصرار دارم. ببنید کل کلمه aftab پشت سر هم تایپ نشده بلکه هر کاراکتر تو یه خط چاپ شده. این قضیه خیلی مهمه. دلیل این اتفاقی که افتاده اینه که دستور Serial.read تنها و تنها یک کاراکتر رو بر میگردونه. بنابراین هر باری که وارد شرط if میشه یک کارکتر از کاراکترهای عبارت aftab چاپ میشه.

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

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

پایان جلسه هفتم