Stmievanie RGB LED diódy

Zápisník experimentátora

Hierarchy: ShiftPWM

V tomto článku sa naučíme stmievať RGB LED diódy. Toto je jednoduchá úloha v prípade, že máme jednu RGB LED diódu, pretože môžeme využiť signál PWM. Keď máme tých diód 8, úloha už nie je tak jednoduchá.

Použité dosky

Na stmievanie využijeme dve dosky z predchádzajúceho článku. V ňom je popísané ich vyrobenie a spôsob zapojenia.

Programovanie

Princíp stmievania je v tom, že sa generuje pre každý pin na RGB LED dióde vlastný PWM signál, ktorý navodí ľudskému oku pocit stmievanie konkrétnej zložky farby. Výsledný signál na troch pinoch vytvorí výslednú farbu. Pri programovaní niečoho takého od základu by sme sa celkom pekne zapotili a preto radšej využijeme hotové riešenie, ktoré pre nás pripravil autor knižnice ShiftPWM.

Táto knižnica vie pracovať aj s jednofarebnými diódami aj s RGB diódami. Poskytuje jednoduché rozhranie pre nastavenie farby každej diódy a my sa môžeme sústrediť len na vytvorenie príslušného efektu. Teoreticky vie ovládať farbu veľkého množstva diód, je ale potrebné pri tom trochu premýšľať. Diódy sú nastavované cez posuvné registre 74HC595, do ktorých sa zasielajú údaje cez SPI. Mikrokontrolér v Arduine pracuje na frekvencii 16 MHz a ľudské oko vyžaduje aspoň 25 obrázkov za sekundu, aby malo pocit plynulého stmievania. Čiže sme limitovaní kompromisom medzi počtom výstupov, výslednou frekvenciou a množstvom odtieňov na jednej farbe. Našťastie to nie je potrebné až tak riešiť a samotná knižnica vie oznámiť cez sériový port, kedy sú prekročené jej možnosti.

Najprv musíme knižnici povedať, ako ju budeme používať. To vykoná nasledovný kód. Pretože ovládame iba 24 pinov, môžeme si dovoliť frekvenciu 75 Hz s 256 odtieňmi pre každú základnú farbu.

const int ShiftPWM_latchPin=10;
const bool ShiftPWM_invertOutputs = false; 
const bool ShiftPWM_balanceLoad = false;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 3;
int numRGBleds = numRegisters*8/3;

Jas farby jednotlivých kanálov si upravujeme tak, aby zodpovedal citlivosti ľudského oka. Na to slúži nasledovná exponenciálna tabuľka hodnôt. Máme ju uloženu vo flash, preto z nej hodnoty čítame funkciou pgm_read_byte. Funkciu SetRGB používam ako proxy, ktorá sa postará o zmenu hodnoty jasu a súčasne aj prehodí jednotlivé hodnoty RGB. Knižnica ShiftPWM totiž vyžaduje striktne poradie RGB a keď máte diódy zapojené nejako ináč, nezobrazovali by sa správne farby. V mojom prípade je to BGR a to je vidno aj v parametroch funkcie.

// table of exponential values
// generated for values of i from 0 to 255 -> x=round( pow( 2.0, i/32.0) - 1);
const byte table[] PROGMEM = {
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  0,   0,   0,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
...
127, 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176,
180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250
};

void SetRGB(int led, unsigned char r,unsigned char g,unsigned char b) {
  r=pgm_read_byte(&table[r]);
  g=pgm_read_byte(&table[g]);
  b=pgm_read_byte(&table[b]);
  
  ShiftPWM.SetRGB(led,b,g,r);
}

Takto sa knižnica inicializuje.

void setup(){
  Serial.begin(9600);

  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetPinGrouping(1); //This is the default, but I added here to demonstrate how to use the funtion
  ShiftPWM.Start(pwmFrequency,maxBrightness);
  ShiftPWM.SetAll(0);
}

A výsledná animácia. Kód je jednoduchý. Prvý cyklus mení farbu od tmavej ku svetlej a druhý cyklus zase naopak. Kód vo vnútri cyklu znamená to, že na prvej dióde bude červená farba, na druhej zelená a na tretej modrá. Zvyšné farby sú tvorené kombináciou základných zložiek. Ako to celé vyzerá je najlepšie vidno na videu. Ak sa budete pozorne pozerať, budete vidieť, že pri kombinácii farieb sa dajú zblízka vidieť jednotlivé základné farby a že ich miešanie nie je úplne čisté a tak napríklad biela alebo žltá farba pôsobia mierne divne. Dalo by sa tomu mierne pomôcť korekciou zelenej farby, ktorá spôsobuje tieto posuny, ale na účely demonštrácie toto stačí.

void loop()
{  
  for(int i=0;i<256;i++) {
    SetRGB(0,i,0,0);
    SetRGB(1,0,i,0);
    SetRGB(2,0,0,i);
    SetRGB(3,i,i,0);
    SetRGB(4,0,i,i);
    SetRGB(5,i,0,i);
    SetRGB(6,i,i,i);
    delay(20);
  }
  for(int i=255;i>=0;i--) {
    SetRGB(0,i,0,0);
    SetRGB(1,0,i,0);
    SetRGB(2,0,0,i);
    SetRGB(3,i,i,0);
    SetRGB(4,0,i,i);
    SetRGB(5,i,0,i);
    SetRGB(6,i,i,i);
    delay(20);
  }
}

Zdrojový kód

Zdrojový kód sa nachádza na GitHub.

Video

Doplňujúce video sa nachádza na YouTube.


10.11.2016


Menu