RGB LED vezérlés

2018-11-03

 

Ebben a cikkben szeretném bemutatni, hogy egy viszonylag macerás kódolást mennyire leegyszerűsít egy valaki által már korában megírt library.

Történt, hogy vettem egy WS2812/5050 RGB LED karikát. Eredetileg potméterhez szerettem volna világító gallérként használni. Mikor megkaptam, láttam ám, hogy ehhez kicsit nagy az átmérője, így egy darabig pihent a műhelyasztalon. Persze utánanéztem, hogyan kell ezeket az RGB LED-eket vezérelni, szóval kell hozzá egy Arduino, az én esetemben egy NANO.

Rájöttem, hogy mire tudnám használni. Macro fotózáskor a fényből soha nem elég. Számtalan, többé-kevésbé DIY (csináld magad) megoldást lehet találni az interneten. Lehet kapni világító gyűrűket, sőt talán előszőr a Yasuhara Nano objektívvel találkoztam, amibe három LED-et építettek be.

Azután a Canon is a színre lépett EF-S 35mm f/2.8 Macro IS STM objektívvel, aminek kijöttek egy párjával a mirrorless gépekhez.

Ez annyira tetszik, hogy itt abba is hagyhatnám a munkát és ha lenne rá 120-130 kHUF-om. Szóval kitaláltam, mi lesz az én megoldásom. Egy olyan világító macro gyűrű, aminek állítható a színhőhérséklete, és nem csak körbe tud világítani, hanem állítható a fény iránya is. A képen látható az optika, közepén egy Canon 50mm F1,4 obi, aminek a két végére egy macro fordító adapter van szerelve. Az elejére rácsavartam a négyszögletes szűrőadapter készlethez kapott egyik tárcsát. Erre három montage szallag darabkával ráragasztottam a LED gyűrűt.

Nézzük meg közelebbről a WS2812B chip vezérlését. Akár szallagban, akár valamilyen más formában, mint mondjuk karikában vesszük/alkalmazzuk, a chip-eket szimplán sorba kapcsolják. Minden chip-ben 3 LED (piros/kék/zöld) van, ezek szinét 8-8 biten (0..255) határozhatjuk meg. A 0 az azt jelenti, hogy nem világít. Magát a vezérlő chip-et nevezik WS2812B-nek, a LED modult meg 5050-nek. Nem tudom mi értelme, lehet hogy külön is lehet kapni őket? Szóval a sorban első chip leszedi az első 3x8 bit-et, a többit továbbengedi, és ez így megy sorban, amennyi chip össze van kapcsolva.

A kódolás elég egyszerű.

Az időzítés. Elég gyorsnak néz ki. De gondoljunk bele, hogy teszem azt egy TV képernyőt akarunk csinálni :), egy csomó chip-et sorba kötünk, és másodpercenként illene 25-30 képet kitenni. Gondolom ilyenkor szegmensekre osztják a teljes kijelzőt. Ha utána számolunk, az Arduinoban a AVR-ünk 16MHz-en ketyeg, ami azt jelenti, hogy 1us alatt 16 gépi ciklust/műveletet tud végrehajtani. Szóval a 0,4us-be nem sok minden fér bele.

Nár kezdtem nézegetni, Arduino-ban hogyan kell Assemy kódot elkövetni, amikor megtaláltam a FastLED könyvtárat. Minden tiszteletem a Daniel Garcia és Mark Kriegsman uraknak. Nem csak azt oldották meg, hogy Arduino alól vezéreljük a WS2812B típusú chip-eket, hanem vezérelhető több mint 10 típus, a legtöbb Arduino kártyára megoldották a lábak direkt vezérlését (tehát szimplán az Arduino lábszámozását használhatjuk), és ha jól vettem ki, szimpla AVR mikrovezérlőkhöz is befordítható. Ha utána olvastok, lehet hogy még a Világbéke érdekében is lehet alkalmazni :). A library-t töltsük le, csomagoljuk ki, és tegyük a \URERS\user_name\DOCUMENTS\ARDUINO\LIBRARIES mappába.

Az első példaprogramunk nagyon egyszerű, egy kék LED-et forgatunk körbe. Betöltjük a FastLED.h-t, 24 LED-ünk van, és az Arduino panel 3-as digitális lábán fogjuk az adatokat kiküldeni. Létrehozunk egy tömböt a LED-eknek, ebbe fogjuk betenni, melyik milyen színben világítson. A setup()-ban megmondjuk a FastLED objektumnak, hol találja majd az adatokat, milyen chip-eket használunk, melyik az adat láb, és színcsatornák sorrendjét is megadjuk. (Alapértelmezés ez RGB, csak 2 órát kellett keresgélnem hol/hogyan kell GRB-re állítani.) A loop() ciklusban az előző LED-et feketére állítjuk, majd a következőt kék-re. A FastLED.show() utasítással kiküldjük a kombinációnkat, váruk 100ms-t, majd a ciklus elejére ugrunk.


#include<FastLED.h>
#define NUM_LEDS 24
#define DATA_PIN 3

CRGB leds[ NUM_LEDS];

int i;

void setup() { 
   FastLED.addLedse<WS2812, DATA_PIN, GRB>( leds, NUM_LEDS);
}


void loop() { 
   if( i == 0) leds[ 23]= CRGB::Black;
   else leds[ i- 1]= CRGB::Black;
   leds[ i]= CRGB::Blue; 
   FastLED.show();
   delay( 100);
   if( i < 23) i++;
   else i= 0;
}

A teljes programot nem publikálom, de nézzük meg, hogyan állítottam, nem túl professzionális módon a színhőmérsékletet. A setup()-ban benne hagytam megjegyzésként egy olyan változatot, amikor a FastLED színprofil korrekcióját használtam. Ez nem müködött kielégítően nekem, de ha majd képernyőt készítetek, jól jöhet :). Egy potit a föld és a táp közé köttötem, a csúszkáját az 1. analóg bemenetre kötöttem. Az összes színcsatornát 200-asra állítottam, a kék csatornát a potinak megfelelően változtatom.


#include<FastLED.h>
#define CHIPSET         WS2812
#define LED_TYPE        TypicalSMD5050
#define COLOR_ORDER     GRB
#define BRIGHTNESS      200
#define NUM_LEDS        24
#define LEDS_PIN        3
#define POTI_PIN        1


CRGB leds[ NUM_LEDS];


int i;
int poti=    0;
int piros= 200;
int kek=   200;
int zold=  200;


void setup() { 
   FastLED.addLeds<CHIPSET, LEDS_PIN, COLOR_ORDER>( leds, NUM_LEDS);
//  FastLED.addLeds<CHIPSET, LEDS_PIN, COLOR_ORDER>( leds, NUM_LEDS).setCorrection( TypicalSMD5050 );
}


void loop() { 
   kek= analogRead( POTI_PIN)/ 4;
   i= 23;
   while( i)
   {
      leds[ i].red   = piros;
      leds[ i].green = zold;
      leds[ i].blue  = kek;
      i--;
   }
   FastLED.show();
   delay( 100);
}

Ennyi az egész, itt a vége, fuss el véle.