آموزش افزایش پین های آردوینو (پورت اکسپندر)
گاهی اوقات تعداد دستگاه های متصل به آردوینو زیاد میشود و محدودیت تعداد پین های آردوینو دردسرساز خواهد بود. اما نگران نباشید، چون با استفاده از یک آیسی پورت اکسپندر یا همان آیسی افزایش پین های آردوینو میتوانید به تعداد پین های بیشتر دسترسی داشته باشید و از این پین ها در پروژه خود استفاده کنید. در این مطلب آموزشی نحوه افزایش تعداد پورت های آردوینو بررسی شده است. آیسی MPC23017 با استفاده از پروتکل I2C راه اندازی میشود و دو پورت 8 بیتی را در اختیار شما قرار میدهد. در ادامه نحوه راه اندازی چند LED از طریق این آی سی بررسی شده است.
آشنایی با MPC23017 آی سی پورت اکسپندر
این آیسی درست مثل یک سه راهی برق عمل میکند، به این صورت که چندین دستگاه را تنها با استفاده از دو پین کنترل میکند. توجه داشته باشید که آیسی های افزایش دهنده پورت (اکسپندر) بدون نقطه ضعف نیستند، چون سرعت کنترل پورت ها متناسب با تعداد دستگاه های متصل شده کاهش می یابد.
آیسی MPC23017 دارای دو پورت دو جهته است، به این معنی که دیتا میتواند از طریق رابط I2C ارسال و دریافت شود. برای کنترل این آیسی به کتابخانه wire نیاز داریم تا پروتکل را راه اندازی کنیم.
خطوط آدرس: به صورت کلی با 23 یا 8 آدرس (سه خط آدرس قابل انتخاب در آی سی) میتوانیم پورت ها را کنترل کنیم.
آشنایی کوتاه با عملگرها
هر کسی که به تازگی وارد دنیای آردوینو شده باشد، دستورات خواندن و نوشتن و کنترل پین ها (مثل digitalWrite(12, HIGH)) را می شناسد. اما افراد مبتدی شاید این نکته را نادیده بگیرند که پین های آردوینو در حقیقت پورت های بزرگتر 8 بیتی هستند.
در این پروژه میخواهیم 2 پورت 8 بیتی را راه اندازی کنیم و دستورات خواندن و نوشتن را روی پین ها اعمال کنیم. به این صورت که همه 8 بیت را یکجا میخوانیم، سپس پین یا بیت مورد نظرمان را به صورت تکی جدا میکنیم که این نیازمند تسلط داشتن روی برخی عملگرها است. این عملگرها کمتر مورد استفاده قرار میگیرند ولی باید آنها را بشناسید و البته که در مطلب آموزشی ” افزایش پین های آردوینو ” سراغ این عملگرها خواهیم رفت.
تفاوت ها:
اولین نکته ای که باید به آن توجه داشته باشید، تفاوت بین & و && است. درست همانطور که | و || با هم متفاوت هستند. همینطور زمانی که از >> یا << استفاده میکنیم، منظورمان کوچکتر یا بزرگتر بودن نیست، بلکه میخواهیم شیفت به چپ یا راست داشته باشیم.
نمایش اعداد به صورت باینری:
ابزار دیگری که قصد استفاده از آن را داریم، نمایش بایت ها به صورت باینری در سریال مانیتور آردوینو است. به عنوان مثال:
Serial.println(29, BIN);
در واقع عدد 29 را به صورت باینری پرینت کرده ایم، یعنی 11101.
توجه داشته باشید که در سمت چپ 3 صفر را نادیده گرفتهایم. خوب بود اگر میتوانستیم هر 8 بیت را نمایش بدهیم ولی با این تابع ساده امکان نمایش این 3 صفر وجود ندارد.
چطور این 3 صفر را هم نمایش بدهیم؟
void loop() {
printBin(29);
}
void printBin(byte inByte){
for (int b = 7; b >= 0; b--)
Serial.print(bitRead(inByte, b)); // حالا عدد 29 به صورت 8 بیتی پرینت میشود: 00011101
Serial.println();
}
بیت ماسک: ( آموزش افزایش پین های آردوینو )
میخواهیم یکی از پین های پورت A را راه اندازی کنیم، و پین 2 (یعنی سومین پین از سمت راست) را برای این کار در نظر گرفته ایم و قصد داریم آن را کنترل کنیم. به همین خاطر باید این بایت ها را ارسال کنیم: 11110100
در اینجا از بیت ماسک استفاده کرده ایم. به جز بیت سوم از راست که 1 است، بقیه بیت ها را صفر کرده ایم و حالا باید از عملگر AND استفاده کنیم. در این عملگر اگر یک بیت صفر وجود داشته باشد، خروجی صفر خواهد بود. یعنی:
- 1 AND 0 میشود 0.
- 0 AND 0 میشود 0.
در نتیجه در سریال مانیتور 00000100 را مشاهده خواهیم کرد که خروجی Serial.println (B11110100 & B00000100) است و به صورت DEC برابر با 4 خواهد بود. برای اینکه بیت مورد نظرمان را 0 یا 1 کنیم از این دستور استفاده میکنم:
Serial.println((B11110100 & B00000100) >> 2)
از این ماسک برای از بین بردن بیت های اضافی که به آنها نیاز نداریم استفاده میشود، تا بیت مورد نظرمان 2 واحد به سمت راست شیفت داده شود. برای این کار یک راه حل ساده تر هم وجود دارد. نکته ای که باید به آن توجه داشته باشید این است که بیت ها از 0 تا 7 شماره گذاری میشوند.
به کدهای زیر توجه کنید:
byte mybyte = B11110100;
Serial.println(bitRead(mybyte, 2)); // prints 1
Serial.println(bitWrite(mybyte, 3, HIGH), BIN); // prints 11111100
Serial.println(bitClear(mybyte, 3), BIN); // prints 11110100
شماتیک پروژه
در این پروژه میخواهیم با استفاده از آیسی افزایش پین های آردوینو 8 تا LED را در کنار یک دیپ سوییچ هشت کانال راه اندازی کنیم.
برای انجام پروژه به قطعات زیر نیاز دارید:
- آردوینو UNO
- آی سی افزایش دهنده پورت (MPC23017)
- سوئیچ DIP هشت کانال
- · 8 ال ای دی
- · 8 مقاومت 680 اهم
- · 8 مقاومت 10K اهم
- مقاومت 2.2K اهم
- سیم جامپر
- برد بورد
شماتیک پروژه به صورت زیر است:
8 تا مقاومت 680 اهم را به LED ها متصل کرده ایم تا جریان را محدود کنیم. مقاومت 2.2 کیلواهم را به پایه 18 آیسی (MCP23017) وصل کرده ایم و 8 تا مقاومت 10 کیلواهم را به عنوان مقاومت پول آپ به 8 کانال دیپ سوییچ وصل کرده ایم. خب حالا باید سراغ کدنویسی پروژه برویم و عملکرد مدار را تست کنیم.
کدنویسی : افزایش پین های آردوینو
پس از اینکه قطعات مدار را به هم وصل کردید، کد زیر را در آردوینو خود آپلود کنید. در این پروژه میخواهیم بیت هایی که توسط دیپ سوییچ ایجاد میکنیم را به صورت واقعی و دسیمال روی سریال مانیتور نمایش دهیم:
//simple read and write to MCP23017 port expander
#include <Wire.h>
byte byteVal=0;
byte chipAddr = 0x27;
byte GPIOA = 0x12; // PortA reg addr
byte GPIOB = 0x13; // PortB reg addr
byte IODIRA = 0x00; // PortA direction reg addr
byte IODIRB = 0x01; // PortB direction reg addr
void setup(){
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(chipAddr);
Wire.write(IODIRA); // IODIRA dir register
Wire.write(0x00); // set entire PORT A as output
Wire.endTransmission();
Wire.beginTransmission(chipAddr);
Wire.write(IODIRB); // IODIRB dir register
Wire.write(0xff); // set entire PORT B as input
Wire.endTransmission();
}
void loop(){
Wire.beginTransmission(chipAddr);
Wire.write(GPIOB); // read the inputs off PORT B
Wire.requestFrom(chipAddr, 1); // ask for 1 byte
byteVal = Wire.read(); // read it
Wire.endTransmission();
// write that input to PORT A
Wire.beginTransmission(chipAddr);
Wire.write(GPIOA); // address PORT A
Wire.write(byteVal); // PORT A
Serial.print(byteVal,BIN); Serial.print(" "); Serial.println(byteVal, DEC);
Wire.endTransmission();
delay (200);
}
توضیح کدهای برنامه
در ابتدا کتابخانه wire را فراخوانی کردهایم. سپس آدرس چیپ را مشخص کرده ایم و در ادامه رجیسترها را مقداردهی کردهایم. رجیسترهای پورت A0 تا A7 آی سی MCP23017 مربوط به پورت A هستند، و رجیسترهای پورت B0 تا B7 مربوط به پورت B هستند. زمانی که رجیسترهای پورت A و B را مقداردهی میکنیم، وضعیت صفر یا یک بودن پین های آی سی را مشخص میکنیم.
در ادامه رجیسترهای مربوط به ورودی یا خروجی بودن (یعنی رجیسترهای direction) را مقداردهی کردهایم. عملکرد کدهای این بخش را میتوان مشابه عملکرد pinMode() دانست. حالا وارد بخش Setup() شده ایم و پورت A را خروجی و پورت B را ورودی تعریف کردهایم.
همچنین لازم است با توجه به نیاز پروژه خود پورت ها را به صورت ورودی یا خروجی تعریف کنید. یعنی لازم نیست یک پورت کاملا ورودی تعریف شود، یا کاملا خروجی باشد. مثلا اگر رجیسترها را به شکل زیر مقدار دهی کنید، پورت ها یکی درمیان ورودی و خروجی خواهند شد:
byte IODIRA = B0101010101
در حلقه Loop پورت B را خوانده ایم و آن را در پورت A قرار دادهایم. بسته به این که دیپ سوییچ چه وضعیتی دارد، در سریال مانیتور موارد زیر را مشاهده خواهید کرد:
پروژه کنترل LED
در این پروژه قصد داریم هر هشت LED را یکی پس از دیگری روشن کنیم. با آپلود کردن کدهای زیر میتوانید وضعیت LED ها را کنترل کنید و این کار با استفاده از دستور شیفت به چپ انجام شده است. کدهای پروژه را در زیر میتوانید مشاهده کنید:
#include <Wire.h> // Wire.h
byte inByte=1;
byte chipAddr = 0x27;
byte GPIOA = 0x12; // PortA reg addr
byte GPIOB = 0x13; // PortB reg addr
byte IODIRA = 0x00; // PortA direction reg addr
byte IODIRB = 0x01; // PortB direction reg addr
byte i = 1;
void setup(){
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(chipAddr);
Wire.write(IODIRA); // IODIRA dir register
Wire.write(0x00); // set entire PORT A as output
Wire.endTransmission();
Wire.beginTransmission(chipAddr);
Wire.write(IODIRB); // IODIRB dir register
Wire.write(0xff); // set entire PORT B as input
Wire.endTransmission();
}
void loop(){
i=i<<1;
if(i==0)
i=1;
Wire.beginTransmission(chipAddr);
Wire.write(GPIOA); // address PORT A
Wire.write(i); // PORT A
delay (500);
Wire.endTransmission();
Serial.println(i);
}
خروجی پروژه در سریال مانیتور
در انتها، امیدواریم این پروژه مورد توجه شما قرار گرفته باشد. در این پروژه با آی سی افزایش دهنده پورت MCP23017 آشنا شدیم و در محیط آردوینو آن را راه اندازی کردیم. حالا میتوانید در پروژه هایتان از این قابلیت مفید و کاربردی استفاده کنید. از این که تا انتهای این مطلب آموزشی با ما همراه بودید از شما متشکریم.