Roby94 (Member)
Guru
Messaggi: 1170
Iscritto: 28/12/2009
|
Buonasera, sto apportando alcune migliorie ad un sistema di gestione illuminazioni, si tratta solo di migliorare le modalità già disponibili.
Una delle modalità è un gradiente di colori che si puo vedere come il precorrimento della circonferenza dell'HSV con S=V=1 quindi con H variabile.
Per far ciò ho questa funzione
Codice sorgente - presumibilmente C/C++ |
void RGBScaleMode()//Gradiente RGB
{
uint8_t delay = EEPROMRead(EEPROM_SCALERGB_DELAY);//Recupero il valore di delay
while(1)
{
for(; GREEN != 255; GREEN++) _delay_ms(delay);//Porto il verde al massimo
for(; RED != 0; RED--) _delay_ms(delay);//Porto il rosso al minimo
for(; BLUE != 255; BLUE++) _delay_ms(delay);//Porto il blu al massimo
for(; GREEN != 0; GREEN--) _delay_ms(delay);//Porto il verde al minimo
for(; RED != 255; RED++) _delay_ms(delay);//Porto il rosso al massimo
for(; BLUE != 0; BLUE--) _delay_ms(delay);//Porto il blu al minimo
}
}
|
e fino qui nessun problema.
Il codice visto in precedenza impone che i valori di partenza siano GREEN=BLUE=0 e RED=255, vorrei eliminare questa limitazione, potendo far partire il gradiente da un colore qualsiasi. Ho iniziato modificando cosi.
Codice sorgente - presumibilmente C/C++ |
void RGBScaleMode()//Gradiente RGB
{
uint8_t delay = EEPROMRead(EEPROM_SCALERGB_DELAY);//Recupero il valore di delay
uint8_t *min;
if(RED < GREEN && RED < BLUE) min = &RED;//Identifico quale sia la componente minore tra le 3
else if(GREEN < RED && GREEN < BLUE) min = &GREEN;
else min = &BLUE;
for(; *min != 0; *min--) _delay_ms(delay);//Lo riduco a 0 graduatamente
/****/
}
|
Con la parte di codice aggiunta identifico quale tra le tre componenti sia la minore e la porto lentamente a 0 riportandomi sulla circonferenza facendo il minor tragitto possibile, ora però non mi viene in mente come continuare l'algoritmo per poter riprendere a percorrere la circonferenza dal nuovo colore trovato, vi viene in mente un modo? Mi aiutereste molto, io continuo a pensarci in tanto.
Grazie
PS Il topic l'avrei volentieri messo nella sezione algoritmi ma trattandosi di un algoritmo da modellarsi su un linguaggio specifico, ho pensato fosse meglio la sezione di C. Ultima modifica effettuata da Roby94 il 22/03/2015 alle 21:57 |
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Io calcolerei una mappa durante l'inizializzazione (che renderebbe il codice più veloce, oltretutto). La mappa deve essere "linearizzata" per mappare tutti i possibili valori di RGB.
Un intero ciclo impiega: 0-255 + 255-0 + 0-255 + 255-0 + 0-255 + 255 - 0 = 256 * 3 = 1536 valori.
Ogni combinazione di colori è rappresentata da 3 bytes (0-255 = 1 byte + 0-255 = 1 byte + 0-255 = 1 byte). Il tipo più vicino è quindi int (che presumo sulla tua piattaforma sia 4 bytes).
Quindi qualcosa del genere...
Codice sorgente - presumibilmente C/C++ |
Ad inizializzazione, devi scrivere il codice che inizializzi la colorMap (o ancora meglio, puoi scrivere un programma che la calcoli staticamente e poi inizializzarla direttamente durante la compilazione).
Codice sorgente - presumibilmente C/C++ |
int colorMap[1535] = {valore1, valore2, ecc.}
|
I valori possono essere mappati come segue:
0|R|G|B (il primo byte è zero).
Ad esempio:
Codice sorgente - presumibilmente C/C++ |
void setMap(int index, uint8_t r, uint8_t g, uint8_t b){
colorMap[index] = 0x00000000 | (r << 16) | (g << 8) | (b << 0); // << 0 non serve, ma per consistenza lo lascio.[
}
setMap(0, 255, 0, 0);
setMap(1, 254, 0, 0);
// eccetera, automatizza con un for loop simile a quello postato da te
|
Dopodichè, per estrarre i valori:
Codice sorgente - presumibilmente Plain Text |
uint8_t r, g, b;
r = (colorMap[index] & 0x00110000) >> 16;
g = (colorMap[index] & 0x00001100) >> 8;
b = (colorMap[index] & 0x00000011) >> 0; // Lo >> 0 non serve, ma per consistenza lo lascio
|
Una volta che hai la mappa, puoi semplicemente incrementare index e partire da qualsiasi punto (da 0, da 300, da 600, non importa) per prendere i valori che ti servono.
Quando arrivi a 1535 riparti da 0.
Bonus: puoi salvare il 25% di spazio comprimendo gli spazi inutilizzati dallo 0 per ogni valore della mappa (invece di 0|R|G|B|0|R|G|B ... puoi fare con un pò di più complessità R|G|B|R|G|B....). L'esercizio è lasciato al lettore. Ultima modifica effettuata da pierotofy il 22/03/2015 alle 23:34
|
|
Roby94 (Member)
Guru
Messaggi: 1170
Iscritto: 28/12/2009
|
Ottima soluzione Piero, grazie, ma 6KB di array è pauroso. Attualmente il codice è pensato per risiedere su ATmega328P, 32KB di flash, consiglieresti questa strada anche su un dispositivo del genere? Prendendo in considerazione che questo non è l'unica modalità presente.
|
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Chiaramente se sei a corto di memoria questa soluzione non è adatta. Ma se hai memoria... usala!
|
|
Roby94 (Member)
Guru
Messaggi: 1170
Iscritto: 28/12/2009
|
Il problema è che non so come la memoria venga gestita, mi riferisco alla ram, l'array viene interamente caricato in memoria? se è cosi allora non è un metodo applicabile su ATmega328P se non sbaglio vi sono solo 2KB di ram.
Ultima modifica effettuata da Roby94 il 22/03/2015 alle 23:43 |
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Oppure usa goto:
Codice sorgente - presumibilmente C/C++ |
switch(...){
case ... :
goto green;
// ...
default:
};
while(1)
{
green:
for(; GREEN != 255; GREEN++) _delay_ms(delay);//Porto il verde al massimo
red:
for(; RED != 0; RED--) _delay_ms(delay);//Porto il rosso al minimo
blue:
for(; BLUE != 255; BLUE++) _delay_ms(delay);//Porto il blu al massimo
// ....
}
|
Almeno puoi partire da un determinato colore (senza la precisione esatta della mappa).
|
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Postato originariamente da Roby94:
Il problema è che non so come la memoria venga gestita, mi riferisco alla ram, l'array viene interamente caricato in memoria? se è cosi allora non è un metodo applicabile su ATmega328P se non sbaglio vi sono solo 2KB di ram. |
Mm, si, effettivamente non funzionerà. Per accedere all'array, l'array dev'essere caricato in memoria.
|
|
Roby94 (Member)
Guru
Messaggi: 1170
Iscritto: 28/12/2009
|
Cavoli, in effetti è un metodo che garantisce una certa semplicità di utilizzo una volta generata la mappa... peccato, ti viene in mente un altro modo?
|
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
^
|
|
Vedi goto. (Risposto qui sopra)
Ultima modifica effettuata da pierotofy il 22/03/2015 alle 23:56
|
|