Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Inserimento in punto variabile di ciclo HSV
Forum - C/C++ - Inserimento in punto variabile di ciclo HSV

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 21:55
Domenica, 22/03/2015
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++

  1. void RGBScaleMode()//Gradiente RGB
  2. {
  3.         uint8_t delay = EEPROMRead(EEPROM_SCALERGB_DELAY);//Recupero il valore di delay
  4.  
  5.         while(1)
  6.         {
  7.                 for(; GREEN != 255; GREEN++) _delay_ms(delay);//Porto il verde al massimo
  8.                 for(; RED != 0; RED--) _delay_ms(delay);//Porto il rosso al minimo
  9.                 for(; BLUE != 255; BLUE++) _delay_ms(delay);//Porto il blu al massimo
  10.                 for(; GREEN != 0; GREEN--) _delay_ms(delay);//Porto il verde al minimo
  11.                 for(; RED != 255; RED++) _delay_ms(delay);//Porto il rosso al massimo
  12.                 for(; BLUE != 0; BLUE--) _delay_ms(delay);//Porto il blu al minimo
  13.         }      
  14. }


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++

  1. void RGBScaleMode()//Gradiente RGB
  2. {
  3.         uint8_t delay = EEPROMRead(EEPROM_SCALERGB_DELAY);//Recupero il valore di delay
  4.         uint8_t *min;
  5.        
  6.         if(RED < GREEN && RED < BLUE) min = &RED;//Identifico quale sia la componente minore tra le 3
  7.         else if(GREEN < RED && GREEN < BLUE) min = &GREEN;
  8.         else min = &BLUE;      
  9.         for(; *min != 0; *min--) _delay_ms(delay);//Lo riduco a 0 graduatamente
  10.        
  11.         /****/
  12. }


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
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:27
Domenica, 22/03/2015
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++

  1. int colorMap[1535];



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++

  1. 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++

  1. void setMap(int index, uint8_t r, uint8_t g, uint8_t b){
  2.     colorMap[index] = 0x00000000 | (r << 16) | (g << 8) | (b << 0); // << 0 non serve, ma per consistenza lo lascio.[
  3. }
  4.  
  5. setMap(0, 255, 0, 0);
  6. setMap(1, 254, 0, 0);
  7. // eccetera, automatizza con un for loop simile a quello postato da te



Dopodichè, per estrarre i valori:

Codice sorgente - presumibilmente Plain Text

  1. uint8_t r, g, b;
  2. r = (colorMap[index] & 0x00110000) >> 16;
  3. g = (colorMap[index] & 0x00001100) >> 8;
  4. 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.

:k:

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


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 23:36
Domenica, 22/03/2015
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.

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:37
Domenica, 22/03/2015
Chiaramente se sei a corto di memoria questa soluzione non è adatta. Ma se hai memoria... usala!


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 23:43
Domenica, 22/03/2015
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
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:47
Domenica, 22/03/2015
Oppure usa goto:

Codice sorgente - presumibilmente C/C++

  1. switch(...){
  2.   case ... :
  3.     goto green;
  4.   // ...
  5.  
  6.   default:
  7. };
  8.  
  9. while(1)
  10.         {      
  11.                 green:
  12.                 for(; GREEN != 255; GREEN++) _delay_ms(delay);//Porto il verde al massimo
  13.                
  14.                 red:
  15.                 for(; RED != 0; RED--) _delay_ms(delay);//Porto il rosso al minimo
  16.                
  17.                 blue:
  18.                 for(; BLUE != 255; BLUE++) _delay_ms(delay);//Porto il blu al massimo
  19.                 // ....
  20.         }



Almeno puoi partire da un determinato colore (senza la precisione esatta della mappa).


Il mio blog: https://piero.dev
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:50
Domenica, 22/03/2015
Testo quotato

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.


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 23:53
Domenica, 22/03/2015
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?

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 23:55
Domenica, 22/03/2015
^
|
|

Vedi goto. (Risposto qui sopra)

Ultima modifica effettuata da pierotofy il 22/03/2015 alle 23:56


Il mio blog: https://piero.dev
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo