Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /***************************************
- RGB BLENDER PROJECT
- Version 1.0 30/10/2009
- COPYRIGTH BNEXT S.R.L. & PROTOCUBE S.N.C.
- AUTHOR MARCO BOMBARA & LEONARDO PERETTI
- MAIL marco@bnext.it - info@protocube.it
- DESCRIPTION :
- Il progetto gestisce una lampada formata da 3 canali RGB che si possono miscelare in maniera indipendente tramite il movimento della mano.
- Posizionando la mano su uno dei tre canali RGB a disposizione il programma tramite un sensore di prossimità IR SHARP determina la distanza della mano.
- Mantenendo la mano nella stessa posizione per un breve lasso di tempo, il sw. memorizza la quantità di colore desiderata e la associa all'illuminazione generale della lampada.
- La miscelazione dei 3 canali può avvenire in contemporanea utilizzando 2 mano o più persone in quanto non ci sono blocchi del processore.
- FUNCTION :
- La lampada ha le seguenti funzioni :
- - Miscelatura onthefly dei singoli canali RGB
- - Indicazione di avvenuta memorizzazione colore con piccolo lampeggio del canale settato
- - Funzione di SHOW iniziale all'accensione
- - Funzione di salvataggio impostazioni colore tramite pulsante
- - Richiamo dell'ultimo colore memorizzato in fase di accensione
- - Pulsante per il lancio dello SHOW iniziale
- - Funzione di Scrensaver
- MATERIAL :
- 1 Arduino Duemilanove
- 1 Alimentatore 12V
- 1 lampada Ikea DIODER Multicolore
- 3 Sensori di prossimità SHARP GP2D120
- 6 MOS irf540
- 2 PCB Pushbutton, 12*12mm size
- 2 220 Ohm Resistors 1/4W
- EXTRA :
- La modellazione e la stampa del prototipo 3D della lampada è stata realizzata da PROTOCUBE S.N.C. www.protocube.it
- NOTE :
- Codice sviluppato in occasione del workshop Arduino - Torino Design Week 26-27-28/10/2009
- SPECIAL THANKS :
- Massimo Banzi
- Davide Gomba
- Enkel Bici
- */
- /*
- **************************************************
- * Spazio per le variabili di gestione della EEPROM
- **************************************************
- */
- #include <EEPROM.h> // Includo la libreria per la gestione della EEPROM per il salvataggio delle impostazioni
- int RGB_Memory_Address[]={0,1,2}; // Indica lo spazio di memoria in cui salvare le impostazioni del colore della lampada
- /*
- *************************************************
- * Spazio per le variabili di gestione dei LED RGB
- *************************************************
- */
- char sensor_type[]="GP2D12"; // In alternativa al sensore di test 2Y0A21
- char name_sensor[]={'R','G','B'}; // Memorizzo il nome rapresentativo dei canali RGB
- int pin_sensor[]={0,1,2}; // Indico il PIN analogico in ingresso a cui è collegato il sesnore per ogni canale RGB
- int pin_led_output[]={9,10,11}; // Indico il PIN PWM in uscita a cui è collegato ogni canale RGB
- unsigned long timer_sensor[]={0,0,0}; // Memorizzo i timer per ogni canale RGB
- int _distance_temp[]={0,0,0}; // Variabile in cui vengono gestite le letture temporanee delle distanze per fare il confronto sulle varizioni di movimento della mano
- boolean enable_sensor[]={true,true,true}; // Variabile che contiene lo stato abilitato/disabilitato per ogni canale RGB
- int channel_RGB[]={0,0,0}; // Variabile che contiene le percentuali di RGB da utilizzare nell'illuminazione globale definite dai singoli sensori
- int pin_channel_RGB[]={3,5,6}; // Indico i PIN PWM in uscita a cui è collegato l'illuminazione globale RGB
- int _last_value_channel[]={0,0,0}; // Variabile temporanea per evitare i picchi
- /*
- *************************************************
- * Spazio per le variabili di gestione dei Bottoni
- *************************************************
- */
- int pin_show = 7; // Pin a cui è collegato il pulsante per lanciare lo show
- int pin_memory = 12; // Pin a cui è collegato il pulsante per memorizzare il colore della lampada
- /*
- *******************************************************
- * Spazio per le variabili di gestione dello Screensaver
- *******************************************************
- */
- unsigned long timer_btn; // Timer che inibisce i pulsanti per un determinato tempo dopo il click
- int time_out_screensaver = 1; // Tempo oltre al quale parte lo screensaver se l'utente non ha fatto nulla (Espresso in minuti)
- unsigned long timer_screensaver; // Timer per la gestione della funzionalità screensaver
- /*
- **********************
- * Inizio del programma
- **********************
- */
- void setup() {
- Serial.begin(9600);
- pinMode(pin_show, INPUT);
- pinMode(pin_memory, INPUT);
- for(int i=0;i<=2;i++){
- pinMode(pin_led_output[i], OUTPUT); // Inizializzo i PIN dei singoli canali in uscita
- delay(10);
- pinMode(pin_channel_RGB[i], OUTPUT); // Inizializzo i PIN dell'illuminazione globale in uscita
- delay(10);
- }
- read_memory(); // Leggo la memoria EEPROM interna per caricare l'ultimo salvataggio della luce impostata ed assegnarlo alla luce globale
- delay(1000); // Effettuo una pausa all'avvio prima di lanciare la sequenza di inizializzazione
- show_RGB(); // Lancio lo show iniziale
- reset_screensaver(); // Resetto il timer dello screensaver
- }
- void loop() {
- for(int i=0;i<=2;i++){
- read_distance_sensor(i); // Ciclo nei 3 canali per leggere i valori dei sensori
- }
- check_button(); // Leggo lo stato dei bottoni
- check_screensaver(); // Verifico lo screensaver
- }
- void read_distance_sensor(int id_channel){
- /*
- Questa funzione serve a misurare la distanza della mano dal sensore per regolare la quantità di colore da miscelare
- il valore "id_channel" rappresenta il riferimento al canale RGB da utilizzare rispetto alle variabili estrene definite all'inizio
- La funzione blocca il colore e lo assegna all'illiminazione globale se si mantiene la posizione con la mano per un determinato tempo settato con la variabile "time_block_color" definita più avanti
- */
- int inner_distance; // Indica la distanza minima di una lettura valida prima di cadere nella zona morta
- int outer_distance; // Indica il distanza massima di una lettura
- if(sensor_type=="GP2D12"){
- inner_distance = 20;
- outer_distance = 500;
- }else{
- // Valori validi per il sensore di test SHARP 2Y0A21
- inner_distance = 20;
- outer_distance = 650;
- }
- int min_value = 50; // Indica il valore al di sotto della quale forzo a zero il valore di uscita, in modo da evitare blinkeggi strani.
- int max_value = 220; // Indica il valore massimo ottenibile con il rappirto di scalatura impostato
- int time_block_color = 350; // Indica quanti millisecondi devono passare per bloccare il colore
- int value_channel; // Rappresenta il valore PWM da memorizzare per questo canale RGB
- int out_put_channel; // Rappresenta il valore PWM in uscita sul LED quando si muove la manso sul sensore
- boolean active_channel = false; // Indica se l'utente sta lavorando sulla variazione di un canale oppure no
- value_channel = analogRead(pin_sensor[id_channel]); // Leggo il valore del sensore
- if(abs(_last_value_channel[id_channel]-value_channel)>=50){
- // In questo punto ho dei pichi dovuti a false letture, quindi non faccio nulla
- }else{
- _last_value_channel[id_channel]=value_channel; // Memorizzo il valore attuale come valido nella variabile temporanea
- }
- if(value_channel>=100){
- if(abs(_last_value_channel[id_channel]>=100)){
- active_channel = true; // L'utente sta muovendo la mano sul sensore e non si tratta di una falsa lettura, quindi attivo il canale come valido
- }
- }
- _last_value_channel[id_channel] = value_channel; // Memorizzo il valore attuale come valido nella variabile temporanea
- value_channel = constrain(value_channel, inner_distance, outer_distance); // Limito il valore in un range predefinito per evitare le zone morte
- value_channel = map(value_channel, inner_distance, outer_distance, 255, 0); // Scalo in maniera inversa il valore del sensore su base 255 per l'uscita PWM
- value_channel = constrain(value_channel, 0, 255); // Limito nuovamente il valore per evitare eventuali picchi oltre il 255
- value_channel = value_channel;
- out_put_channel = value_channel;
- if(value_channel >= max_value){
- value_channel=255; // Taglio al di sopra di una certa soglia per spegnere il led quando esco con la mano
- out_put_channel = 0;
- }
- if(value_channel <= min_value){
- value_channel=0; // Taglio al di sotto di una certa soglia per evitare di andare nella zona morta con la mano
- out_put_channel = 0;
- }
- if(active_channel == true){
- // Vario lo stato dei LED perchè l'utente sta interagendo
- analogWrite(pin_led_output[id_channel], out_put_channel); // Illumino il led del canale costantemente in base alla distanza rilevata
- analogWrite(pin_channel_RGB[id_channel], out_put_channel); // Illumino il led centrale con la stessa quantità di luce del led sensore
- }else{
- // Ripristino le condizioni di nessun interazione con l'utente
- analogWrite(pin_led_output[id_channel], 0); // Spengo il led perchè non ho interazione con l'utente
- analogWrite(pin_channel_RGB[id_channel], channel_RGB[id_channel]); // Illumino il led centrale con la quantità memorizata nella variabile globale
- }
- if(millis() >= timer_sensor[0]){
- // Verifico se è passato un tempo X dall'ultima lettura valida
- timer_sensor[id_channel] = millis()+time_block_color;
- int _last_increment = abs(_distance_temp[id_channel]-value_channel);
- if(_last_increment<=10 && value_channel!=255 && enable_sensor[id_channel]==true){
- enable_sensor[id_channel] = false; // Blocco il sensore fino a quando non ci sarà una variazione significativa (Impedisce continue memorizzazioni di colore dopvute al movimento instabile della mano)
- if(value_channel>=200) value_channel=255; // Imposto al massimo livello nel caso il valore sia superioread una certa soglia
- channel_RGB[id_channel] = value_channel; // Assegna l'attuale valore all'illuminazione globale
- blink_channel(id_channel); // Effettua un blink del canale per evidenziare la memorizazzione del colore
- set_color(); // Richiama la funzione di cambio colore globale
- }else if(_last_increment>=10){
- enable_sensor[id_channel] = true; // Sblocco il sensore perchè c'è stata una variazione significativa di colore
- }
- _distance_temp[id_channel] = out_put_channel; // Memorizzo il valore nella variabile globale esterna
- }
- }
- void set_color(){
- /*
- Questa funzione viene richiamata per settare il valore dell'illuminazione globale
- */
- Serial.print("ILLUMINAZIONE GLOBALE");
- for(int i=0;i<=2;i++){
- Serial.print(" : ");
- Serial.print(name_sensor[i]);
- Serial.print(" ");
- Serial.print(channel_RGB[i]);
- analogWrite(pin_channel_RGB[i], channel_RGB[i]); // Imposto nell'illuminazione globale i singoli valori per ogni canale RGB
- }
- Serial.println("");
- }
- void blink_channel(int id_channel){
- /*
- Questa funzione fa blinkare il canale RGB specificato
- */
- for(int i=0;i<=2;i++){
- analogWrite(pin_led_output[id_channel], 255); // Illumino il led costantemente in base alla distanza rilevata
- delay(50);
- analogWrite(pin_led_output[id_channel], 0); // Illumino il led costantemente in base alla distanza rilevata
- delay(50);
- }
- reset_screensaver(); // Resetto lo screensaver
- }
- void show_RGB(){
- /*
- Questa funzione fa un piccolo SHOW sui vari canali RGB
- */
- for(int i=0;i<=2;i++){
- analogWrite(pin_led_output[i], 0);
- analogWrite(pin_channel_RGB[i], 0);
- }
- for(int i=0;i<=2;i++){
- analogWrite(pin_led_output[i], 255);
- delay(1000);
- for(int x=0;x<=255;x++){
- analogWrite(pin_channel_RGB[i], x);
- delay(10);
- }
- analogWrite(pin_led_output[i], 0);
- analogWrite(pin_channel_RGB[i], 0);
- delay(500);
- }
- for(int i=10;i>=1;i--){
- int pausa = i*20;
- analogWrite(pin_led_output[2], 0);
- analogWrite(pin_led_output[0], 255);
- delay(pausa);
- analogWrite(pin_led_output[1], 255);
- analogWrite(pin_led_output[0], 0);
- delay(pausa);
- analogWrite(pin_led_output[2], 255);
- analogWrite(pin_led_output[1], 0);
- delay(pausa);
- }
- analogWrite(pin_led_output[2], 0);
- analogWrite(pin_channel_RGB[0], 255);
- analogWrite(pin_channel_RGB[1], 255);
- analogWrite(pin_channel_RGB[2], 255);
- delay(1000);
- for(int x=255;x>=0;x--){
- analogWrite(pin_channel_RGB[0], x);
- analogWrite(pin_channel_RGB[1], x);
- analogWrite(pin_channel_RGB[2], x);
- delay(10);
- }
- delay(500);
- analogWrite(pin_channel_RGB[0], channel_RGB[0]);
- analogWrite(pin_channel_RGB[1], channel_RGB[1]);
- analogWrite(pin_channel_RGB[2], channel_RGB[2]);
- }
- void check_button(){
- /*
- Questa funzione verifica lo stato dei 2 pulsanti
- */
- if(millis()>=timer_btn){
- if(digitalRead(pin_show) == LOW){
- // Ho attivato il bottone SHOW
- timer_btn = millis()+2000; // Inibisco la lettura del botone per 2 secondi
- show_RGB(); // Lancio lo show iniziale
- }
- if(digitalRead(pin_memory) == LOW){
- // Ho attivato il bottone MEMORY
- timer_btn = millis()+2000; // Inibisco la lettura del botone per 2 secondi
- write_memory(); // Scrivo il valore dell'attuale illuminazione in memoria
- for(int i=0;i<=2;i++){
- // Faccio fare un piccolo blink ai 3 canali per far capire all'utente che ho memoizzato il dato
- blink_channel(i);
- }
- }
- }
- }
- void reset_screensaver(){
- /*
- Questa funzione resetta lo screensaver
- */
- timer_screensaver = millis()+(time_out_screensaver*60000);
- }
- void check_screensaver(){
- /*
- Questa funzione verifica se è scaduto il tempo di screensaver dall'ultima interazione con l'utente
- */
- if(millis()>=timer_screensaver){
- show_RGB();
- reset_screensaver();
- }
- }
- void write_memory(){
- /*
- Questa funzione scrive nella EEPROM il valori dei 3 canali RGB dell'illuminazione globale
- */
- for(int i=0;i<=2;i++){
- EEPROM.write(RGB_Memory_Address[i], channel_RGB[i]); // Scrivo nell'indirizzo di memoria dedicato
- delay(100);
- }
- }
- void read_memory(){
- /*
- Questa funzione legge dalla EEPROM il valori dei 3 canali RGB dell'illuminazione globale
- */
- for(int i=0;i<=2;i++){
- channel_RGB[i] = EEPROM.read(RGB_Memory_Address[i]); // Scrivo nell'indirizzo di memoria dedicato
- Serial.print("Canale : ");
- Serial.print(name_sensor[i]);
- Serial.print(" ");
- Serial.println(channel_RGB[i]);
- delay(100);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement