HSV è meglio di RGB…
Come molti di voi, anche io in passato ho avuto la curiosità di “giocare” con i primi led RGB, e come credo tutti possiate aver constatato, il problema principale nell’utilizzo di questi led è la generazione di colori indipendentemente dalla luminosità che con l’assegnazione diretta dei valori RGB non è certo semplice ed intuitiva, cosa che invece risulta estremamente facile con il sistema di descrizione del colore HSV ovvero:
Hue (tonalità) Saturation (saturazione) Brightness (luminosità):

In pratica definendo il valore H (nel range da 0° a 360°) si definisce il colore; quindi con S la quantità in percentuale (valore da 0 a 1) di colore presente, e con B la percentuale (valore da 0 a 1) dell’intensità luminosa.
Ed agendo ad esempio sul solo valore B sarà possibile far accendere e spegnere gradualmente il led mantenendo ad ogni livello di luminosità il colore prescelto 🙂
Così, due anni or sono, scrissi questo semplice algoritmo per Xduino (vedi post originale):
[sourcecode language=”cpp” autolinks=”true” collapse=”false”]
//— prototipo funzione
void HSVtoRGB( float h, float s, float v );
struct tipo_rgb{ //definisce la struttura dati RGB
unsigned char r; //red – rosso
unsigned char g; //green – verde
unsigned char b; //blue – blu
}
led[2], pin[2]; //definisce i due array utilizzati: i valori RGB e le relative uscite
//variabili di uso generale
byte x;
int h = 0;
float s, v;
void setup()
{
pin[0].r = 3; //assegna le uscite ai colori del primo led
pin[0].g = 6;
pin[0].b = 5;
pin[1].r = 9; //assegna le uscite ai colori del secondo led
pin[1].g = 11;
pin[1].b = 10;
for( x=0; x<2; x++){ //imposta i pin come uscite
pinMode(pin[x].r, OUTPUT);
pinMode(pin[x].g, OUTPUT);
pinMode(pin[x].b, OUTPUT);
}
}
void loop()
{
(h > 359) ? h = 0 : h++; //ciclo della tonalita
v = 0.5; //luminosita
s = 1; //saturazione
HSVtoRGB( 0, (float)(h), s, v );
HSVtoRGB( 1, (float)(360 – h), s, v );
for( x=0; x<2; x++){ //aggiorna le uscite
analogWrite(pin[x].r, 255 – led[x].r);
analogWrite(pin[x].g, 255 – led[x].g);
analogWrite(pin[x].b, 255 – led[x].b);
}
delay(10);
}
/* HSVtoRGB
(cc) 2008-2010 Kokiua (alias L.M.) from Sorbolo (Parma) – Italy
Creative Commons – http://creativecommons.org/licenses/by-nc-sa/3.0/
algoritmo rielaborato partendo da da http://www.cs.rit.edu/~ncs/color/t_convert.html
da RGB a HSB (Hue/Tonalita’ – Saturation/Saturazione – Brightness/Luminosita’)
HSB diventa HSV definendo Brightness = Value per distinguere la variabile B di RGB
i valori RGB che tornano sono nel range da 0-255
i valori in entrata sono:
h = [0.0-360.0] ( Tonalita’ in gradi)
s = [0.0-1.0] (Saturazione in % dove 1 = 100%)
v = [0.0-1.0] (Luminosita’ in % dove 1 = 100%)
*/
void HSVtoRGB( unsigned char x, float h, float s, float v )
{
int i;
float f, p, q, t, r, g, b;
if( s == 0 ) {
r = g = b = v; // achromatic (grey)
return;
} else {
h /= 60; // sector 0 to 5
i = floor( h );
f = h – i; // factorial part of h
p = v * ( 1 – s );
q = v * ( 1 – s * f );
t = v * ( 1 – s * ( 1 – f ) );
switch( i ) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
default: r = v; g = p; b = q; break; // case 5:
}
}
led[x].r = 255 * r; //converto i valori RGB dal range 0.0-1.0 a 0-255
led[x].g = 255 * g;
led[x].b = 255 * b;
}
[/sourcecode]
N.B. i led che ho utilizzato (2 ma possono essere chiaramente di più visto l’uso dell’array) sono a catodo comune e quindi la logica è invertita (per questo emetto il valore 255 – x).
Chiaramente sarà possibile “legare” uno o più parametri di controllo del colore ad ingressi analogici (al quale avremo collegato un sensore, un potenziometro, o altro) con grande semplicità, come in questo esempio:
[sourcecode language=”cpp” autolinks=”true” collapse=”false”]
//loop centrale modificato
void loop()
{
h = (float)((float)analogRead( 0 ) * (360.0L/1024.0L) ); //assegnazione del valore analogico letto nel pin 0 al parametro h (tonalità)
v = 0.5; //luminosita
s = 1; //saturazione
HSVtoRGB( 0, (float)(h), s, v );
HSVtoRGB( 1, (float)(360 – h), s, v );
for( x=0; x<2; x++){ //aggiorna le uscite
analogWrite(pin[x].r, 255 – led[x].r);
analogWrite(pin[x].g, 255 – led[x].g);
analogWrite(pin[x].b, 255 – led[x].b);
}
delay(10);
}
[/sourcecode]
2 Comments Already
Lascia un commento
Devi essere connesso per inviare un commento.
Mi pare un ottimo articolo, questo metodo lo implementerò nella prossima lampada rbg!
Hey that you just very much to the article, it was fairly and beneficial go through! I will be back again later for positive.