مقدمه
فرض کنید میخواهید یک ماتریس LED با تعداد 4x4x4 بسازید. برای کنترل دقیق هر یک از LED ها، به 64 عدد پایه دیجیتال نیاز دارید. حال اگر بخواهید میکروکنترلری را انتخاب کنید که این تعداد پایه دیجیتال خروجی را داشته باشد، بسیار پرهزینه میشود. بنابراین راه مناسب آن است که از طریقی بتوانید تعداد پایه های دیجیتال میکروکنترلر را افزایش دهید.
افزایش تعداد پایههای دیجیتال میکروکنترلر ها از جمله موضوعات جذاب و کاربردی میباشد. در بسیاری از کاربردها برای صرفه جویی در هزینه و به جای استفاده از یک میکروکنترلر گرانتر، میتوانیم با استفاده از آیسی شیفت رجیستر 74HC595 تعداد پایههای میکروکنترلر را افزایش دهیم. یکی از کاربردهای مهم آن در پروژههایی است که از تعداد زیادی LED استفاده میشود. شما توسط این آموزش میتوانید LED های زیادی را تنها با تعداد بسیار کمی از پایههای دیجیتال آردوینو کنترل کنید.
گاهی اوقات تعداد سنسورها و ماژول های زیادی به میکروکنترلر شما متصل است و شما نمیتوانید پایه های زیادی را برای اتصال به LED ها و سوئیچ های خود اختصاص دهید. در این صورت بهترین راهکار به کار بردن آیسی shift-register و افزایش تعداد پایههای دیجیتال میکروکنترلر میباشد.
در این آموزش، دو هدف را دنبال میکنیم:
- افزایش تعداد پایه دیجیتال میکروکنترلر
- صرفه جویی در هزینه و قابلیت استفاده از میکروکنترلر های ارزان تر با تعداد پایه کمتر
با به کار بردن یک شیفت رجیستر میتوان 3 عدد پایه میکروکنترلر را به 8 عدد افزایش داد. در حالی که استفاده از دو عدد shift register به صورت سری، قابلیت افزایش پایه ها تا 16 عدد را نیز فراهم میکند.
آنچه در این آموزش یاد میگیرید
در این آموزش ابتدا در مورد آیسی شیفت رجیستر 74HC595 صحبت کرده و نحوه عملکرد آن را بیان میکنیم. سپس توسط 3 پایه آردوینو و با یک عدد شیفترجیستر، 8 عدد LED را در حالت های مختلف کنترل میکنیم. در ادامه با اتصال دو عدد شیفت رجیستر 74HC595 به صورت سری و اشغال تنها سه پایه از آردوینو، 16 عدد LED را کنترل میکنیم.
از آردوینو UNO به عنوان میکروکنترلر بهره میبریم و 3 عدد پایه دیجیتال آن را جهت کنترل LED ها استفاده میکنیم.
آی سی شیفت رجیستر 74HC595 چیست؟
شیفترجیستر ها معمولا در مدارات برای انتقال و ذخیره دیتاهای باینری به کار برده میشوند. این آیسی ها دیتاهای سری و موازی را به یکدیگر تبدیل میکنند. بر اساس این توضیح، شیفترجیستر ها به 4 دسته زیر تقسیم میشوند:
- SIPO: دیتای ورودی به صورت سریال و دیتای خروجی به صورت موازی میباشد.
از این دسته زمانی استفاده میشود که میخواهیم تعدادی خروجی را توسط دیتای سریال کنترل کنیم. - PISO: دیتای ورودی به صورت موازی و دیتای خروجی به صورت سریال میباشد.
زمانی که بخواهیم تعدادی ورودی مانند سوئیچ را به دیتای سریال تبدیل کنیم. - PIPO و SISO: ورودی و خروجی این دو دسته مشابه هم میباشد. PIPO دارای ورودی و خروجی موازی و SISO دارای ورودی و خروجی سریال هستند. عملکرد این دو مدل مانند بافر است و برای نگهداری دیتا در یک زمان مشخص استفاده میشود.
در این آموزش دیتای میکروکنترلر به صورت سری ارسال میگردد. همچنین در خروجی، تعدادی LED را به صورت مستقل کنترل خواهیم کرد. بنابرین باید از مدل SIPO استفاده کنیم. آیسی شیفترجیستر 74HC595 از این دسته میباشد.
معرفی پایه های (پین اوت) آی سی 74HC595
پین اوت این ماژول را در تصویر زیر مشاهده میکنید:
پایه های این آی سی به شرح زیر میباشد:
- GND: زمین الکتریکی
- VCC: تغذیه – 5 ولت
- SER: پایه دیتای سریال – توسط این پین، دیتا به صورت بیت به بیت به سمت shift-register ارسال میگردد. بیت صفر شیفترجیستر به این پایه وصل میباشد.
- SRCLK: پایه کلاک شیفترجیستر – با هر بار کلاک با لبه بالارونده، بیت ها درون شیفترجیستر یک واحد شیفت پیدا میکنند.
- RCLK: پایه کلاک رجیستر latch – با هر بار HIGH شدن این پایه، مقادیر 8 بیت شیفترجیستر از طریق رجیستر latch بر روی خروجی قرار میگیرد. پایه های خروجی رجیستر latch به خروجی های آیسی (Q0-Q7) متصل هستند.
- OE: فعالسازی خروجی – این پایه Active Low میباشد. زمانی که این پایه LOW باشد، خروجی ها قابل دسترس هستند. وقتی این پایه HIGH میشود، خروجی ها غیرفعال شده و High Impedance میشوند.
- Q0-Q7: خروجیها – 8 بیت خروجی آیسی که میتوانند به LED و یا هر تجهیز دیگری متصل شوند.
- SRCLR: پایه clear شیفترجیستر – این پایه Active Low میباشد. زمانی که این پین Low شود، تمام بیت های شیفترجیستر صفر میشوند. این پایه در حالت عادی، HIGH میباشد.
’Q7: پین 7 خروجی – این پین برای اتصال دو یا چند shift-register به یکدیگر تعبیه شدهاست. بدین صورت که پایه دیتای آردوینو به پایه SER اولین شیفرجیستر و پایه ’Q7 آن نیز به پایه SER شیفترجیستر دوم متصل میگردد. بدین ترتیب میتوان 2 یا چند عدد شیفت رجیستر را به صورت سری به هم متصل کرد و تعداد خروجی ها را به 16، 24 و … ارتقا داد.
در ادامه میتوانید دیتاشیت این آیسی را دانلود کنید.
74HC595 datasheet
نحوه عملکرد آی سی شیفت رجیستر 74HC595
میتوان گفت که هر آیسی 74HC595 شامل دو رجیستر میباشد:
- شیفترجیستر: از طریق این رجیستر دیتاهای ورودی به صورت بیت به بیت از حالت سریال به صورت موازی تبدیل میشوند. پایه SRCLK، کلاک این رجیستر میباشد. با هر پالس بالارونده، دیتا یک بیت در این شیفت رجیستر شیفت پیدا میکند. توسط پین SRCLR نیز همه بیت های این رجیستر صفر میشوند.
- رجیستر latch: سپس بیت ها توسط این رجیستر بر روی پایه های خروجی قرار میگیرند. پایه RCLK کلاک این رجیستر میباشد. با هر بار HIGH شدن این پالس، بیتهای دیتا بر روی پایه های خروجی قرار میگیرند.
انتقال دیتا توسط آیسی 74HC595 شامل دو مرحله میشود:
مرحله اول: انتقال یک بایت دیتا از میکرو به شیفترجیستر
انتقال یک بایت دیتا به صورت بیت به بیت انجام میشود. بدین صورت که به ازای ارسال هر بیت دیتا، کلاک بایستی یک پالس تولید کند. برای مثال برای انتقال 8 بیت دیتا، به 8 پالس کلاک نیاز داریم.
برای مثال فرض کنید میخواهیم دیتایی با اندازه باینری 11010100 را ارسال کنیم:
مرحله دوم: قرار گرفتن دیتا بر روی پایههای خروجی توسط رجیستر latch
پس از اینکه 8 بیت دیتا بر روی خروجی قرار گرفت، با ارسال یک پالس توسط کلاک رجیستر latch، دیتای ارسال شده بر روی پایههای خروجی آیسی 74HC595 قرار میگیرد.
لوازمی که به آن احتیاج دارید
در ادامه به قطعات و لوازم زیر نیاز دارید:
سخت افزارهای موردنیاز
نرمافزارهای موردنیاز
افزایش پایههای دیجیتال آردوینو از 3 به 8 توسط یک شیفت رجیستر 74HC595
توسط هر یک از آیسی های شیفترجیتر 74HC595 میتوانید 3 عدد پایه دیجیتال آردوینو را به 8 عدد افزایش دهید. حال میخواهیم 8 عدد LED را توسط 3 پایه آردوینو کنترل کنیم. در حالت نرمال برای کنترل 8 عدد LED به 8 پایه دیجیتال آردوینو نیاز داریم. اما با وجود این آیسی، این کار را با 3 عدد پایه دیجیتال کنترل میکنیم.
گام اول: سیمبندی مدار
ابتدا مدار عملی آن را بر روی بردبورد آماده کرده و با توجه به پین اوت شیفترجیستر 74HC595 ، اتصالات را مانند زیر برقرار میکنیم:
نکات زیر در رابطه با مدار بالا قابل توجه میباشد:
- پایه SRCLR که عمل ریست را انجام میدهد، به VCC متصل شده است. (به این علت که هیچ گاه ریست نشود)
- پایه OE جهت کنترل نور LED ها به پایه شماره 6 آردوینو متصل شده است.
- تغذیه آیسی را به همان 5 ولت آردوینو متصل کردیم.
- از مقاومت های 330 اهم برای کاهش جریان عبوری از LEDها استفاده شده است.
در ضمن 4 پایه کنترلی آیسی 74HC595 مانند زیر به آردوینو متصل شدهاند:
- پایه کلاک رجیستر latch (RCLK) به پایه شماره 10 آردوینو
- پایه دیتای سریال ورودی (SER) به پایه شماره 8 آردوینو
- پایه کلاک شیفترجیستر (SRCLK) به پایه شماره 9 آردوینو
- پایه فعالسازی خروجی (OE) به پایه شماره 6 آردوینو
گام دوم: کد برنامه
پس از اینکه مدار بالا را آماده کردید، آردوینو را به کامپیوتر متصل کرده و برنامه زیر را بر روی آن آپلود کنید:
/*
Made on 13 July 2021
By Amirmohammad Shojaei
Home
*/
int latchPin = 10; // Latch pin of 74HC595 is connected to Digital pin 10
int clockPin = 9; // Clock pin of 74HC595 is connected to Digital pin 9
int dataPin = 8; // Data pin of 74HC595 is connected to Digital pin 8
int j;
int OE = 6; // Output Enable pin of 74HC595 is connected to Digital pin 8
byte leds = 0; // Variable to hold the pattern of which LEDs are currently turned on or off
void setup()
{
// Set all the pins of 74HC595 as OUTPUT
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(OE, OUTPUT);
}
void loop() {
state_1();
state_1(); //play state_1 for 3 times
state_1();
delay(300);
state_2();
state_2(); //play state_2 for 3 times
state_2();
delay(300);
state_3();
state_3(); //play state_3 for 3 times
state_3();
delay(300);
state_4();
state_4(); //play state_4 for 3 times
state_4();
delay(300);
}
/*
updateShiftRegister() - This function sets the latchPin to low, then calls the Arduino function 'shiftOut' to shift out contents of variable 'leds' in the shift register before putting the 'latchPin' high again.
*/
void updateShiftRegister()
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, leds);
digitalWrite(latchPin, HIGH);
}
/*
this function is used to control LED light in state_4 function
*/
void brightness(int b) {
analogWrite(OE, 255 - b);
}
void state_1() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 8; i++)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
leds = 0;
}
for (int i = 6; i > -1; i--)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
leds = 0;
updateShiftRegister();
}
}
void state_2() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 8; i++)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
}
for (int i = 7; i > -1; i--)
{
bitClear(leds, i);
updateShiftRegister();
delay(50);
}
}
void state_3() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 4; i++)
{
j = 7 - i; // 0-7/1-6/2-5/3-4
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
bitSet(leds, j);
updateShiftRegister();
delay(100);
}
for (int i = 0; i < 4; i++)
{
j = 7 - i; // 0-7/1-6/2-5/3-4
bitClear(leds, i); // Set the bit that controls that LED in the variable 'leds'
bitClear(leds, j);
updateShiftRegister();
delay(100);
}
}
void state_4() {
brightness(255);
leds = 0b11111111;
updateShiftRegister();
for (byte y = 255; y > 0; y--)
{
brightness(y);
delay(5);
}
for (byte z = 0; z < 255; z++)
{
brightness(z);
delay(5);
}
leds = 0;
updateShiftRegister();
}
توسط برنامه بالا، 8 عدد LED با آیسی 74HC595 کنترل میشود. 4 حالت برای روشنایی LED ها در نظر گرفته ایم که در حلقه اصلی به ترتیب هر کدام سه مرتبه اجرا میشوند.
برای قرار دادن دیتا بر روی خروجی آیسی 74HC595 از تابع updateshiftregister() بهره برده ایم. در این تابع از دستور shiftOut() برای انتقال سریال دیتا از آردوینو به سمت شیفت رجیستر 74HC595 استفاده میشود.
چند نکته در رابطه با دستور shiftOut:
- شماره پایه های کلاک شیفترجیستر و سریال دیتا بایستی وارد شود.
- پارامتر سوم نشان میدهد که ارسال سریال دیتا از سمت LSB (کم ارزشترین بیت) باشد و یا MSB (پرارزش ترین بیت).
- پارامتر آخر نیز سریالی است که قرار است ارسال شود.
یک تابع نیز به نام brightness() برای تنظیم روشنایی LED ها تعریف شده است:
- میزان روشنایی LEDها با تغییر پین OE از 0 تا 255 قابل تنظیم میباشد.
- به دلیل اینکه پایه OE دارای وضعیت Active Low میباشد، باید مقدار آن برای حداکثر روشنایی 0 باشد.
- دقت شود که پین OE به یکی از پایه های PWM آردوینو متصل گردد.
هر یک از 4 حالت بیان شده، در یک تابع جداگانه تعریف شده است که در ادامه به توضیح هر یک میپردازیم:
State_1
در این حالت به طور همزمان فقط یکی از LED ها روشن میشود. LED ها به ترتیب از اول تا آخر روشن شده و سپس زمانی که به انتها رسید، دوباره به همان ترتیب برمیگردد. کد آن به شکل زیر میباشد:
void state_1() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 8; i++)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
leds = 0;
}
for (int i = 6; i > -1; i--)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
leds = 0;
updateShiftRegister();
}
}
ابتدا روشنایی را در حالت Max قرار میدهیم. قبل از شروع کار اصلی، متغیر سریال دیتا (leds) را برابر صفر قرار داده و آن را توسط تابع updateshiftregister() بر روی خروجی قرار میدهیم. در حلقه for، ابتدا بیت های سریال را به ترتیب از راست به چپ برابر 1 قرار میدهیم.این کار توسط دستور bitSet() انجام میشود. زمانی که به انتها رسید، همین فرآیند را از چپ به راست تکرار میکنیم. وضعیت LED ها در این حالت به صورت زیر میباشد:
State_2
در حالت دوم LED ها از راست به چپ روشن میشوند و با روشن شدن LED های بعدی، LED های قبلی نیز روشن باقی میمانند. زمانی که به انتها رسید، همه ی LED ها روشن شدهاند. سپس به همین ترتیب LED ها از سمت چپ شروع به خاموش شدن میکنند. وضعیت روشنایی LED ها در این حالت به صورت زیر میباشد:
void state_2() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 8; i++)
{
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
updateShiftRegister();
delay(50);
}
for (int i = 7; i > -1; i--)
{
bitClear(leds, i);
updateShiftRegister();
delay(50);
}
}
ابتدا روشنایی را در حالت Max قرار میدهیم. قبل از شروع کار اصلی، متغیر سریال دیتا (leds) را برابر صفر قرار داده و آن را توسط تابع updateshiftregister() بر روی خروجی قرار میدهیم. در اولین حلقه for، مانند حالت قبلی توسط دستور bitSet()، بیت های متغییر leds را به ترتیب از LSB به MSB مساوی با یک قرار میدهیم. تفاوت آن با حالت اول در این است که در هر مرحله کل بیت ها را صفر نمیکنیم. در حلقه دوم for هم توسط دستور bitClear() از سمت چپ شروع به خاموش کردن LED ها میکنیم. وضعیت روشنایی LED ها در این حالت به صورت زیر میباشد.
State_3
در این وضعیت، LED های 0 با 7 ، 1 با 6، 2 با 5 و 3 با 4 همزمان روشن میشوند. برنامه آن به صورت زیر است:
void state_3() {
brightness(255);
leds = 0; // Initially turns all the LEDs off, by giving the variable 'leds' the value 0
updateShiftRegister();
delay(50);
for (int i = 0; i < 4; i++)
{
j = 7 - i; // 0-7/1-6/2-5/3-4
bitSet(leds, i); // Set the bit that controls that LED in the variable 'leds'
bitSet(leds, j);
updateShiftRegister();
delay(100);
}
for (int i = 0; i < 4; i++)
{
j = 7 - i; // 0-7/1-6/2-5/3-4
bitClear(leds, i); // Set the bit that controls that LED in the variable 'leds'
bitClear(leds, j);
updateShiftRegister();
delay(100);
}
}
روشنایی را در حالت Max قرار میدهیم. قبل از شروع کار اصلی، متغیر سریال دیتا (leds) را برابر صفر قرار داده و آن را توسط تابع updateshiftregister() بر روی خروجی قرار میدهیم. در ادامه دو متغیر i و j را تعریف کرده و توسط این دو متغیر طرح مدنظر خود را به وجود میآوریم:
State_4
در وضعیت آخر میخواهیم میزان روشنایی LEDها را کنترل کنیم.
void state_4() {
brightness(255);
leds = 0b11111111;
updateShiftRegister();
for (byte y = 255; y > 0; y--)
{
brightness(y);
delay(5);
}
for (byte z = 0; z < 255; z++)
{
brightness(z);
delay(5);
}
leds = 0;
updateShiftRegister();
}
در این حالت ابتدا LED ها را توسط مقدار باینری 0b11111111 روشن میکنیم. سپس در اولین حلقه for و توسط تابع brightness نور LEDها را به تدریج کاهش داده تا به صفر برسند. در حلقه دوم همین عمل را برعکس کرده و نور LED ها را به حداکثر میرسانیم. وضعیتLED ها مانند کلیپ زیر تغییر میکنند:
گام سوم: مشاهده خروجی
4 حالت مختلف LED ها به طور مجزا بررسی شدند. حال خروجی نهایی بدین صورت است که 4 حالت پشت سر هم و به صورت متوالی اجرا شوند. خروجی نهایی به صورت زیر میباشد:
افزایش پایههای دیجیتال آردوینو از 3 به 16 با دو شیفت رجیستر 74HC595
اکنون در این قسمت میخواهیم توسط 2 عدد شیفترجیستر 74HC595 که به صورت سری به هم متصل شدهاند، 16 عدد LED را به طور مستقل کنترل کنیم. برای این کار از 3 پایه آردوینو استفاده میکنیم.
گام اول: سیمبندی مدار
قبل از هر کاری ابتدا باید اتصالات مدار را طبق شکل زیر ببندید:
توسط دو شیفترجیستر 74HC595، شانزده عدد LED را به صورت مستقل کنترل میکنیم. هر 8 عدد LED به یک شیفرجیستر 74HC595 متصل شده اند.
چند نکته در رابطه با کنترل همزمان دو shift-register:
- پین های کلاک دیتای شیفترجیستر (SRCLK) و کلاک latch (RCLK) بین دو شیفت رجیستر مشترک بوده و به هم متصل میشوند. SRCLK از طریق پایه 12 آردوینو و RCLK از طریق پایه شماره 8 آردوینو کنترل میشوند.
- پایهی شماره 11 آردوینو به پایه سریال دیتای SER شیفترجیستر اول متصل میگردد.
- سریال دیتای شیفترجیستر دوم از طریق اتصال سری با شیفترجیستر اول فراهم میشود. بدین ترتیب که برای برقراری ارتباط سریال بین دو شیفترجیستر، پایه ’Q7 از شیفترجیستر اول را به پایه سریال SER شیفترجیستر دوم متصل میکنیم.
- در ضمن پایه های SRCLR را به VCC و پایههای OE را به GND وصل کرده ایم.
- 8 سری اول LEDها به شیفترجیستر اول و 8 سری دوم LEDها به شیفت رجیستر دوم متصل شدهاند.
- از مقاومت 330 اهم برای محدود کردن جریان LEDها استفاده شده است.
گام دوم: کد برنامه
پس از کامل کردن اتصالات مدار فوق، برنامه زیر را بر روی آردوینو Upload کنید:
/*
Modified on 13 July 2021
By Amirmohammad Shojaei
Home
based on www.Arduino.cc Example
*/
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
//Pin connected to DS of 74HC595
int dataPin = 11;
//holders for infromation you're going to pass to shifting function
byte dataRED;
byte dataGREEN;
byte dataArrayRED[33];
byte dataArrayGREEN[33];
void setup() {
//set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
Serial.begin(9600);
//Arduino doesn't seem to have a way to write binary straight into the code
//so these values are in HEX. Decimal would have been fine, too.
dataArrayRED[0] = 0b11111111;
dataArrayRED[1] = 0b11111110;
dataArrayRED[2] = 0b11111100;
dataArrayRED[3] = 0b11111000;
dataArrayRED[4] = 0b11110000;
dataArrayRED[5] = 0b11100000;
dataArrayRED[6] = 0b11000000;
dataArrayRED[7] = 0b10000000;
dataArrayRED[8] = 0b00000000;
dataArrayRED[9] = 0b00000000;
dataArrayRED[10] = 0b00000000;
dataArrayRED[11] = 0b00000000;
dataArrayRED[12] = 0b00000000;
dataArrayRED[13] = 0b00000000;
dataArrayRED[14] = 0b00000000;
dataArrayRED[15] = 0b00000000;
dataArrayRED[16] = 0b00000000;
dataArrayRED[17] = 0b00000000;
dataArrayRED[18] = 0b00000000;
dataArrayRED[19] = 0b00000000;
dataArrayRED[20] = 0b00000000;
dataArrayRED[21] = 0b00000000;
dataArrayRED[22] = 0b00000000;
dataArrayRED[23] = 0b00000000;
dataArrayRED[24] = 0b00000000;
dataArrayRED[25] = 0b00000000;
dataArrayRED[26] = 0b10000000;
dataArrayRED[27] = 0b11000000;
dataArrayRED[28] = 0b11100000;
dataArrayRED[29] = 0b11110000;
dataArrayRED[30] = 0b11111000;
dataArrayRED[31] = 0b11111100;
dataArrayRED[32] = 0b11111110;
dataArrayRED[33] = 0b11111111;
//Arduino doesn't seem to have a way to write binary straight into the code
//so these values are in HEX. Decimal would have been fine, too.
dataArrayGREEN[0] = 0b11111111;
dataArrayGREEN[1] = 0b11111111;
dataArrayGREEN[2] = 0b11111111;
dataArrayGREEN[3] = 0b11111111;
dataArrayGREEN[4] = 0b11111111;
dataArrayGREEN[5] = 0b11111111;
dataArrayGREEN[6] = 0b11111111;
dataArrayGREEN[7] = 0b11111111;
dataArrayGREEN[8] = 0b11111111;
dataArrayGREEN[9] = 0b11111110;
dataArrayGREEN[10] = 0b11111100;
dataArrayGREEN[11] = 0b11111000;
dataArrayGREEN[12] = 0b11110000;
dataArrayGREEN[13] = 0b11100000;
dataArrayGREEN[14] = 0b11000000;
dataArrayGREEN[15] = 0b10000000;
dataArrayGREEN[16] = 0b00000000;
dataArrayGREEN[17] = 0b10000000;
dataArrayGREEN[18] = 0b11000000;
dataArrayGREEN[19] = 0b11100000;
dataArrayGREEN[20] = 0b11110000;
dataArrayGREEN[21] = 0b11111000;
dataArrayGREEN[22] = 0b11111100;
dataArrayGREEN[23] = 0b11111110;
dataArrayGREEN[24] = 0b11111111;
dataArrayGREEN[25] = 0b11111111;
dataArrayGREEN[26] = 0b11111111;
dataArrayGREEN[27] = 0b11111111;
dataArrayGREEN[28] = 0b11111111;
dataArrayGREEN[29] = 0b11111111;
dataArrayGREEN[30] = 0b11111111;
dataArrayGREEN[31] = 0b11111111;
dataArrayGREEN[32] = 0b11111111;
dataArrayGREEN[33] = 0b11111111;
//function that blinks all the LEDs
//gets passed the number of blinks and the pause time
blinkAll_2Bytes(2, 500);
}
void loop() {
for (int j = 0; j < 34; j++) {
//load the light sequence you want from array
dataRED = dataArrayRED[j];
dataGREEN = dataArrayGREEN[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, dataGREEN);
shiftOut(dataPin, clockPin, dataRED);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(30);
}
}
// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low
//internal function setup
int i = 0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
//for each bit in the byte myDataOut�
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i = 7; i >= 0; i--) {
digitalWrite(myClockPin, 0);
//if the value passed to myDataOut and a bitmask result
// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1 << i) ) {
pinState = 1;
}
else {
pinState = 0;
}
//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll_2Bytes(int n, int d) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(200);
for (int x = 0; x < n; x++) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(d);
}
}
نخست پایه های خروجی آردوینو را مشخص کرده و متغیرهایی را که برای انتقال دیتا نیاز داریم تعریف میکنیم. متغیرهای RED برای شیفترجیستر اول و متغیرهای GREEN برای دومین شیفترجیستر تعریف شدهاند. در این برنامه LEDها 33 حالت پشت سر هم را طی میکنند. تعداد آرایه ها نیز به همین تعداد در نظر گرفته شده اند.
در حلقه Setup حالت هایی که میخواهید LEDها روشن و خاموش شوند را مشخص میکنید. مقادیر به صورت باینری تعریف شدهاند. بیت 1 نشان دهنده روشن شدن LED و بیت صفر هم بیانگر خاموش شدن آن میباشد. هر بایت شامل 8 بیت میباشد. شما توسط هر یک از این 8 بیت میتوانید 8 عدد LED را کنترل کنید.
در انتهای این حلقه، تابع blinkAll_2Bytes() فراخوانی میشود. توسط این حلقه در ابتدای اجرای برنامه، همهی LEDها دو بار چشمک میزنند.
نکاتی در رابطه با این تابع:
- این تابع دارای دو ورودی میباشد:
n : تعداد چشمک
d : زمان تاخیر
- با تغییر n و d میتوانید تعداد چشمک زدن و تاخیر زمانی آن را مشخص کنید.
در حلقه اصلی 33 حالت LEDها به ترتیب بر روی پایه سریال قرار میگیرند. این کار توسط تابع shiftOut() انجام میشود. این تابع، دیتای تعریف شده را به سمت شیفت رجیسترها ارسال میکند. دقت شود که تابع shiftOut() ابتدا برای LEDهای سری دوم (GREEN) و سپس برای LEDهای سری اول (RED) به کار برده میشود.
همانطور که مشاهده میشود قبل از این کار، پایه latch را برابر صفر قرار داده تا در حین استفاده از تابع shiftOut() مقادیر بر روی خروجی شیفترجیستر ها ظاهر نگردد. اما بعد از اینکه سریال های دیتا توسط تابع shiftOut() بر روی شیفترجیستر ها قرار گرفت، با قرار دادن کلاک latch ، مقادیر سریال هر دو رجیستر بر روی خروجی هایشان ظاهر میگردد.
حال کمی در مورد تابع مهم shiftOut() توضیح می دهیم:
- این تابع دارای 3 ورودی میباشد. دو ورودی myDataPin و myClockPin همان شماره پایه های کلاک و سریال شیفترجیسر میباشند. متغییر myDataOut نیز سریال دیتایی است که میخواهیم به سمت شیفترجیستر ارسال گردد.
- این تابع، سریال دیتا را از سمت بیت پرارزش (MSB) به سمت شیفت رجیستر ارسال میکند. بدین ترتیب سریال دیتا بیت به بیت به سمت شیفترجیستر ارسال میگردد.
- به همراه ارسال هر بیت، کلاک نیز با یک لبه بالارونده این عملیات را تکمیل میکند.
گام سوم: مشاهده خروجی
پس از آپلود کردن برنامه، LEDها باید با حالتهای زیر روشن و خاموش شوند:
همانطور که مشاهده میشود، ابتدا همهی LEDها روشن شده و به ترتیب از سمت راست و از LEDهای شیفترجیستر اول شروع به خاموش شدن میکنند. زمانی که همهی LEDها خاموش شدند، به همین منوال LEDها از سمت چپ شروع به روشن شدن میکنند.
یک گام جلوتر
پس از انجام کامل این آموزش، موضوعات و طرح های زیر را میتوانید به عنوان گام بعدی انجام دهید:
- ایجاد طرح های جالب و جدیدتر برای LEDها
- تنظیم نور LEDها برای تعداد 16 عدد
- استفاده از رله به جای LEDها و روشن و خاموش کردن لامپ هایی با توان بالاتر توسط این تکنیک
- به کاربردن LEDهای RGB برای ایجاد تنوع بیشتر
- تبدیل دیتاهای موازی به سری توسط آیسی74HC165
Comments (8)
سلام ممنون از آموزش خوبتون
کدهای مربوط به طرح اولی که گذاشتید من کپی کردم در محیط برنامه ولی ارور state 1 و هر چی state دیگه که بود میده و میگه تعریف نشده
مشکل از کجاست
با سلام
اگر در محیط Arduino IDE اجرا میکند ارور نخواهید گرفت.
اگر در محیط Platform IO اجرا میگیرید باید ترتیب فانکشن ها را رعایت کنید.
در این کد کافی است کل فانکشن void loop را به انتهای کد انتقال بدهید تا درست شود.
سلام
ممنون از آموزشتون
برای کنترل ال ای دی های با ولتاژ بالاتر مثلا 220 ولت dc چطور میتونم از آردواینو استفاده کنم؟
من از رله استفاده کردم ولی سرعت رله پایین هست و برای نورپردازی جواب نمیده و همچنین ایجاد صدا می کنه
با سلام
خروجی ها را با استفاده از ماسفت قدرت باید تقویت کنید تا بتواند ولتاژ مورد نیاز شما را تامین کند.
سلام با احترام وقت بخیر خسته نباشید
◇برای وصل کردن تقریبا ۱۲ عدد IC 74HC595 ،چطوری سیم بندی مدار و با چه تغییری در برنامه در آردوینو uno نصب و راه اندازی کنیم
◇لطفا.بی زحمت . خواهشمندیم راهنمایی کنید
تا بتونیم از ۱۲ عدد IC استفاده و راه اندازه کنیم
◇با تشکر از تمامی لطف ، زحمات و هم آموزش های بسیار عالی شما ممنونیم ◇
با سلام
در بخش 2 شیفت رجیستر توضیح داده شده است.
2 عدد از سیم ها مشترک هستند.
و یک سیم از خروجی IC اول به ورودی IC دوم میرود و کافی است از خروجی IC دوم به ورودی IC سوم بروید.
و همین مورد را تکرار کنید تا به هر تعدادی که میخواهید بروید.
همچنین در کد نیز باید تکرار توالی رو انجام بدهید.
سلام وقت بخیر
چطور میتونم ترتیب روشن و خاموش کردن ال ای دی هارو بصورت تصادفی اجرا کنم؟ مثلا 16 ال ای دی داریم و میخوام بعنوان مثال شماره 3،4،8،11،13و15 رو روشن کنم
وسوال دیگه اینکه از بین ال ای دی های گفته شده بازهم بعنوان مثال شماره 8و13 رو خاموش کنم و بقیه روشن بمونن؟
ممنون میشم راهنمایی کنید یا مرجعی رو معرفی کنید
مرسی
با سلام
در صورتی که بخش 4 ام کد را مشاهده کنید
brightness(255);
leds = 0b11111111;
updateShiftRegister();
شما می توانید مقدار leds را با قرار دادن این 1 ها تایین کنید که خاموش باشن یا روشن.
برای رندوم شدن نیز می توانید از دستور random استفاده کنید.