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

LED های RGB از سه LED با رنگ های قرمز ، آبی و سبز تشکیل شده اند . این LED ها توانایی نمایش رنگ ها مختلف را دارد . عملکرد آن ها به این صورت است که برای ساخت هر نوع رنگی ، درصد مختلفی از نورای قرمز ، سبز و آبی را ترکیب می کنند . این سه نور جز نور های اصلی هستند که می توان با آن ها نور های دیگر را ساخت . برای کنترل شدت هر کدام از این رنگ ها از سیگنال PWM استفاده می شود . با افزایش دیوتی سایکل سیگنال هر کدام از LED های قرمز ، آبی و سبز ، شدت نور آن افزایش می یابد . برای راه اندازی LED های RGB باید سه پین از میکروکنترلر را به آن اختصاص دهیم . در صورتی که بخواهیم n تعداد LED RGB را راه اندازی کنیم ، به n*3 پین از میکروکنترلر احتیاج داریم ( در حداقل حالت خود ) .

در این میان شرکت Worlsemi با ساخت درایور های LED RGB مشکل تعداد پین های ارتباطی را رفع کرد . در این حالت میکروکنترلر تنها از طریق یک پین دیتای مربوط به رنگ را به درایور LED RGB و درایور تا دریافت دیتای بعدی ، LED RGB را راه اندازی میکند . یکی از مدل های قدیمی این شرکت ، درایور WS2811 است . WS2811 در قالب یک چیپ کوچک با هشت پین می باشد . این درایور را به LED RGB ارتباط داده و سپس برای ایجاد هر رنگ ، دیتای مربوط به هرکدام از LED ها را به صورت هشت بیتی و از طریق یک پین ارتباطی به درایور می فرستیم . به طور مثال برای نمایش رنگ سفید در یک LED RGB باید هر کدام از LED ها قرمز ، سبز و آبی را با حداکثر توان خود روشن کنیم تا نور سفید مشاهده شود . در این حالت اگر از درایور WS2811 برای راه اندازی LED استفاده شود برای هر کدام از LED ها باید مقدارد 0xFF را فرستاد در واقع 0xFFFFFF که به صورت 24 بیتی است را به WS2811 می فرستیم تا نور سفید مشاهده گردد ( برای هر رنگ یک بایت در نتیجه برای سه رنگ اصلی 24 بیت باید ارسال شود) .

 

 

اگرچه درایور WS2811 تا حد زیادی مشکلات LED RGB ها را برطرف کرد اما همچنان مشکلاتی باقی مانده اند . به طور مثال برای راه اندازی n تعداد LED RGB با درایور WS2811 ، شما به n تعداد WS2811 نیز احتیاج دارید که این مشکل باعث چند برابر شدن حجم مدار خواهد شد . به همین منظور شرکت Worsemi اقدام به ساخت مدل جدید درایور های LED RGB به نام WS2812 کرد . در این مدل درایور در پکیج LED RGB قرار دارد . در واقع شما یک LED RGB با درایور داخلی خواهید داشت . WS2812 انقلابی را در صنعت نور پردازی ایجاد کرد . WS2812 در دو مدل معمولی و مدل WS2812 2020 ساخته شده اند . WS2812 امکان سری شدن را دارند . می توان چندین WS2812 را با همدیگر سری کرده و همگی آن ها را تنها از طریق یک پین ارتباطی کنترل نمود .

 

 

کنترل و راه اندازی LED های WS2812 :

برای راه اندازی این ماژول ها از ارتباطی شبیه به 1Wire استفاده می شود . در این ارتباط از دیوتی سایکل های مختلف برای ایجاد منطق های صفر و یک استفاده می شود . تصویر زیر بر گرفته از دیتا شیت WS2812  می باشد :

با دقت در جدول بالا خواهید دید که کم ترین تاخیر مربوط T0H است . با وجود کریستال 16MHz آردوینو UNO و همچنین توانایی اجرای هر دستور در یک سیکل در AVR ها ، با یک محاسبه ساده متوجه خواهید شد که کمترین تاخیری که می توان با آردوینو UNO ایجاد کرد 1/16000000 ثانیه یا در واقع 0.0625 میکرو ثانیه است که تنها با 6 دستور NOP می توان یک تاخیر تقریبا 0.35 میکرو ثانیه ای ایجاد کرد . با وجود مقدار کم تاخیر در ایجاد سیگنال و همچنین حساسیت آن ، راه اندازی این LED ها توسط آردوینو UNO چالش بزرگی است . شاید در نگاه اول فکر ایجاد یک حلقه و ایجاد سیگنال های 1 و 0 به نظرتان برسد اما باید گفت که سرعت ارسال دیتا در این ارتباط به حدی بالا است که اجرای حلقه خود ایجاد تاخیر چشم گیری در اسال دیتا خواهد کرد به همین دلیل این LED ها را با استفاده از کد های اسمبلی راه اندازی می کنند . خوشبختانه نیازی به محاسبه و کد نویسی اسمبلی برای این LED ها وجود ندارد چرا که کتابخانه Adafruit_NeoPixel همه ی این کار ها را انجام می دهد .ما در این آموزش از کتابخانه Adafruit استفاده خواهیم کرد .

 

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

برای راه اندازی این LED ها ابتدا کتابخانه آن را از لینک زیر دانلود در آردوینو IDE خود نصب کنید :

https://github.com/adafruit/Adafruit_NeoPixel

پس از دانلود و نصب این کتابخانه میتوانید مثال های این کتابخانه را از مسیر زیر اجرا کنید :

توابع و کلاس های کاربردی WS2812 :

در اینجا لازم است چنتا از مهمترین توابع ، هدر فایل ها و… WS2812 را مورد بررسی قرار دهیم .

 

افزودن کتابخانه :

#include <Adafruit_NeoPixel.h>

با این دستور کتابخانه Adafruit برای WS2812 به برنامه افزوده می شود .

در برد هایی با هسته AVR توسط دستور زیر باید هدر های مورد نیاز برای هسته AVR را به برنامه افزود :

#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

 

توسط دستور زیر باید یک شی از کلاس Adafruit_NeoPixel بسازید تا از آن برای راه اندازی WS2812 استفاده کنید :

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

در کد بالا pixelss می تواند هر اسمی باشد .

NUMPIXEL تعداد پیکسل های سری شده با همدیگر است .

PIN همان پین اتصال به پین DI می باشد .

پارامتر سوم که در این جا جمع دو ماکرو می باشد ، جهت تعییر مد راه اندازی WS2812 است زیرا این LED های از ارتباط های I2S و همچنین سرعت های 800KHz و 400KHz پشتیبانی میکنند (این مقادیر برای مدل WS2812 ، WS2812B و… متغیر است ) .

 

توسط متد begin (برای شی pixel که در بالا توضیح داده شد ) WS2812 با مقادیر بالا پیکرندی می شود . این تابع را در setup برنامه فراخوانی می شود .

 

pixels.begin();

 

توسط متد LED clear ریست می شود . بهتر است قبل از شروع برنامه یک بار از این تابع استفاده شود تا LED خاموش گردد .

pixels.clear();

 

توسط دستور زیر می توان یک رنگ را به بافر برنامه ارسال کرد . با اجرای این دستور تنها مقدار رنگ و دیتا آماده ارسال می شوند که با فراخوانی تابع show این مقدار به LED ارسال شده و رنگ وارد شده نمایش داده می شود .

pixels.setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
pixels.show();

پارامتر n شماره LED می باشد (در صورتی که چنتا WS2812 سری باشند با این پارامتر می توان انتخاب کرد که دیتا به کدام LED ارسال شود ).

پارامتر های r ، g و b به ترتیب مقدار رنگ های سبز ، قرمز و آبی می باشند .

تابع show جهت ارسال مقادیر تابع setPixelColor به LED است .

 

مثال زیر برای راه اندازی یک LED Ring با 16 پیکسل است .

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 8

// 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(16, 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.setBrightness(50);
  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);
}

شماتیک مدار :

 

Tags:
About Author: USER_4