Finalmente dopo una lunga assenza, in cui ero immerso nella realizzazione finale di questo mio progetto, CE L’HO FATTA!!!
Dopo mesi di progettazione, studi, ricerche e ostacoli vari, la RGB LED Lamp 1.0 by Toggio è realtà.
Posto subito il video che mostra il risultato definitivo ottenuto:
Ed ora una breve cronistoria.
Una delle cose che mi ha attirato di più quando ho sentito parlare di Arduino, era la luce, e in particolar modo ho sempre avuto il sogno di realizzare una lampada a LED RGB.
Niente di difficile, si potrebbe pensare… Solo che lungo questo percorso ho trovato diversi ostacoli.
Innanzitutto non ho trovato progetti completi in rete… Si trova qualcosa, ma, a mio avviso, con algoritmi fatti male, con poche spiegazioni, con metodi elaborati.
Io volevo una cosa semplice da regalare alla persona che amo e che mi ha dato una bellissima figlia…
Volevo qualcosa che avesse una luce abbastanza potente, senza però scaldare troppo. Volevo qualcosa che avesse la possibilità di scegliere il colore e non una semplice “color cycler”. Volevo qualcosa che fungesse anche da lampada standard. Ed infine volevo qualcosa che fosse modulare e upgradabile in futuro.
Dopo queste riflessioni, ho cominciato a studiare innanzitutto l’hardware. Non volevo usare l’Arduino UNO perchè mi sembrava eccessivamente grande per il mio progetto. Ho deciso quindi (e qui si potrebbe aprire un’enorme parentesi) di utilizzare una board non tanto diffusa ma a mio avviso eccezionale (tant’è che ne ho comprate 4 o 5): la Arduino Mini Pro.
(Resta inteso che nel progetto di questo post, può essere tranquillamente sostituita con una UNO o qualsiasi altra Arduino board.)
E’ una board estremamente piccola (18mm x 33mm), compatibile al 100% con Arduino Dumilanove, e a basso consumo. Esiste in quattro versioni: con Atmega328 a 3.3V e 5V e con Atmega168 a 3.3 e 5V.
Ho quindi optato per questo progetto per la versione a 5V con Atmega168. In definitiva si tratta di una soluzione molto economica (costa circa la metà dell’Arduino UNO), alquanto compatta e bella da vedere.
Ho poi pensato di utilizzare delle comodissime Strip LED RGB, che offrono numerosi vantaggi rispetto ad utilizzare led di potenza a 1W o a 3W: non scaldano, si alimentano a 12V e offrono una potenza fino a 13-14W per metro lineare.
Ogni canale può essere alimentato da un’uscita PWM di Arduino tramite un semplice transistor (nel mio caso ho usato dei BC337, ma per potenze superiori si possono usare altri transistor o addirittura dei Mosfet).
Ho quindi provveduto a costruire una specie di shield per la mia board. In pratica ho realizzato un circuito in cui la Arduino Mini Pro possa inserirsi con dei connettori strip ed essere eventualmente rimossa per aggiornare il firmware. Il tutto è stato progettato con Fritzing e realizzato da Fritzing Fab.
Il risultato finale del circuito stampato è il seguente:
Si possono notare le due file di fori dove andrà montata la Mini Pro… Praticamente è una shield al contrario 🙂
Ma facciamo un passo indietro e vediamo lo schema di circuito:
Spero sia abbastanza chiaro anche se non l’ho disegnato proprio benissimo!
In ogni caso il funzionamento è il seguente: I due potenziometri da 10k posti tra i +5V e la massa, sono i due input analogici che permettono di regolare la luminosità e altri parametri stabiliti dal software. Il deviatore a 3 posizioni SW2, permette di selezionare tre funzioni diverse per la lampada. Le uscite digitali 3,5,6 vanno a pilotare tramite un resistore i 3 transistori BC337 che andranno a dare corrente alle 3 uscite negative R,G,B della striscia a LED. Il positivo comune va ai +12V, mentre l’Arduino è alimentato tramite porta RAW (ingresso da 7V a 13V) tramite un diodo che oltre a fornire protezione da eventuale inversione di polarità, abbassa leggermente la tensione. SW1 è semplicemente il ponte dove andrà collegato un normalissimo interuttore di accensione.
Una volta saldati i vari componenti, connettori e potenziometri, montato il circuito, incapsulata la board Arduino, e montato il tutto dentro una scatola da elettricista, il risultato è quello della foto seguente:
La dimensione della scatola è di circa 10cmx10cmx7cm.
Per la parte superiore, ho utilizzato circa 70cm di striscia led RGB, per una potenza totale di circa 10W. Per farla stare tutta l’ho arrotolata intorno al perno di supporto di una campana da CD. Ho tagliato con un taglierino tale perno e l’ho incollato con dei distanziatori sopra la scatola. Ho poi incollato con della colla a caldo la striscia a led avvolgendola sul perno… Insomma un lavoro un po’ artigianale ma il risultato alla fine è il seguente:
Il vetro che si vede sulla scrivania leggermente spostato rispetto alla lampada, è il pezzo finale che manca: la copertura in vetro di una lampada IKEA, opportunamente fatta tagliare da un vetraio locale, affinché rimanga vuota sui due lati. Questa coperturà verrà infine appoggiata sopra la scatola da elettricista ed incollata, ottenendo il seguento risultato:
Mica male vero?
Ovviamente manca ancora la ciliegina sulla torta, una parte non meno importante: il software.
Il codice autoesplicativo è il seguente:
/* RGB Led Lamp 1.0a by Luca Soltoggio 15/03/2012 https://arduinoelettronica.wordpress.com/ */ int rpin = 3; // pin RED int gpin = 5; // pin GREEN int bpin = 6; // pin BLU unsigned int r=0, g=0, b=0,bm=0; // valori rgb e coefficiente divisore del blu unsigned int valh=0, vals=0, valv=0; // hue, saturation, value unsigned int sensorValue; // variabile che memorizza il valore dei potenziometri const int analogInPin = A0; // pin dei potenziometri const int analogInPin2 = A1; const int digitalInPin = 10; // pin del deviatore const int digitalInPin2= 11; int red[]={255,255,135}; // array con i valori RGB della funzione "Bianco" int green[]={157,255,158}; int blue[]={51,255,255}; boolean DIG1, DIG2; long previousMillis = 0; int i=0,j=0; int dl=0; // delay void setup() { pinMode(digitalInPin,INPUT); pinMode(digitalInPin2,INPUT); } void loop() { DIG1=digitalRead(digitalInPin); DIG2=digitalRead(digitalInPin2); if (DIG1) { bm=1.1; HSV_Game(); } else if (DIG2) { bm=1.9; RAINBOW_Game(); } else { bm=2.4; LIGHT_Game(); } analogWrite(rpin, r/1.09); // ROSSO analogWrite(gpin, g/1); // VERDE analogWrite(bpin, b/bm); // BLUE } // funzione di armonizzazione dei valori analogici tramite media aritmetica int SensorSmooth (int pin) { sensorValue=0; for (int i = 0; i<10; i++) { sensorValue+= analogRead(pin); } return int ((float)sensorValue/10+0.5); } // prima funzione: selezione del colore e della luminosità tramite potenziometri void HSV_Game() { valh = SensorSmooth(analogInPin); vals = 255; valv = SensorSmooth(analogInPin2); valh = map(valh,0,1023,0,359); valv = map(valv,0,1023,32,255); hsv2rgb(valh,vals,valv,r,g,b); } // seconda funzione: selezione di bianco caldo, bianco neutro e bianco freddo, oltre alla luminosità void LIGHT_Game() { valv = SensorSmooth(analogInPin2); valv = map(valv,0,1023,16,255); valh = SensorSmooth(analogInPin); if (valh=742) valh=2; if (valh>2) valh=1; r=red[valh]*valv/255; g=green[valh]*valv/255; b=blue[valh]*valv/255; } // terza funzione: selezione della velocità di rotazione tra tutti i colori e della luminosità void RAINBOW_Game() { dl = SensorSmooth(analogInPin); // tempo di pausa dl = map(dl,0,1023,1,100); valv = SensorSmooth(analogInPin2); valv = map(valv,0,1023,64,255); unsigned long currentMillis = millis(); switch (j) { case 0: r=255*valv/255; g=i*valv/255; b=0*valv/255; break; case 1: r=(255-i)*valv/255; g=255*valv/255; b=0*valv/255; break; case 2: r=0*valv/255; g=255*valv/255; b=i*valv/255; break; case 3: r=0*valv/255; g=(255-i)*valv/255; b=255*valv/255; break; case 4: r=i*valv/255; g=0*valv/255; b=255*valv/255; break; case 5: r=255*valv/255; g=0*valv/255; b=(255-i)*valv/255; } if (currentMillis-previousMillis > (long)(100-dl)) { // usa millis invece che delay previousMillis=currentMillis; i=i+1; if (i==256) { i=1; j=j+1; if (j==6) j=0; } } } /* Funzione che trasforma HSV in RGB (c) Elco Jacobs, E-atelier Industrial Design TU/e, July 2011 http://code.google.com/p/shiftpwm/source/browse/trunk/examples/ShiftPWM_Example1/hsv2rgb.cpp?r=3 */ void hsv2rgb(int hue, int sat, int val, unsigned int& r, unsigned int& g, unsigned int& b) { int H_accent = hue/60; int bottom = ((255 - sat) * val)>>8; int top = val; int rising = ((top-bottom) *(hue%60 ) ) / 60 + bottom; int falling = ((top-bottom) *(60-hue%60) ) / 60 + bottom; switch(H_accent) { case 0: r = top; g = rising; b = bottom; break; case 1: r = falling; g = top; b = bottom; break; case 2: r = bottom; g = top; b = rising; break; case 3: r = bottom; g = falling; b = top; break; case 4: r = rising; g = bottom; b = top; break; case 5: r = top; g = bottom; b = falling; break; } }
La pagine Fritzing del progetto (dove è possibile anche scaricare il codice sorgente) la trovate qui:
http://fritzing.org/projects/high-power-rgb-lamp-10-with-arduino/
Alla prossima!!!