جلسه هجدهم : راه اندازی LCD کاراکتری 1602

به نام خدا
اول جلسه یه پیشنهاد دارم : این که اول کل جلسه رو یه دور تا آخر بخونین بعد قسمت های سخت افزاریش رو اجرا کنین چون دو روش ارائه میشه. پس تا آخر جلسه رو بخونید هر کدوم از دو روش رو که خواستین انجام بدین.
این جلسه قصد داریم در مورد LCD کاراکتری 1602 حرف بزنیم . اول بگیم که چرا به این میگن 1602: این نمایشگر 16 تا ستون و دو تا سطر داره همین ! در مورد این که چرا لازمه تو پروژه هامون LCD داشته باشیم فکر نمی کنم هیچ نیازی داشته باشه که توضیح بدم. فقط همینو بگم که تا الان هر چیزی رو که می خواستیم ببینیم (مثلا عدد پتانسیومتر ) روی کنسول سریال آردوینو می دیدیم ولی خب خیلی مواقع ممکنه مدارمون رو از کامپیوتر جدا کنیم و با یه سوئیچ آداپتور ببریمش یه جایی وصلش کنیم که هیچ نوع کامپیوتری نباشه که بتونیم از کنسول سریالش استفاده کنیم. وقتی تو همچین شرایطی گرفتار شدیم می ریم سراغ استفاده از انواع LCD ها.
character_2x16_modules_lcd_display_hd44780_controller_black_on_yg
این نمایشگر 16 تا پایه داره که اگه به عکس بالا یه کم دقیق بشید کنار پینها یه شماره 1 می بینید یه شماره 16 . ارتباط آردوینو و این LCD به صورت پارالل هست به همین خاطر باید یه عالمه پین رو وصل کنیم پس بدون فوت وقت بریم سراغ سخت افزار مدرا .

مواد لازم :
هر نمونه آردوینو در دسترس
LCD کاراکتری 1602
برد بورد کوچیک
پتانسیومتر
مقاومت 220 اهم
سیم نری به نری

خب حالا مدارتون رو مثل عکس زیر ببندید :
LCD_Base_bb_Fritz
LCD_Base_bb_Schem
میدونم مدارش زیاد دل و روده داشت بنابراین خسته نباشید.
پروژه ای که می خوایم انجام بدیم اینه که هر چیزی رو که از کنسول سریال دریافت کردیم توی LCD نمایش بده .
برای این کار کتابخونه Liquid Crystal رو به کتابخونه های آردوینو اضافه کنید:
Adafruit_LiquidCrystal-master
آموزش اضافه کردن کتابخونه هم اینجاست:

بعد از این که کتابخونه رو به صورت موفقیت آمیز به آردوینو اضافه کردید مثل عکس زیر کد serialdisplay رو بیارید :
2016-01-30_14-07-20
خب با یه همچین کدی مواجه میشید (البته من نیم کیلو کامنت بالاش رو پاک کردم ):
2016-01-30_14-09-10

قسمت های مختلف :
1:معرفی کتابخونه LiquidCrystal

2: اگه یادتون باشه قبلا هر وقت یه پین رو استفاده می کردیم میومدیم توی هدر برنامه بهش اسم می دادیم . الان اگه بشمارید 6 تا سیم از LCD وصل کردیم به پین های آردوینو . قائدتا باید 6 تا متغیر تو هدر تعریف می کردیم . پس کو ؟ چرا نکردیم ؟ همین خط دستوری که اینجا نوشتیم (LiquidCrystal lcd(12, 11, 5, 4, 3, 2 دقیقا همین کار رو میکنه. فقط فرقش اینه که اون تعریف کردنا به جای اینه اینجا نوشته بشه رفته تو کتابخونه نوشته شده .

3.توی این قسمت کانفیگ پین هایی که تو قسمت 2 معرفی شد انجام میشه.تابع begin در کتابخونه LiquidCrystal پین های معرفی شده در قسمت 2 رو به صورت ورودی / خروجی کانفیگ میکنه. علاوه بر این تعداد سطر و ستون های LCD به عنوان آرگومان های ورودی این تابع قرار داده میشه (یعنی 2 و 16).

4: کانفیگ ارتباط سریال با baude rate مساوی 9600.

بافر ارتباط سریال : قبل از توضیح پارت پنجم لازمه در مورد بافر سریال یه توضیح خیلی ساده بدم. در همین حد بدونید که بافر سریال یه واسطه . یعنی هر آنچه که شما توی کنسول سریال آردوینو تایپ می کنید قبل از این که با دستور Serial.read بریزیدش تو یه متغیر، توی بافر سریال ذخیره میشه. بافر رو یه چیزی مثل شکل زیر تصور کنید که هر کاراکتری که ما تو کنسول تایپ می کنیم میره تو یکی از خونه های این بافر می شینه.

2016-01-30_14-53-39
5: این جا داریم میگیم اگه چیزی توی بافر ارتباط سریال وجود داشت بیا کارای توی کروشه رو انجام بده . دقت کنید با if نوشته . دستور Serial.available میاد تعداد متغیرهایی رو که توی بافر ارتباط سریال هست رو خروجی میده. یعنی مثلا اگه شما تو کنسول سریال تایپ کرده باشید salam خروجی دستورSerial.available عدد 5 هست (یعنی 5 تا کاراکتر). اینجا داره میگه اگه خروجی این دستور بزرگتر از صفر بود (یعنی یه چیزی توی کنسول سریال آردوینو نوشته شده بود (اصلا مهم نیست چند تا)) بیا دستور های بین دو کروشه مربوط به این if رو اجرا کن.

6: اینجا 100 میلی ثانیه صبر می کنه تا کل اون چیزی که ما توی کنسول سریال تایپ کردیم تو بافرارتباط سریال جا بگیره .

7: با دستور clear تمام داده های روی LCD پاک میشه در واقع LCD رو خالی می کنه تا داده بعدی روش چاپ بشه.

8 و 9 : اتفاقی که توی این دو خط کد می افته اینه که داده های خونه های بافر ارتباط سریال دونه دونه روی LCD چاپ میشن تا جایی که بافر خالی بشه. علت این که از while استفاده شده اینه که باید تک تک خونه ها رو خالی کنه تا جایی که دیگه بافر خالی بشه . بعد با دستور (()lcd.write(Serial.read میاد هر چیزی رو که از کنسول سریال میگیره توی LCD چاپ می کنه.

دقیق تر بگم ؟
بار اول که وارد دستور (while (Serial.available() > 0 میشه خروجی دستور Serial.available() مساوی 5 خواهد بود (چون salam توی بافر سریاله ) .بنابراین شرط برقراره و از while عبور میکنه میاد دستور (()lcd.write(Serial.read رو اجرا می کنه .

اگه یادتون باشه توی جلسه ای که در مورد ارتباط سریال حرف میزدیم می گفتیم Serial.read فقط یک کاراکتر رو بر می گردونه . یعنی اگه توی بافر سریال ما مثل بالا salam نوشته شده باشه نمیاد کل salam رو به عنوان خروجی بده فقط S رو برمیگردونه و بعد بافر سریال رو به این شکل در میاره یعنی S رو از اون خارج می کنه :
2016-01-30_15-23-13
توی همین بار اول کاراکتر S با دستور (()lcd.write(Serial.read روی LCD چاپ میشه.
به آخر while  می رسیم .طبق خاصیت حلقه while یک باردیگه شرایط while چک میشه. اگر شرط برقرار باشه وارد حلقه میشه اگه شرط برقرار نباشه از حلقه while خارج میشه.
بار دوم که قراره شرط while چک بشه خروجی دستور Serial.available() مساوی 4 خواهد بود بنابراین بازم شرط برقراره و یک بار دیگه دستور (()lcd.write(Serial.read اجرا میشه و این بار a از بافر سریال خارج میشه و توی LCD چاپ میشه .

اینطوریه که کارکاترها دونه دونه از بافر خارج میشن و روی LCD چاپ میشن تا جایی که بافر خالی بشه و خروجی دستور Serial.available() مساوی صفر بشه. در این حالت شرط while  برقرار نمیشه و از حلقه خارج میشیم.

برای این که حرف منو بهتر درک کنین این قسمت از کد رو تغییر بدید و اپلود کنید:
2016-01-30_16-42-17
همونطور که میبیند هر کدوم از کاراکترها با فاصله زمانی 2 ثانیه روی LCD چاپ میشن.

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

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

آزار دهنده ترین قسمت انجام این پروژه قسمت سیم بندی اون بود که مجبور بودیم n تاسیم رو با مقاومت و پتانسیومتر استفاده کنیم .
یه راه حل خیلی خوب وجود داره که به جای این همه بند و بساط با 4 تا دونه سیم بتونیم ارتباط نمایشگر و آردوینو رو فراهم کنیم.
برای این کار فقط باید دستمونو بکنیم تو جیبمون و یه دونه از درایور های LCD بخریم :2016-01-30_16-17-22

بعد از این که اینو خریدید لحیمش کنیمد پشت LCD به این شکل :
2016-01-30_16-15-27

وقتی لحیم کاری تموم شد الان سخت افزارمون رو به این شکل می بندیم :
LCD 1602 I2C SCH

می بینید فقط 4 تا دونه سیم .بدون پتانسیومتر ، بدون مقاومت و بدون n تا سیم. اگه دقت کنید علاوه بر VCC و GND دو تا پین دیگه وجود داره به نام های SCL و SDA. این دو تا پین ، پین های ارتباط I2C هستن . ارتباط I2C یکی از پرکاربردترین پروتکل های ارتباطی تو کار ماست . خیلی از سنسورها خیلی از نمایشگرهامون با این پروتکل کار میکنن و ما باید بتونیم تشخیصشون بدیم و راهشون بندازیم. حالا یه سوال پیش میاد و اونم اینه که یه قطعه رو که پروتکل ارتباطیش I2C هست چطوری تشخیص بدیم؟
جواب سوال اینه که به پین های قطعه نگاه می کنیم در صورتی که روی پینهای قطعه اسم های SCL و SDA وجود داشت پروتکل ارتباطی اون قطعه I2C هست.

حالا قطعه هایی رو که پروتکل ارتباطیشون I2C هست چجوری به آردوینو وصل کنیم ؟آیا پین خاصی دارن ؟
مطابق جدول زیر این قطعه ها رو به آردوینو وصل می کنیم :
2016-01-30_16-39-40

یعنی اگه با آردوینو UNO کار می کنید باید به پایه های آنالوگ 4 و 5 وصل کنید. اگه با مگا کار می کنید به پایه های دیجیتال 20 و 21 وصل کنید و الی آخر.

ما روی UNO کار می کنیم بنابراین به پایه های آنالوگ 4 و 5 وصل می کنیم . دقت کنین که ترتیب پایه ها تغییر نکنه که اگه جا به جا بزنین پروژه به هیچ عنوان کار نمی کنه.

خب مدار رو بستید حالا کتابخونه زیر رو به نرم افزار آردوینو اضافه کنید:
LiquidCrystal_I2C

مثل حالت قبل مطابق عکس زیر مثال serialdisplay رو بیارید :
2016-01-30_16-47-28

کدی مثل همون کد قبلی رو به این صورت میبینید (البته من بازم کامنت ها رو پاک کردم ) :
2016-01-30_16-50-17

1: معرفی کتابخونه Wire (در مواقع استفاده از پروتکل I2C صدا زده میشه )

2.معرفی کتابخونه LiquidCrystal_I2C

3.این جا تعداد سطر ها و ستون ها و آدرس I2C نمایشگر معرفی میشه (دقت کنید هر قطعه ای که با I2C کار کنه یه آدرس خاص داره مثلا مال این LCD آدرسش 0X27 هست)

4. بک لایت (نوز زمینه) نمایشگر صدا زده میشه.

بقیه قسمت های کد دقیقا مثل قبله و با همون توشیحات می تونید درکش کنید. کد رو آپلود کنید و استفاده کنید.

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

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

سلام و عذر خواهی بابت تاخیر در آپلود کردن جلسه ها.
این جلسه قصد داریم در مورد ال ای دی های RGB حرف بزنیم. این که منطق کارشون چیه و با آردوینو چطوری باید راه اندازیشون کنیم.

خب اول میریم سراغ معرفی خود این ال ای دی ها. برای این که با تکنولوژی RGB آشنا بشید یه سری به این لینک بزنید و برگردید.

LED-RGB-8CD5kCA

قسمت اول ماجرا با کمک دوستان حل شد. میریم سراغ کار اصلی خودمون اتصال این ال ای دی به آردوینو. همونطوری که تو عکس بالا می بینید 4 تا پایه داره. سه پایه مربوط به رنگه و یک پایه مربوط به زمین. مسلمه که گراند(زمین) به گراند آردوینو وصل می شه، میمونن اون سه تا پایه. اون سه تا پایه باید به پین های دیجیتال آردوینو وصل بشن ولی سوالی که پیش میاد اینه که به هر پین دیجیتال دلخواه یا یه سری پین خاص. برای این که بفهمیم باید چیکار کنیم یه کم توضیح میدم:

ببینید ما یه موقع میخوایم رنگ سفید تولید کنیم. برای تولید این رنگ باید از سه رنگ قرمز، سبز و آبی با درصد های مساوی استفاده کنیم. یه موقع می خوایم رنگ بنفش تولید کنیم. برای رنگ بنفش درصد رنگ سبز با درصد رنگ قرمز صد در صد مساوی نیست (طبق قانون ترکیب رنگ ها ). حالا، گفتیم که پین های ال ای دی به پین های دیجیتال آردوینو وصل میشن. اگه قرار باشه مثل پروژه های قبل با دستور digitalWrite کار کنیم نمی تونیم برای هر رنگ درصد قائل بشیم و رنگ های مختلف ایجاد کنیم علتش اینه که وقتی می نویسیم (digitalWrite(8,HIGH داریم ولتاژ ( دقت کنید ولتاژ ) پین 8 رو 5 ولت می کنیم. وقتی می نویسیم (digitalWrite(8,LOW داریم ولتاژ این پایه رو صفر می کنیم. ما برای تولید رنگ بنفش ولتاژی که به سه تا پایه میدیم نباید مساوی باشه بلکه مثلا یکی باید 5 باشه یکی باید 3 باشه یکی باید 1.5 باشه. خب چاره چیه؟ چجوری ولتاژ متفاوت تولید کنیم؟

راه حل استفاده از PWM هست. اول یه سری به این لینک بزنید و ببینید که PWM چیه؟
با کمک منطق PWM و کد نویسی می تونیم یه کاری بکنیم که روی پایه های دیجیتال ولتاژ های بین 0 و 5 ولت بیفته. دستوری که با کمک اون از PWM استفاده می کنیم دستور analogWrite هست. مثلا (analogWrite(9,255
این دستور دو تا آرگومان داره. آرگومان اول شماره پین دیجیتال مورد نظره. آرگومان دوم یک عدد در بازه 0 تا 255 هست. وقتی صفر میدیم روی پایه دیجیتال شماره 9 ولتاژ 0 ولت می افته وقتی 255 می نویسیم روی پایه دیجیتال 9 ولتاژ 5 ولت می افته. یعنی یک تناسب بین عدد آرگومان دوم ما و ولتاژی که روی پین دیجیتال می افته وجود داره. حالا اگه قرار باشه ولتاژ 2.5 ولت روی پین 9 بیفته به جای 255 عدد 127 رو می نویسیم. یعنی میشه (analogWrite(9,127.
حالا آیا میشه به جای این پین شماره 9 هر پین دیجیتالی رو نوشت؟ جواب منفیه! پین های دیجیتالPWM آردوینو خاص هستن مثلا روی آردوینو UNO پین های PWM پین های شماره 3, 5, 6, 9, 10 و 11 هستن و تنها از این پین ها استفاده میشه. برای این که راحت تر پیداشون کنین روی برد کنار پین های PWM یه علامت مد کشیده شده:
dsku-fidhsfudhsfdsfidhsi00001
تا این جای جلسه منطق حاکم بر پروژه رو گفتیم الان میریم سراغ انجام خود پروژه عملیمون: می خوایم سه رنگ اصلی (قرمز، سبز وآبی ) رو با توالی 1 ثانیه روشن کنیم. مداری که استفاده می کنیم به صورت زیره:
learn_arduino_fritzing

دقت کنید که سه تا مقاومت به صورت سری در مدار قرار گرفته، این یه تکنیک برای افزایش طول عمر ال ای دی هاست.
خب مدار رو بستید؟ حله؟ بریم سراغ کد نویسی:

2015-09-13_11-45-17

اگه دقت کنید این کد به 4 بخش تقسیم شده. بخش اول هدر برنامه هست که متغیر های گلوبال رو توش تعریف کردیم (قبلا هم تاکید کردم حتما یه سری به برنامه نویسی بزنید). الان ما تو هدر برناممون اومدیم شماره پین های PWM مورد نظرمون رو (یعنی 9 و 10 و11) ریختیم توی سه تا متغیر. فایده این کار چیه؟ آخر برنامه میگم 😆

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

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

و اما قسمت چهارم، تابع LOOP. توی این تابع 6 بار تابع RGB صدا زده میشه. دفعه اول (RGB(200,0,0 صدا زده میشه و با این کار نور قرمز روی ال ای دی با قدرت 200 ظاهر میشه (دقت کنید اگه به جای 200، 255 میزاشتیم با توان بیشتری ال ای دی روشن میشد ولی برای جلوگیری از خطر کور شدن میزاریمش 200 حتی شما اگه بزارینش 100 بازم بهتره). بعد تابع delay رو داریم که مدت 1 ثانیه صبر میکنه و تو این یک ثانیه رنگ ال ای دی قرمزه. بعد از delay تابع (RGB(0,0,0 رو داریم. با این دستور داریم ال ای دی رو خاموش می کنیم تا برای مرحله بعد که تولید رنگ سبزه آماده بشه. تا آخر تابع loop همینطوری پیش میره و رنگ ها یکی پس از دیگری نمایش داده میشن.

پروژه ما اینجا تموم شد. اما:
1.اگه خواستید رنگ سفید درست کنید چون باید هر سه رنگ به یک میزان وجود داشته باشن از دستور (RGB(200,200,200 استفاده کنید.
2.اگه یادتون باشه تو هدر برنامه گفتم شماره پین ها رو می ریزیم تو متغیر. فایده این کار چیه ؟ فرض کنید به هر دلیلی پین شماره 10 آردوینو شما سوخت و شما تصمیم گرفتید به جای استفاده از پین PWM شماره 10 از پین PWM شماره 6 استفاده کنید. علاوه بر این که از لحاظ سخت افزاری باید تغییر مورد نظر رو انجام بدید باید توی کدنویسی تون هم این تغییر رو لحاظ کنید. الان که شماره پین تو هدر برنامه تعریف شده شما فقط و فقط همون خط معرفی پین شماره 10 رو به پین شماره 6 تغییر می دید. ولی اگه تو هدر برنامه شماره پین رو تو متغیر نریخته بودیم برای این تغییر لازم بود هم توی دستور pinMode هم توی دستور analogWrite عدد 10 رو به 6 تغییر می دادید. البته ما الان کدمون بیست خط هم نیست ولی وقتی خطوط کد نویسی زیاد بشه این کار خیلی به چشم میاد.

پایان جلسه