Arduino - RGB LED
Contents
Kleuren met licht
Wit licht van de zon bestaat letterlijk uit alle kleuren van de regenboog. Als tijdens een regenbui ook de zon schijnt en het zonlicht op de waterdruppels valt, wordt het zonlicht door waterdruppels uit elkaar getrokken en kunnen we de onderdelen van het invallende witte licht licht zien in de regenboog. Wat wij zien als wit licht is dus eigenlijk een mengsel van alle kleuren. Nu werkt het mengen van kleuren met licht heel anders dan mengen van kleuren met potloden. In principe is het zo dat bij potloden elke kleur meer van het invallende spectrum tegenhoudt. Bij licht werkt het precies andersom: elke kleur voegt wat extra toe. Als je bij potloden alle kleuren mengt krijg je donkere tinten en als je een keer een donkere kleur hebt, kun je die niet meer lichter maken door meer geel toe te voegen. Ach, dat kan wel als je dekkende kleuren zou gebruiken, maar dan ben je niet meer aan het mengen natuurlijk. Bij licht is het andersom: naarmate je meer kleuren licht toevoegt wordt het licht helderder en als je alle kleuren samenvoegt krijg je wit licht. Bij kleurpotloden vormen rood, blauw en geel de basiskleuren. Rood en blauw geven paars, geel en rood geven oranje en alledrie bij elkaar geeft verschillende tinten bruin. Bij licht zijn rood, groen en blauw de basiskleuren. Geel licht kun je dan bijvoorbeeld maken door rood en groen bij elkaar te doen.
|
| Kleuren mengen met licht |
Helemaal in het midden zit wit licht dat gemaakt wordt door rood, groen en blauw licht bij elkaar te voegen. In dit plaatje staan de kleuren vol aan, maar we kunnen de individuele kleuren ook dimmen natuurlijk. Zo kunnen we ook andere kleuren maken. We kunnen elke mogelijk kleur definieren door van elk van de drie basiskleuren de helderheid op te geven. Normaliter doen we dat in 256 stapjes, een byte per kleur. Bij zwart staan alle drie de LED-jes dan uit (0,0,0) en bij wit staan ze maximaal aan (255, 255, 255). Bij alle grijs-tinten zijn de drie waarden gelijk, maar ergens tussen de 0 en 255 in (50,50,50) is bijvoorbeeld een grijs-tint. Waar (255,0,0) helderrood is, is (20,0,0) donkerrood. En zo voort. Met deze drie kunnen we alle kleuren weergeven; bij elkaar ruim 16 miljoen verschillende kleuren!
De RGB LED
Een RGB LED is niet één LED, maar drie; van binnen bevat het letterlijk een rode (R), groene (G) en blauwe (B) LED. RGB-LEDs hebben dus geen twee, maar zes aansluitingen. Om het aantal poostjes te verkleinen heeft een RGB LED een gemeenschappelijke cathode (-), of een gemeenschappelijke annode (+). Welk type het precies is, kun je aan de buitenkant niet zien. Wel is het langste pootje de gemeenschappelijke poot en zijn de andere drie voor de rode, groene en blauwe LED. Maar ook hiervoor bestaat er geen standaard.
| Een RGB LED |
Je weet ook niet welk pootje voor rood is, welk voor groen en welk voor blauw. Daarvoor zou je de specificaties moeten bekijken, maar gewoon proberen werkt ook uitstekend. Als je een RGB LED op een printplaat zou solderen moet je er rekening mee houden dat het type net wat anders is dan je had verwacht. Gelukkig is zo'n Arduino erg flexibel en kun je in veel gevallen de software aanpassen om het alsnog goed te maken. Als het nodig is om het van te voren zeker te weten, dan moet je zorgen dat je vooraf hebt getest.
| RGB LED; twee typen schematisch |
Net als bij gewone LED's moet de stroom door elke LED binnen een RGB-LED worden beperkt met een weerstand. Je moet dan voor elke LED een eigen weerstand gebruiken omdat de LED-jes anders elkaar beinvloeden.
HSL
Een RGB LED wordt aangestuurd met een RGB signaal dat voor elke LED aangeeft hoe hard die moet branden. Maar het is voor mensen niet zo gemakkelijk om kleuren te definieren in de RGB-vorm. Probeer maar eens te bedenken welke RGB waarden er horen bij een kleur als mosgroen. Er zijn andere kleur-modellen die beter aansluiten bij onze natuur. Een van die modellen heet HSL. Ook hier worden alle kleuren met drie getallen gedefinieerd, net als bij het RGB model, maar de drie getallen bij het HSL model betekenen iets heel anders. De letter H slaat op Hue; dat getal wijst op het type kleur, de kleurtint. De letter S staat voor Satuartion, ofwel, verzadiging. Een hoge S betekent een felle kleur, terwijl lagere waarden meer pastel-tinten geven om uiteindelijk uit te komen bij allerlei tinten grijs (S=0). Als S=0 zijn de kleuren niet meer te herkennen. In dat geval maakt de waarde van H niets meer uit. Tenslotte hebben we L: de Lightness ofwel de helderheid. Bij maximale helderheid is de kleur zo helder dat elke tint wit wordt. Bij L=0 wordt elke kleur zwart. In beide extreme gevallen maken de waarden van H of S niets uit. Bij tussenliggende waarden worden de kleuren duidelijker. Het meest duidelijk zijn de kleuren bij maximale S en halve helderheid L. Bij HSL wordt H meestal uitgedrukt als een getal tussen 0 en 360. Dat staat dan voor graden op de kleurencirkel. S en L worden uitgedrukt in procenten (tussen 0% en 100%) of als getal tussen 0 en 1. Hieronder de HSL kleurring voor S=100% en L=50%:
|
| HSL kleurring |
Als je nu bovenstaande kleurring bekijkt kun je je, misschien na wat oefenen, beter voorstellen wat je moet doen om bijvoorbeeld een donker-bruin als van oud verweerd hout te maken. Dan begin je met een Hue-tint van bijvoorbeeld 15 graden -oranje- en maakt die donkerder om meer bij bruin uit te komen, dus bijvoorbeeld door L=20% te kiezen. Omdat het om verweerd hout gaat, zal de kleur ook wel naar grijs neigen. Daarom maken we de verzadiging S ook lager, bijvoorbeeld 50%. Als je wilt zien hoe dit uitpakt kun je bijvoorbeeld eens [hier] kijken, of [hier]. Misschien is dit nog niet precies de goede kleur, maar je komt in elk geval in de richting. En kun je bedenken wat de bijbehorende RGB waarden zijn? Vast niet; dat is: (R=77,G=38,B=26). Als je wat wilt oefenen kun je proberen om mosgroen te maken, of lavendel.
De schakeling
Extra benodigdheden:
- 1 RGB LED met common cathode (= gemeenschappelijke min)
- 3 weerstanden van 180Ω-220Ω
- 3 potmeters van 10kΩ
|
| Schakeling met regelbare RGB LED |
Het programma
We maken hier twee versies van het programma. Bij het eerste worden de drie kleuren van de LED rechtstreeks geregeld met de drie potmeters. De linker potmeter is voor de rode LED, de midden potmeter voor de groene en de rechter potmeter voor de blauwe LED. Het programma gaat ervan uit dat jouw RGB LED dezelfde pin-configuratie heeft als de onze. Door in het programma de pin toewijzing te veranderen kun je het programma aanpassen op de hardware. Onze LED heeft ook een gemeenschappelijke cathode, en dus een gemeenschappelijke nul aansluiting - tweede pootje van links.
Overigens hebben RBG LEDs een vaak heldere plastic behuizing waarmee de overall kleur niet erg goed uitkomt. Om dat te verbeteren kun je een stukje matglas of ondoorzichtig wit plastic, bijvoorbeeld van een plastic bekertje, over de LED heen plaatsen.
Upload het volgende programma naar je Arduino:
int redpin = 11; // select the pin for the red LED
int bluepin = 10; // select the pin for the blue LED
int greenpin = 9; // select the pin for the green LED
int r_pot_pin = 2; // A2 is the analog input pin for the red pot
int g_pot_pin = 1; // A1 is the analog input pin for the green pot
int b_pot_pin = 0; // A0 is the analog input pin for the blue pot
void setup() {
pinMode(redpin, OUTPUT);
pinMode(bluepin, OUTPUT);
pinMode(greenpin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
int R = analogRead(r_pot_pin)/4; // red; division by 4 gives range 0 to 255
int G = analogRead(g_pot_pin)/4; // green
int B = analogRead(b_pot_pin)/4; // blue
analogWrite(redpin, R);
analogWrite(bluepin, B);
analogWrite(greenpin, G);
delay(100);
}
Onze tweede versie is gebasseerd op het HSL kleurmodel. De eerste potmeter is dan voor de kleur-tint (Hue), de tweede voor de kleur-verzadiging (Satuartion) en de derde potmeter is voor de Lightness (helderheid). Voor dit programma is het net zo belangrijk dat de kleuren van de LEDjes correct zijn aangesloten anders worden de verkeerde kleuren aangestuurd en wordt een alternatieve kleurcirkel gevolgd. Het HSL model is geimplementeerd in de functie HSL_to_RGB(). Deze functie schrijft ook resultaten naar de Serial Monitor.
int redpin = 11; // select the pin for the red LED
int bluepin = 10; // select the pin for the blue LED
int greenpin = 9; // select the pin for the green LED
int hue_pin = 2; // A2 is the analog input pin for the Hue pot
int sat_pin = 1; // A1 is the analog input pin for the Satuartion pot
int light_pin = 0; // A0 is the analog input pin for the Lightness pot
int r;
int g;
int b;
void setup() {
pinMode(redpin, OUTPUT);
pinMode(bluepin, OUTPUT);
pinMode(greenpin, OUTPUT);
Serial.begin(9600);
}
void HSL_to_RGB(float H, float S, float L)
// informatie: https://nl.wikipedia.org/wiki/HSL_%28kleurruimte%29#Omzetting_van_HSL_naar_RGB
{
int Hi;
float f; float span;
byte p; byte q; byte t; byte u;
// begrens input waarden
if (S>1) S=1; if (S<0) S=0;
if (L>1) L=1; if (L<0) L=0;
// berekening RGB
L = exp(L)*0.582-0.582; // exponentieel meer licht voor logaritmisch werkende ogen !!
Hi=floor(H/60); // bepaling segment
f=(H/60-Hi)*2-1; // factor binnen segment
Hi=(Hi+600) % 6; // correctie voor H buiten bereik 0-360
if (L<0.5) { span=S*L; } else { span=S*(1-L); }
p=(L+span)*255;
q=(L+f*span)*255;
t=(L-span)*255;
u=(L-f*span)*255;
switch (Hi) { // de 6 segmenten
case 0: r=p; g=q; b=t; break;
case 1: r=u; g=p; b=t; break;
case 2: r=t; g=p; b=q; break;
case 3: r=t; g=u; b=p; break;
case 4: r=q; g=t; b=p; break;
case 5: r=p; g=t; b=u; break;
}
if (random(0,2)<1) {
Serial.print("H:"); Serial.print(H);
Serial.print(" S:"); Serial.print(S, 3);
Serial.print(" L:"); Serial.print(L, 3);
Serial.print(" r:"); Serial.print(r);
Serial.print(" g:"); Serial.print(g);
Serial.print(" b:"); Serial.println(b);
}
}
void loop()
{
float H = 360.0*analogRead(hue_pin)/1023.0; // kleur-tint
float S = analogRead(sat_pin)/1023.0; // verzadiging
float L = analogRead(light_pin)/1023.0; // helderheid
HSL_to_RGB(H,S,L); // conversie naar r, b en g
analogWrite(redpin, r);
analogWrite(bluepin, b);
analogWrite(greenpin, g);
delay(100);
}
Uitleg
De setup in beide versies stelt eerst de pins van de drie kleuren van de RGB LED in als OUTPUT. Daarna worden de pins van de drie potmeters opgegeven; een voor R, een voor G en een voor B (in de tweede versie voor respectievelijk H, S en L). De loop() functie van de eerste versie leest eerst de waarden van de drie potmeters uit met analogRead(). Zoals je ziet wordt de uitgelezen waarde meteen gedeeld door 4. Dat is omdat analogRead waarden geeft tussen 0 en 1023. Door te delen voor 4 wordt dat een getal tussen 0 en 255; precies de waarden die via PWM kunnen worden uitgestuurd naar de LEDs. Dat gebeurt dus direct daarna, waarna het programma 100 ms wacht voor een volgende ronde. Deze wachttijd is overigens niet erg belangrijk.
De tweede versie definieert drie extra variabelen, r, g en b, die gebruikt worden om de waarden door te geven van de HSL_to_RGB() functie. In wezen doet dit programma precies hetzelfde alleen worden de waarden van de potmeters nu uitgelezen als HSL waarden die vervolgens (en dat is de enige extra stap) door de HSL_to_RGB() functie worden vertaald naar de r, g en b waarden die worden doorgestuurd naar de LED. Dan blijft de werking over van de HSL_to_RGB() functie. Om dat te begrijpen moet je beter begrijpen hoe HSL in elkaar steekt en dat gaat voor dit project net iets te ver. Als je daar meer over wilt weten, en dat wil je vast, kun je bijvoorbeeld op wikipedia kijken.
Beetje spelen
Je ziet dat een gewone RGB LED niet echt mooie kleuren levert. Dat heeft meerdere oorzaken. Ten eerste is het een goedkope RGB LED waarvan de basiskleuren niet goed op elkaar zijn afgestemd. Bovendien zorgt de glasachtige behuizing er bepaald niet voor dat de kleuren mooi worden samengevoegd tot één totaal kleur. In plaats daarvan komen de kleuren voor een belangrijk deel ongemend naar buiten. Daar komt dan nog bij dat de kleuren onderling vrij sterk verschillen in hun felheid bij bijvoorbeeld halve sterkte (rood is vaak overheersend). Tenslotte zijn de kleuren nog relatief helder bij het zwakste PWM signaal van 1/255. De stap van 0 naar 1 blijkt heel groot te zijn, terwijl het veschil tussen 254 en 255 nauwelijks zichtbaar is. Overigens treedt dit effect bij een beeldscherm nauwelijks op: dan is een lichtsterkte van 1 echt heel donker, bijna zwart. Het is onduidelijk waarom een LED bij Arduino relatief helder is bij een PWM signaal van 1/255. In elk geval is hier ruimte om te experimenteren. Je kunt bijvoorbeeld proberen om de kleuren beter te mengen door een dun stukje wit plastic over de RGB LED te plaatsen. Ook kun je mischien iets bedenken om een LEDje aan te sturen met een signaal dat kleiner is dan 1/255. Je kunt bijvoorbeeld de betreffende uitgang op zelf gekozen momenten aan en uit zetten. En om dat dan weer netjes te doen met de drie kleuren tegelijk zal lastig zijn. Om mooie kleuren te maken met een RGB LED is toch wat meer nodig.


