بررسی WS2812 LED و راه اندازی آن با آردوینو
در این بخش به بررسی روش سیگنال دهی این آی سی خواهیم پرداخت. در ابتدا نیز لازم به ذکر است که با توجه به اینکه برای استفاده از این آی سی از کتابخانه های آماده بهره خواهیم گرفت لذا درک عمیق این مباحث ضروری نیست و صرفا جهت آشنایی با این ساختار مطرح می شود.
همان گونه که گفته شد برای اتصال این آی سی ها و تشکیل یک زنجیره باید دیتا از پایه ورودی اولین آی سی وارد و از پایه خروجی اولین آی سی به بعدی تا انتها اتصال یابد. به تصویر زیر توجه نمائید:
برای کنترل هر آی سی از 24 بیت استفاده می شود که 8 بیت برای هر رنگ قرمز، سبز و آبی استفاده می شود که در واقع امکان 256 حالت نوری(Grayscale) را ممکن می سازد. تصویر زیر ترتیب ارسال این سیگنال را نمایش می دهد:
این سیگنال ها باید به صورت پشت سر هم و به صورت سریال ارسال شود یعنی با فرض سه پیکسل به صورت پشت سر هم، یک بسته 24 بیتی به ازای هر پیکسل ارسال می شود. هر پیکسل اولین 24 بیت دریافتی را به خود اختصاص داده و باقی بیت های دریافتی را به پیکسل های بعدی منتقل می نماید. این روند تا آخرین پیکسل ادامه می یابد. با یک سیگنال ریست نیز کل آی سی های زنجیره خاموش می شود. در تصویر زیر شیوه اجرایی این فرآیند مشاهده می شود:
با توجه به اینکه برای ارتباط و انتقال اطلاعات از یک خط دیتا(سریال) استفاده شده است لذا از روش خاصی برای تعیین صفر و یک منطقی و همچنین سیگنال ریست استفاده شده است. در این حالت برای نمایش صفر و یک منطقی از زمان بندی های خاص بهره گرفته شده است. یعنی با ست و ریست شدن خط دیتا به زمان معین سیگنال معرف صفر، یک و ریست خواهد بود.
همان گونه که قبلا نیز گفته شد این آی سی دارای دو مد کاری 400 کیلو هرتز(Low Speed) و 800 کیلوهرتز (High Speed) می باشد. با توجه به اینکه زمان بندی های سیگنال با توجه به مد کاری تغییر می کند و همچنین سرعت بالاتر مد پر سرعت و متداول تر بودن این مد کاری، زمان بندی ها بر اساس آن قرار داده می شود: (لازم به ذکر است زمان بندی های مد 400 کیلو دو برابر جدول زیر است)
روند ارسال سیگنال بدین صورت است که در ابتدا یک سیگنال ریست از طریق خط دیتا ارسال می شود. در این حالت حافظه کل چیپ ها پاک (Clear) می شود. بعد از این حالت سیگنال های ارتباطی با زمان بندی ها مناسب ارسال می گردد برای مثال با وجود دو آی سی پشت سر هم و به جهت رنگ سفید و سبز باید ابتدا 0xFFF (رنگ سفید) و سپس 0x0F0 (رنگ سبز خالص) به صورت پشت هم ارسال گردد.
نصب کتابخانه NEOPIXEL در نرم افزار آردوینو
برای راه اندازی ریسه های WS2812 در آردوینو می توانید از کتابخانه NEOPIXEL استفاده کنید برای این منظور کافی است در قسمت manage libraries عبارت NEOPIXEL جست و جو و نصب کنید.
محاسبه توان مصرفی:
هر کدام از LED های RGB تقربیاً 60mA جریان در ولتاژ 5v مصرف می کند.پس توان مصرفی هر کدام از این LED ها برابر است با:
5V×60mA=0.3 wat
اگر از یک زنجیر یک متری با 60 عدد از این LED ها در پروژه خود استفاده کنید به یک منبع تغذیه ۵ولت با توانایی تولید حداقل A3.6 آمپر جریان نیاز دارید.
نکته مهم: برای راه اندازی WS2812 به هیچ عنوان از پین های 5V و GND روی برد آردوینو استفاده نکنید.چون اگر بخواهید از پورت USB کامپیوتر خود این جریان را تامین کنید هم پورت USBو هم برد آردوینو آسیب خواهد دید.پین های 5V و GND باید به یک منبع تغدیه خارجی وصل شود.
نحوه اتصال به برد آردوینو:
انتخاب WS2812 مناسب با پروژه
این نوع LED ها هم در یه صورت تکی و هم به صورت ماژول در فروشگاه موجود می باشد که می توانید با توجه به نیاز خود یکی را انتخاب کنید.
نمونه کد برای تست WS2812:
#include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> #endif #define PIN 6 // Parameter 1 = number of pixels in strip // Parameter 2 = Arduino pin number (most are valid) // Parameter 3 = pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800); // IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across // pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input // and minimize distance between Arduino and first pixel. Avoid connecting // on a live circuit...if you must, connect GND first. void setup() { // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket #if defined (__AVR_ATtiny85__) if (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // End of trinket special code strip.begin(); strip.show(); // Initialize all pixels to 'off' } void loop() { // Some example procedures showing how to display to the pixels: colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color(0, 255, 0), 50); // Green colorWipe(strip.Color(0, 0, 255), 50); // Blue //colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW // Send a theater pixel chase in... theaterChase(strip.Color(127, 127, 127), 50); // White theaterChase(strip.Color(127, 0, 0), 50); // Red theaterChase(strip.Color(0, 0, 127), 50); // Blue rainbow(20); rainbowCycle(20); theaterChaseRainbow(50); } // Fill the dots one after the other with a color void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); delay(wait); } } void rainbow(uint8_t wait) { uint16_t i, j; for(j=0; j<256; j++) { for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i+j) & 255)); } strip.show(); delay(wait); } } // Slightly different, this makes the rainbow equally distributed throughout void rainbowCycle(uint8_t wait) { uint16_t i, j; for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel for(i=0; i< strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); } strip.show(); delay(wait); } } //Theatre-style crawling lights. void theaterChase(uint32_t c, uint8_t wait) { for (int j=0; j<10; j++) { //do 10 cycles of chasing for (int q=0; q < 3; q++) { for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, c); //turn every third pixel on } strip.show(); delay(wait); for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); //turn every third pixel off } } } } //Theatre-style crawling lights with rainbow effect void theaterChaseRainbow(uint8_t wait) { for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel for (int q=0; q < 3; q++) { for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on } strip.show(); delay(wait); for (uint16_t i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); //turn every third pixel off } } } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); }
توضیح تعدادی از توابع:
begin
این دستور برای آماده سازی نوار LED و بصورت زیر اعمال میشه:
Strip.begin();
setPixelColor
بوسیله این دستور میتونیم مشخص کنیم که هر ال ای دی چه رنگی باشه و بصورت زیر فراخوانیش می کنیم:
Strip.setPixelColor(n,r,g,b);
Color
این تابع به شکل زیر فراخوانی میشه :
Unit32_t col = Strip.Color(r,g,b);
سه تا مقداره رنگ رو بهش میدیم و یه متغیر 32 بیتی که رنگ رو در بر داره تحویل می گیریم.
clear
این دستور همه ال ای دی ها رو خاموش می کند.
Strip.clear();
setBrightness
نکته ای که این دستور داره اینه که شما این تابع رو فقط توی setup برنامه می تونید استفاده کنید و برای یک بار میزان روشنایی رو مشخص کنید که این مقدار رو از بین صفر تا 255 میتونید انتخاب کنید.
مثال:
Strip.setBrightNess(128);
با اعمال این دستور میزان روشنایی هر ال ای دی که فرمان روشن شدن بگیره نصف خواهد شد.
updateLength
بوسیله این دستور میتونیم در هر جای برنامه تعداد LED ها رو که توی ساخت معرفی کردیم تغییر بدیم.
Strip.updateLength(30);
با این مثال تعداد ال ای دی ها که 60 بود رو به 30 تغییر دادیم.
سلام و خدا قوت
با توجه به اینکه سری جدید ریسه های آدرس پذیر WS2813 هم اکنون با رفع نواقص مدل قبلی در بازار هستند برای برنامه نویسی آن چه تفاوت هایی با مدل ارایه شده دارد
سلام،
اگر بخواهیم ws2812b با استفاده از atmega16 یا مشابه راه اندازی کنیم، چطوری باید انجام بدیم؟
با سلام خیلی ممنونم از اینکه علم و تجربتون رو به اشتراک گذاشتین
من با چندین کد و کتابخونه های مختلف امتحان کردم و کد شما هم امتحان کردم من LED شماره ۰ رو میخوام روشن کنم مثلا رنگ زد اگه مقادیر RGB بالاتر باشن LED کناری یعنی شماره ۱ هم روشن میشه ولی اگه Brightness رو مثلا بزارم روی ۱۰ این مشکل حل میشه ولی شدت نو ضعیف هست
ممنون میشم اگه راهنمایی بفرمایین