Advertisement
Guest User

davideallume

a guest
Jan 11th, 2010
456
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.51 KB | None | 0 0
  1. /***************************************
  2.  RGB BLENDER PROJECT
  3.  Version 1.0 30/10/2009
  4.  
  5.  COPYRIGTH BNEXT S.R.L. & PROTOCUBE S.N.C.
  6.  AUTHOR MARCO BOMBARA & LEONARDO PERETTI
  7.  MAIL marco@bnext.it - info@protocube.it      
  8.  
  9.  DESCRIPTION :
  10.  
  11.  Il progetto gestisce una lampada formata da 3 canali RGB che si possono miscelare in maniera indipendente tramite il movimento della mano.
  12.  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.
  13.  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.
  14.  La miscelazione dei 3 canali può avvenire in contemporanea utilizzando 2 mano o più persone in quanto non ci sono blocchi del processore.
  15.  
  16.  FUNCTION :
  17.  
  18.  La lampada ha le seguenti funzioni :
  19.    - Miscelatura onthefly dei singoli canali RGB
  20.    - Indicazione di avvenuta memorizzazione colore con piccolo lampeggio del canale settato
  21.    - Funzione di SHOW iniziale all'accensione
  22.    - Funzione di salvataggio impostazioni colore tramite pulsante
  23.    - Richiamo dell'ultimo colore memorizzato in fase di accensione
  24.    - Pulsante per il lancio dello SHOW iniziale
  25.    - Funzione di Scrensaver
  26.  
  27.  MATERIAL :
  28.  
  29.  1 Arduino Duemilanove
  30.  1 Alimentatore 12V
  31.  1 lampada Ikea DIODER Multicolore
  32.  3 Sensori di prossimità SHARP GP2D120
  33.  6 MOS irf540
  34.  2 PCB Pushbutton, 12*12mm size
  35.  2 220 Ohm Resistors 1/4W
  36.  
  37.  EXTRA :
  38.  
  39.  La modellazione e la stampa del prototipo 3D della lampada è stata realizzata da PROTOCUBE S.N.C. www.protocube.it
  40.  
  41.  NOTE :
  42.  
  43.  Codice sviluppato in occasione del workshop Arduino - Torino Design Week 26-27-28/10/2009
  44.  
  45.  SPECIAL THANKS :
  46.  
  47.  Massimo Banzi
  48.  Davide Gomba
  49.  Enkel Bici
  50.  
  51.  
  52.  */
  53.  
  54.  
  55.  /*
  56. **************************************************
  57. * Spazio per le variabili di gestione della EEPROM
  58. **************************************************
  59. */
  60. #include <EEPROM.h> // Includo la libreria per la gestione della EEPROM per il salvataggio delle impostazioni
  61. int RGB_Memory_Address[]={0,1,2}; // Indica lo spazio di memoria in cui salvare le impostazioni del colore della lampada
  62.  
  63. /*
  64. *************************************************
  65. * Spazio per le variabili di gestione dei LED RGB
  66. *************************************************
  67. */
  68. char sensor_type[]="GP2D12"; // In alternativa al sensore di test 2Y0A21
  69. char name_sensor[]={'R','G','B'}; // Memorizzo il nome rapresentativo dei canali RGB
  70. int pin_sensor[]={0,1,2}; // Indico il PIN analogico in ingresso a cui è collegato il sesnore per ogni canale RGB
  71. int pin_led_output[]={9,10,11}; // Indico il PIN PWM in uscita a cui è collegato ogni canale RGB
  72. unsigned long timer_sensor[]={0,0,0}; // Memorizzo i timer per ogni canale RGB
  73. 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
  74. boolean enable_sensor[]={true,true,true}; // Variabile che contiene lo stato abilitato/disabilitato per ogni canale RGB
  75. int channel_RGB[]={0,0,0}; // Variabile che contiene le percentuali di RGB da utilizzare nell'illuminazione globale definite dai singoli sensori
  76. int pin_channel_RGB[]={3,5,6}; // Indico i PIN PWM in uscita a cui è collegato l'illuminazione globale RGB
  77. int _last_value_channel[]={0,0,0}; // Variabile temporanea per evitare i picchi
  78.  
  79. /*
  80. *************************************************
  81. * Spazio per le variabili di gestione dei Bottoni
  82. *************************************************
  83. */
  84. int pin_show = 7; // Pin a cui è collegato il pulsante per lanciare lo show
  85. int pin_memory = 12; // Pin a cui è collegato il pulsante per memorizzare il colore della lampada
  86. /*
  87. *******************************************************
  88. * Spazio per le variabili di gestione dello Screensaver
  89. *******************************************************
  90. */
  91. unsigned long timer_btn; // Timer che inibisce i pulsanti per un determinato tempo dopo il click
  92. int time_out_screensaver = 1; // Tempo oltre al quale parte lo screensaver se l'utente non ha fatto nulla (Espresso in minuti)
  93. unsigned long timer_screensaver; // Timer per la gestione della funzionalità screensaver
  94.  
  95. /*
  96. **********************
  97. * Inizio del programma
  98. **********************
  99. */
  100. void setup() {
  101.   Serial.begin(9600);
  102.   pinMode(pin_show, INPUT);
  103.   pinMode(pin_memory, INPUT);
  104.   for(int i=0;i<=2;i++){
  105.     pinMode(pin_led_output[i], OUTPUT); // Inizializzo i PIN dei singoli canali in uscita
  106.     delay(10);
  107.     pinMode(pin_channel_RGB[i], OUTPUT); // Inizializzo i PIN dell'illuminazione globale in uscita
  108.     delay(10);
  109.   }
  110.   read_memory(); // Leggo la memoria EEPROM interna per caricare l'ultimo salvataggio della luce impostata ed assegnarlo alla luce globale
  111.   delay(1000); // Effettuo una pausa all'avvio prima di lanciare la sequenza di inizializzazione
  112.   show_RGB(); // Lancio lo show iniziale
  113.   reset_screensaver(); // Resetto il timer dello screensaver
  114. }
  115. void loop() {
  116.   for(int i=0;i<=2;i++){
  117.     read_distance_sensor(i); // Ciclo nei 3 canali per leggere i valori dei sensori
  118.   }
  119.   check_button(); // Leggo lo stato dei bottoni
  120.   check_screensaver(); // Verifico lo screensaver
  121. }
  122.  
  123. void read_distance_sensor(int id_channel){
  124.     /*
  125.     Questa funzione serve a misurare la distanza della mano dal sensore per regolare la quantità di colore da miscelare
  126.     il valore "id_channel" rappresenta il riferimento al canale RGB da utilizzare rispetto alle variabili estrene definite all'inizio
  127.    
  128.     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
  129.    
  130.     */
  131.     int inner_distance; // Indica la distanza minima di una lettura valida prima di cadere nella zona morta
  132.     int outer_distance; // Indica il distanza massima di una lettura
  133.     if(sensor_type=="GP2D12"){
  134.       inner_distance = 20;
  135.       outer_distance = 500;
  136.     }else{
  137.       // Valori validi per il sensore di test SHARP 2Y0A21
  138.       inner_distance = 20;
  139.       outer_distance = 650;
  140.      }
  141.    
  142.     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.
  143.     int max_value = 220; // Indica il valore massimo ottenibile con il rappirto di scalatura impostato
  144.     int time_block_color = 350; // Indica quanti millisecondi devono passare per bloccare il colore
  145.     int value_channel; // Rappresenta il valore PWM da memorizzare per questo canale RGB
  146.     int out_put_channel; // Rappresenta il valore PWM in uscita sul LED quando si muove la manso sul sensore
  147.     boolean active_channel = false; // Indica se l'utente sta lavorando sulla variazione di un canale oppure no
  148.    
  149.  
  150.     value_channel = analogRead(pin_sensor[id_channel]); // Leggo il valore del sensore
  151.     if(abs(_last_value_channel[id_channel]-value_channel)>=50){
  152.       // In questo punto ho dei pichi dovuti a false letture, quindi non faccio nulla
  153.     }else{
  154.       _last_value_channel[id_channel]=value_channel; // Memorizzo il valore attuale come valido nella variabile temporanea
  155.     }
  156.      
  157.     if(value_channel>=100){  
  158.       if(abs(_last_value_channel[id_channel]>=100)){
  159.         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
  160.       }  
  161.     }
  162.     _last_value_channel[id_channel] = value_channel; // Memorizzo il valore attuale come valido nella variabile temporanea
  163.    
  164.     value_channel = constrain(value_channel, inner_distance, outer_distance); // Limito il valore in un range predefinito per evitare le zone morte
  165.     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
  166.     value_channel = constrain(value_channel, 0, 255); // Limito nuovamente il valore per evitare eventuali picchi oltre il 255
  167.      
  168.  
  169.     value_channel = value_channel;
  170.     out_put_channel = value_channel;
  171.     if(value_channel >= max_value){
  172.       value_channel=255; // Taglio al di sopra di una certa soglia per spegnere il led quando esco con la mano      
  173.       out_put_channel = 0;
  174.     }
  175.     if(value_channel <= min_value){
  176.       value_channel=0; // Taglio al di sotto di una certa soglia per evitare di andare nella zona morta con la mano
  177.       out_put_channel = 0;
  178.     }
  179.  
  180.      
  181.      if(active_channel == true){
  182.        // Vario lo stato dei LED perchè l'utente sta interagendo
  183.        analogWrite(pin_led_output[id_channel], out_put_channel); // Illumino il led del canale costantemente in base alla distanza rilevata
  184.        analogWrite(pin_channel_RGB[id_channel], out_put_channel); // Illumino il led centrale con la stessa quantità di luce del led sensore
  185.      }else{
  186.        // Ripristino le condizioni di nessun interazione con l'utente
  187.        analogWrite(pin_led_output[id_channel], 0); // Spengo il led perchè non ho interazione con l'utente
  188.        analogWrite(pin_channel_RGB[id_channel], channel_RGB[id_channel]); // Illumino il led centrale con la quantità memorizata nella variabile globale
  189.      }
  190.      if(millis() >= timer_sensor[0]){
  191.         // Verifico se è passato un tempo X dall'ultima lettura valida
  192.         timer_sensor[id_channel] = millis()+time_block_color;
  193.         int _last_increment = abs(_distance_temp[id_channel]-value_channel);
  194.         if(_last_increment<=10 && value_channel!=255 && enable_sensor[id_channel]==true){
  195.             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)
  196.             if(value_channel>=200) value_channel=255; // Imposto al massimo livello nel caso il valore sia superioread una certa soglia                    
  197.             channel_RGB[id_channel] = value_channel; // Assegna l'attuale valore all'illuminazione globale
  198.             blink_channel(id_channel); // Effettua un blink del canale per evidenziare la memorizazzione del colore
  199.             set_color(); // Richiama la funzione di cambio colore globale
  200.        }else if(_last_increment>=10){        
  201.             enable_sensor[id_channel] = true; // Sblocco il sensore perchè c'è stata una variazione significativa di colore
  202.          }
  203.             _distance_temp[id_channel] = out_put_channel; // Memorizzo il valore nella variabile globale esterna
  204.      }
  205. }
  206.  
  207. void set_color(){
  208.   /*
  209.   Questa funzione viene richiamata per settare il valore dell'illuminazione globale
  210.  
  211.   */
  212.   Serial.print("ILLUMINAZIONE GLOBALE");
  213.   for(int i=0;i<=2;i++){
  214.     Serial.print(" : ");
  215.     Serial.print(name_sensor[i]);
  216.     Serial.print(" ");
  217.     Serial.print(channel_RGB[i]);  
  218.     analogWrite(pin_channel_RGB[i], channel_RGB[i]); // Imposto nell'illuminazione globale i singoli valori per ogni canale RGB
  219.   }
  220.    Serial.println("");
  221. }
  222.  
  223. void blink_channel(int id_channel){
  224.   /*
  225.   Questa funzione fa blinkare il canale RGB specificato
  226.   */
  227.   for(int i=0;i<=2;i++){
  228.     analogWrite(pin_led_output[id_channel], 255); // Illumino il led costantemente in base alla distanza rilevata
  229.     delay(50);  
  230.     analogWrite(pin_led_output[id_channel], 0); // Illumino il led costantemente in base alla distanza rilevata
  231.     delay(50);
  232.   }
  233.   reset_screensaver(); // Resetto lo screensaver
  234. }
  235.  
  236. void show_RGB(){
  237.   /*
  238.   Questa funzione fa un piccolo SHOW sui vari canali RGB
  239.   */
  240.   for(int i=0;i<=2;i++){
  241.     analogWrite(pin_led_output[i], 0);
  242.     analogWrite(pin_channel_RGB[i], 0);
  243.   }
  244.   for(int i=0;i<=2;i++){
  245.     analogWrite(pin_led_output[i], 255);
  246.     delay(1000);
  247.     for(int x=0;x<=255;x++){  
  248.       analogWrite(pin_channel_RGB[i], x);
  249.       delay(10);
  250.     }
  251.     analogWrite(pin_led_output[i], 0);
  252.     analogWrite(pin_channel_RGB[i], 0);
  253.     delay(500);
  254.   }
  255.   for(int i=10;i>=1;i--){
  256.     int pausa = i*20;
  257.     analogWrite(pin_led_output[2], 0);
  258.     analogWrite(pin_led_output[0], 255);
  259.     delay(pausa);
  260.     analogWrite(pin_led_output[1], 255);
  261.     analogWrite(pin_led_output[0], 0);
  262.     delay(pausa);
  263.     analogWrite(pin_led_output[2], 255);
  264.     analogWrite(pin_led_output[1], 0);
  265.     delay(pausa);
  266.   }
  267.   analogWrite(pin_led_output[2], 0);
  268.  
  269.   analogWrite(pin_channel_RGB[0], 255);
  270.   analogWrite(pin_channel_RGB[1], 255);
  271.   analogWrite(pin_channel_RGB[2], 255);
  272.   delay(1000);
  273.   for(int x=255;x>=0;x--){  
  274.     analogWrite(pin_channel_RGB[0], x);
  275.     analogWrite(pin_channel_RGB[1], x);
  276.     analogWrite(pin_channel_RGB[2], x);
  277.     delay(10);
  278.   }
  279.   delay(500);
  280.  
  281.   analogWrite(pin_channel_RGB[0], channel_RGB[0]);
  282.   analogWrite(pin_channel_RGB[1], channel_RGB[1]);
  283.   analogWrite(pin_channel_RGB[2], channel_RGB[2]);
  284. }
  285.  
  286. void check_button(){
  287.   /*
  288.   Questa funzione verifica lo stato dei 2 pulsanti
  289.   */  
  290.   if(millis()>=timer_btn){
  291.     if(digitalRead(pin_show) == LOW){
  292.       // Ho attivato il bottone SHOW
  293.       timer_btn = millis()+2000; // Inibisco la lettura del botone per 2 secondi
  294.       show_RGB(); // Lancio lo show iniziale
  295.     }
  296.     if(digitalRead(pin_memory) == LOW){
  297.       // Ho attivato il bottone MEMORY
  298.       timer_btn = millis()+2000; // Inibisco la lettura del botone per 2 secondi
  299.       write_memory(); // Scrivo il valore dell'attuale illuminazione in memoria
  300.       for(int i=0;i<=2;i++){
  301.         // Faccio fare un piccolo blink ai 3 canali per far capire all'utente che ho memoizzato il dato
  302.         blink_channel(i);
  303.       }
  304.     }
  305.   }
  306. }
  307.  
  308. void reset_screensaver(){
  309.   /*
  310.   Questa funzione resetta lo screensaver
  311.   */
  312.   timer_screensaver = millis()+(time_out_screensaver*60000);
  313. }
  314.  
  315. void check_screensaver(){
  316.   /*
  317.   Questa funzione verifica se è scaduto il tempo di screensaver dall'ultima interazione con l'utente
  318.   */
  319.   if(millis()>=timer_screensaver){
  320.     show_RGB();
  321.     reset_screensaver();  
  322.   }
  323. }
  324.  
  325. void write_memory(){
  326.   /*
  327.   Questa funzione scrive nella EEPROM il valori dei 3 canali RGB dell'illuminazione globale
  328.   */  
  329.   for(int i=0;i<=2;i++){
  330.     EEPROM.write(RGB_Memory_Address[i], channel_RGB[i]); // Scrivo nell'indirizzo di memoria dedicato
  331.     delay(100);
  332.   }  
  333. }
  334.  
  335. void read_memory(){
  336.   /*
  337.   Questa funzione legge dalla EEPROM il valori dei 3 canali RGB dell'illuminazione globale
  338.   */  
  339.   for(int i=0;i<=2;i++){
  340.     channel_RGB[i] = EEPROM.read(RGB_Memory_Address[i]); // Scrivo nell'indirizzo di memoria dedicato
  341.     Serial.print("Canale : ");
  342.     Serial.print(name_sensor[i]);
  343.     Serial.print(" ");
  344.     Serial.println(channel_RGB[i]);
  345.     delay(100);
  346.   }  
  347. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement