آردوینو Arduinoمطالب علمی

بررسی WS2812 LED و راه اندازی آن با آردوینو

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

ws2812

برای کنترل هر آی سی از 24 بیت استفاده می شود که 8 بیت برای هر رنگ قرمز، سبز و آبی استفاده می شود که در واقع امکان 256 حالت نوری(Grayscale) را ممکن می سازد. تصویر زیر ترتیب ارسال این سیگنال را نمایش می دهد:

1409986446_data_sequence

این سیگنال ها باید به صورت پشت سر هم و به صورت سریال ارسال شود یعنی با فرض سه پیکسل به صورت پشت سر هم، یک بسته 24 بیتی به ازای هر پیکسل ارسال می شود. هر پیکسل اولین 24 بیت دریافتی را به خود اختصاص داده و باقی بیت های دریافتی را به پیکسل های بعدی منتقل می نماید. این روند تا آخرین پیکسل ادامه می یابد. با یک سیگنال ریست نیز کل آی سی های زنجیره خاموش می شود. در تصویر زیر شیوه اجرایی این فرآیند مشاهده می شود:

ws28121

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

1409986682_sequence_chart

همان گونه که قبلا نیز گفته شد این آی سی دارای دو مد کاری 400 کیلو هرتز(Low Speed) و 800 کیلوهرتز (High Speed) می باشد. با توجه به اینکه زمان بندی های سیگنال با توجه به مد کاری تغییر می کند و همچنین سرعت بالاتر مد پر سرعت و متداول تر بودن این مد کاری، زمان بندی ها بر اساس آن قرار داده می شود: (لازم به ذکر است زمان بندی های مد 400 کیلو دو برابر جدول زیر است)

1409986682_table

روند ارسال سیگنال بدین صورت است که در ابتدا یک سیگنال ریست از طریق خط دیتا ارسال می شود. در این حالت حافظه کل چیپ ها پاک (Clear) می شود. بعد از این حالت سیگنال های ارتباطی با زمان بندی ها مناسب ارسال می گردد برای مثال با وجود دو آی سی پشت سر هم و به جهت رنگ سفید و سبز باید ابتدا 0xFFF (رنگ سفید) و سپس 0x0F0 (رنگ سبز خالص) به صورت پشت هم ارسال گردد.

نصب کتابخانه NEOPIXEL در نرم افزار آردوینو

برای راه اندازی ریسه های WS2812 در آردوینو می توانید از کتابخانه NEOPIXEL استفاده کنید برای این منظور کافی است در قسمت manage libraries عبارت NEOPIXEL  جست و جو و نصب کنید.Screenshot 32

محاسبه توان مصرفی: 

هر کدام از LED های RGB تقربیاً 60mA جریان در ولتاژ 5v مصرف می کند.پس توان مصرفی هر کدام از این LED ها برابر است با:

5V×60mA=0.3 wat

اگر از یک زنجیر یک متری با  60 عدد از این LED ها در پروژه خود استفاده کنید به یک منبع تغذیه ۵ولت با توانایی تولید حداقل A3.6 آمپر جریان نیاز دارید.

نکته مهم: برای راه اندازی WS2812 به هیچ عنوان از پین های 5V و GND روی برد آردوینو استفاده نکنید.چون اگر بخواهید از پورت USB کامپیوتر خود این جریان را تامین کنید هم پورت USB‌و هم برد آردوینو آسیب خواهد دید.پین های 5V و GND باید به یک منبع تغدیه خارجی وصل شود.

نحوه اتصال به برد آردوینو:

51f1a42fce395f8520000001

انتخاب WS2812 مناسب با پروژه

این نوع LED ها هم در یه صورت تکی و هم به صورت ماژول در فروشگاه موجود می باشد که می توانید با توجه به نیاز خود یکی را انتخاب کنید.

Screenshot 33

نمونه کد برای تست 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 تغییر دادیم.

ویدیویی از راه اندازی WS2812:

نوشته های مشابه

3 دیدگاه

  1. سلام،
    اگر بخواهیم ws2812b با استفاده از atmega16 یا مشابه راه اندازی کنیم، چطوری باید انجام بدیم؟

  2. با سلام خیلی ممنونم از اینکه علم و تجربتون رو به اشتراک گذاشتین
    من با چندین کد و کتابخونه های مختلف امتحان کردم و کد شما هم امتحان کردم من LED شماره ۰ رو میخوام روشن کنم مثلا رنگ زد اگه مقادیر RGB بالاتر باشن LED کناری یعنی شماره ۱ هم روشن میشه ولی اگه Brightness رو مثلا بزارم روی ۱۰ این مشکل حل میشه ولی شدت نو ضعیف هست
    ممنون میشم اگه راهنمایی بفرمایین

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا