So der erste Prototyp2013-03-31-14-04-51
von meiner LED-RGB-Lamp ist fertig ;o)

Das Ergebnis gefällt mir auch schon sehr ….
Das Einzige was mich hier jetzt noch stört das die widerstände
zu viel Spannung killen müssen ….
Und daher werden sie mir zu warm.

Also wir wohl doch noch eine 5 Volt Version kommen müssen 😉

Es wurden verwendet:

  •  Arduino Nano
  • Serial Bluetooth Adapter
  • 3Watt RGB-Led
  • Und der übliche Kram 😉

 

Und hier jetzt noch die Schaltung:

led_lamp_12_volt_version_mit_spannungsregulierung_fuer_den_arduino_steckplatine

#Edit:

Jetzt habe ich auch die 5 Volt Version fertig …
Die Schaltung wird wie erwartet nicht annähend so heiß wie der 12 Volt Version!
Daher rate ich jeden der das hier nachbauen will zur 5 Volt Version, das die 12 Volt Version schon grenzwertig war.

Hier die neue Schaltung:

led_lamp_5_volt_version_steckplatine

Und ein Video…… 😉

https://youtu.be/K45k77karOY

Der Code ist nicht von mir!

Hier die Quelle: http://www.myledlamp.net
Und die App: https://play.google.com/store/apps/details?id=com.mgs.LEDLamp

#include <TimedAction.h>
#include <EEPROM.h>

//---------------------------
// LED(Lamp)
// Firmware by Alessandro Carrara - Via Molino Ronchin, 6 30174 Zelarino (Venice) Italy
// web: http://www.myledlamp.net
// mail: info@myledlamp.net
// LICENSE: GPL3
//---------------------------

//--------------------------------------------------
// formato messaggio *CcVxxx#
//                   |--------------------------- start messaggio
//                    |-------------------------- flag che precede il comando (fisso a C)
//                     |------------------------- valore del comando (fisso a 1chr, exemp: H accendi, L spegni, S imposta colore)
//                      |------------------------ flag valore (fisso a 1chr, exemp: R valore colore R, G B...)
//                       |||--------------------- valore (stringa lunga a piacere)
//                          |-------------------- end messaggio
//--------------------------------------------------

//funzioni multi threading
TimedAction mainAction = TimedAction(60, main1);                         //main thread (ricezione comandi)
TimedAction karmafade_effectAction = TimedAction(50, karmafade_effect);  //karmafade thread
TimedAction candle_effectAction = TimedAction(50, candle_effect);        //candleeffect thread

// costanti versione
const String myHWName = "LED(Lamp) 1";  // nome dispositivo hardware
const String myHWVer =  "v1.0";  // versione dispositivo hardware
const String myFWVer =  "v0.7";  // versione firmware

// configurazione hardware
const int ledPin = 13; // the pin that the LED is attached to
const int led_R = 9;    // LED Rosso (atmega pin 11) - in futuro 9*
const int led_G = 10;    // LED Verde (atmega pin 12) - in futuro 10*
const int led_B = 11;    // LED Blu (atmega pin 5)    - in futuro 11*
//* utilizzare i pin 9 10 11 in quanto hanno la stessa freq. pwm.

//------------------------------------
// costanti relative al formato del messaggio in ricezione dal dispositivo
const String MSG_START = "*";         // flag start messaggio
const String MSG_END = "#";           // flag end messaggio
const int MSG_MAX = 16;             // lunghezza massima della stringa messaggio (utilizzato per non rimanere in loop in caso di messaggio errato
const String MSG_COMMAND = "C";      // flag che precede il codice comando
const String MSG_VALUE   = "V";      // flag che precede il valore
const String MSG_INFO = "I";         // flag che precede il valore di ritorno

//------------------------------------
// codici comando (set)
// settaggio valori
const String MSG_SET_STATE = "1"; 
const String MSG_SET_RGB_COLOR = "2"; 
const String MSG_SET_BRIGHTNESS = "3"; 
const String MSG_SET_RGB_WBT = "4";  // White Balance Threshold
const String MSG_GOTO_RGB_COLOR = "5";  // va al colore in modo transizione.
const String MSG_GOTO_BRIGHTNESS = "6";  // modifica luminosità in modo transizione.

// settaggio effetti
const String MSG_SET_EFFECT = "20"; 
// settaggio velocità effetti
const String MSG_SET_KARMAFADE_VELOCITY = "50"; 
const String MSG_SET_CANDLEEFFECT_VELOCITY = "51"; 
// salvataggio in memoria
const String MSG_SET_DEFAULT_RGB_COLOR = "60";
const String MSG_SET_DEFAULT_BRIGHTNESS = "61"; 
const String MSG_SET_DEFAULT_KARMAFADE_VELOCITY = "62"; 
const String MSG_SET_DEFAULT_CANDLEEFFECT_VELOCITY = "63"; 
// ripristino impostazioni di fabbrica
const String MSG_SET_DEVICE_TO_DEFAULT = "90"; 

// codice comando (get)
const String MSG_GET_INFO = "100";
// valori post comando get
const String MSG_VALUE_STATE = MSG_SET_STATE; 
const String MSG_VALUE_RGB_COLOR = MSG_SET_RGB_COLOR; 
const String MSG_VALUE_BRIGHTNESS = MSG_SET_BRIGHTNESS; 
const String MSG_VALUE_RGB_WBT = MSG_SET_RGB_WBT; 
const String MSG_VALUE_DEFAULT_RGB_COLOR = MSG_SET_DEFAULT_RGB_COLOR; 
const String MSG_VALUE_DEFAULT_BRIGHTNESS = MSG_SET_DEFAULT_BRIGHTNESS; 

const String MSG_VALUE_KARMAFADE_VELOCITY = MSG_SET_KARMAFADE_VELOCITY; 
const String MSG_VALUE_CANDLEEFFECT_VELOCITY = MSG_SET_CANDLEEFFECT_VELOCITY; 
const String MSG_VALUE_DEFAULT_KARMAFADE_VELOCITY = MSG_SET_DEFAULT_KARMAFADE_VELOCITY; 
const String MSG_VALUE_DEFAULT_CANDLEEFFECT_VELOCITY = MSG_SET_DEFAULT_CANDLEEFFECT_VELOCITY; 
const String MSG_VALUE_HW_NAME = "100";
const String MSG_VALUE_HW_VER = "101";
const String MSG_VALUE_FW_VER = "102";

// stati di funzionamento
const String STATE_OFF = "0";            // valore relativo a lampada spenta
const String STATE_ON = "1";             // valore relativo a lampada accesa
const String STATE_PAUSE = "2";          // valore relativo a lampada spenta
const String STATE_RESUME = "3";         // valore relativo a lampada accesa
const String STATE_KARMAFADE_EFFECT = "20";     // valore relativo a effetto karmafade in esecuzione
const String STATE_CANDLEEFFECT = "21";  // valore relativo a effetto candle in esecuzione

//------------------------------------
// mappa memoria eprom default fabbrica
const int EPROM_ADDR_FIRST_TIME_EXEC = 0;           // indirizzo memoria in cui è scritto se il dispositivo è la priva volta che viene lanciato
const int EPROM_ADDR_VALUE_R = 1;           // indirizzo memoria in cui è scritto il valore di default del led rosso
const int EPROM_ADDR_VALUE_G = 2;           // indirizzo memoria in cui è scritto il valore di default del led verde
const int EPROM_ADDR_VALUE_B = 3;           // indirizzo memoria in cui è scritto il valore di default del led blu
const int EPROM_ADDR_VALUE_WBT_R = 11;           // indirizzo memoria in cui è scritto il valore di Threshold per il WB del colore Rosso
const int EPROM_ADDR_VALUE_WBT_G = 12;           // indirizzo memoria in cui è scritto il valore di Threshold per il WB del colore Verde
const int EPROM_ADDR_VALUE_WBT_B = 13;           // indirizzo memoria in cui è scritto il valore di Threshold per il WB del colore Blu
const int EPROM_ADDR_VALUE_BRIGHTNESS = 21;  // indirizzo memoria in cui è scritto il valore della luminosità
const int EPROM_ADDR_VALUE_KARMAFADE_VELOCITY = 22;    // indirizzo memoria in cui è scritto il valore della Velocità dell'effetto karma
const int EPROM_ADDR_VALUE_CANDLEEFFECT_VELOCITY = 23;    // indirizzo memoria in cui è scritto il valore della Velocità dell'effetto candle

//------------------------------------
// valori di default
// colori
const int DEFAULT_VALUE_R = 255;
const int DEFAULT_VALUE_G = 50;
const int DEFAULT_VALUE_B = 50;
// Threshold per il White Balance
const int DEFAULT_VALUE_WBT_R = 105;
const int DEFAULT_VALUE_WBT_G = 0;
const int DEFAULT_VALUE_WBT_B = 176;
// luminosità ed effetti
const int DEFAULT_VALUE_BRIGHTNESS = 125;
const int DEFAULT_VALUE_KARMAFADE_VELOCITY = 128;
const int DEFAULT_VALUE_CANDLEEFFECT_VELOCITY = 128;

//------------------------------------
// costanti relative agli stati di funzionamento
String State;                            // Variabile Stato corrente
String PreState;                         // Variabile Stato precedente la pausa

//------------------------------------
// valori globali RGB
int global_R_Color = 0;
int global_G_Color = 0;
int global_B_Color = 0;

//------------------------------------
// valori globali di Threshold per i colori primari utilizzati per il white balance.
int global_WB_R_Threshold = 0;
int global_WB_G_Threshold = 0;
int global_WB_B_Threshold = 0;

//------------------------------------
// valori globali precedenti alla pausa
int pre_global_R_Color = 0;
int pre_global_G_Color = 0;
int pre_global_B_Color = 0;

//------------------------------------
// valori globali Regolazioni
int global_Brightness = 0;
int global_KarmaFadeVelocity = 0;
int global_CandleEffectVelocity = 0;

//------------------------------------
// valori per effetto karmafade
int kf_fadeValueR = 0;   // valore analogico sul led1
int kf_fadeValueG = 0;  // valore analogico sul led2
int kf_fadeValueB = 0;  // valore analogico sul led3

int kf_minfadeValueR = 0;  // valore fade minimo del led1
int kf_minfadeValueG = 0;  // valore fade minimo del led2
int kf_minfadeValueB = 0;  // valore fade minimo del led3

int kf_maxfadeValueR = 255;  // valore fade massimo del led1
int kf_maxfadeValueG = 255;  // valore fade massimo del led2
int kf_maxfadeValueB = 255;  // valore fade massimo del led3

int kf_fadeDirectionR = 0;  // direzione del fade del led1 (0 = aumenta, 1 = diminuisce)
int kf_fadeDirectionG = 0; // direzione del fade del led2 (0 = aumenta, 1 = diminuisce)
int kf_fadeDirectionB = 0; // direzione del fade del led3 (0 = aumenta, 1 = diminuisce)

int kf_timeFadeR = 10;  // tempo di fade per ogni salita o discesa
int kf_timeFadeG = 5;  // tempo di fade per ogni salita o discesa
int kf_timeFadeB = 5;  // tempo di fade per ogni salita o discesa

unsigned long kf_time;  // variabile tempo da quando è in esecuzione il programma
unsigned long kf_timeLedR; // variabile tempo utilizzata per il led1
unsigned long kf_timeLedG; // variabile tempo utilizzata per il led2
unsigned long kf_timeLedB; // variabile tempo utilizzata per il led3

//------------------------------------
// valori per effetto candeleffect
unsigned long  ce_time;
unsigned long  ce_timeLedR;
unsigned long  ce_timeLedG;

int ce_timeFadeR = 5;  // tempo di fade per ogni salita o discesa
int ce_timeFadeG = 5;  // tempo di fade per ogni salita o discesa

//---------------------------------------------------------------------------------------

void setup() {

  for (int i = 0; i < 1024; i++)
  EEPROM.write(i, 0);
  digitalWrite(13, HIGH);

  karmafade_effectAction.disable();   // disattivazione thread effetti
  candle_effectAction.disable();
  //pinMode(ledPin, OUTPUT);    // initialize the LED pin as an output:

  Serial.begin(115200);    // initialize serial communication:
  startDevice();    // esegue check iniziali ed accende i led

  Serial.print("ready\n");

}

void loop() {
  mainAction.check();
  karmafade_effectAction.check();
  candle_effectAction.check();
}

//--------------------------------------------------------
// funzione che riceve ed elabora la stringa comando.
void main1(){
  mainAction.disable();
  if (Serial.available()){
    main2();
  }
  mainAction.enable();
}

void main2(){

  char inString[MSG_MAX+1];
  String srlC;
  int inCount=0;
  String Command="";
  String Value="";
  int nValue=0;
  boolean waitCommand = false;
  boolean waitValue = false;

  do {
    srlC = "";
    inString[inCount] = Serial.read();
    srlC = (String)inString[inCount];

    if (srlC == MSG_START){

    }else if(srlC == MSG_COMMAND){
      waitCommand = true;
      waitValue   = false;
    }else if (srlC == MSG_VALUE){
      waitValue   = true;
      waitCommand = false;
    }else if (srlC == MSG_END){
      break;
    }else{
      if (waitCommand){
        Command.concat(inString[inCount]);
      }
      if (waitValue){
        Value.concat(inString[inCount]);
      }
    }

  } while (++inCount < MSG_MAX);

  //Serial.print
  //Serial.println("CMD:" + Command + " VAL:" + Value);

  // lancia esecuzione comandi
  if(Command != ""){
    executeCommand(Command, Value);
  }

}

//--------------------------------------------------------
// funzione che esegue i comandi ricevuti
void executeCommand(String Command, String Value){

  // in caso di nuovo comando disattivo il thread fade
  // tranne nel caso di richiesta info sul device
  if (Command != MSG_GET_INFO & 
      Command != MSG_SET_BRIGHTNESS &
      Command != MSG_SET_KARMAFADE_VELOCITY & 
      Command != MSG_SET_CANDLEEFFECT_VELOCITY){
    karmafade_effectAction.disable();
    candle_effectAction.disable();
  }

  // funzioni invio stato  
  if (Command == MSG_GET_INFO) {
    // invia informazioni sulla versione
      if (Value == MSG_VALUE_HW_NAME){
        SendToDevice(MSG_VALUE_HW_NAME +
                     MSG_VALUE + 
                     myHWName);
      }
      if (Value == MSG_VALUE_HW_VER){
        SendToDevice(MSG_VALUE_HW_VER +
                     MSG_VALUE + 
                     myHWVer);
      }
      if (Value == MSG_VALUE_FW_VER){
        SendToDevice(MSG_VALUE_FW_VER +
                     MSG_VALUE + 
                     myFWVer);
      }
      // invia stato lampada 
      if (Value == MSG_VALUE_STATE){
        SendToDevice(MSG_VALUE_STATE + 
                     MSG_VALUE + 
                     State);
      }
      // invia valori RGB globali
      if (Value == MSG_VALUE_RGB_COLOR){
        if (State == STATE_PAUSE) {
          SendToDevice(MSG_VALUE_RGB_COLOR + 
                       MSG_VALUE + 
                       addZeroToLeft((String)pre_global_R_Color) +
                       addZeroToLeft((String)pre_global_G_Color) + 
                       addZeroToLeft((String)pre_global_B_Color));
        }else{
          SendToDevice(MSG_VALUE_RGB_COLOR + 
                       MSG_VALUE + 
                       addZeroToLeft((String)global_R_Color) +
                       addZeroToLeft((String)global_G_Color) + 
                       addZeroToLeft((String)global_B_Color));
        }
      }
      // invia valore luminosità
      if (Value == MSG_VALUE_BRIGHTNESS){
        SendToDevice(MSG_VALUE_BRIGHTNESS + 
                     MSG_VALUE + 
                     addZeroToLeft((String)global_Brightness));
      }
      // invia valore White Balnce Threshold
      if (Value == MSG_VALUE_RGB_WBT){
          SendToDevice(MSG_VALUE_RGB_WBT + 
                       MSG_VALUE + 
                       addZeroToLeft((String)global_WB_R_Threshold) +
                       addZeroToLeft((String)global_WB_G_Threshold) + 
                       addZeroToLeft((String)global_WB_B_Threshold));
      }
      // invia valore velocità 
      if (Value == MSG_VALUE_KARMAFADE_VELOCITY){
        SendToDevice(MSG_VALUE_KARMAFADE_VELOCITY + 
                     MSG_VALUE + 
                     addZeroToLeft((String)global_KarmaFadeVelocity));
      }
      // invia valore velocità
      if (Value == MSG_VALUE_CANDLEEFFECT_VELOCITY){
        SendToDevice(MSG_VALUE_CANDLEEFFECT_VELOCITY + 
                     MSG_VALUE + 
                     addZeroToLeft((String)global_CandleEffectVelocity));
      }
      // invia valori RGB di default
      if (Value == MSG_VALUE_DEFAULT_RGB_COLOR){
        SendToDevice(MSG_VALUE_DEFAULT_RGB_COLOR + 
                     MSG_VALUE + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_R)) + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_G)) + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_B)));
      }
      // invia valori Brightness di default
      if (Value == MSG_VALUE_DEFAULT_BRIGHTNESS){
        SendToDevice(MSG_VALUE_DEFAULT_BRIGHTNESS + 
                     MSG_VALUE + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_BRIGHTNESS)));
      }
      // invia valori Velocity per karma
      if (Value == MSG_VALUE_DEFAULT_KARMAFADE_VELOCITY){
        SendToDevice(MSG_VALUE_DEFAULT_KARMAFADE_VELOCITY + 
                     MSG_VALUE + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_KARMAFADE_VELOCITY)));
      }
      // invia valori Velocity per candle
      if (Value == MSG_VALUE_DEFAULT_CANDLEEFFECT_VELOCITY){
        SendToDevice(MSG_VALUE_DEFAULT_CANDLEEFFECT_VELOCITY + 
                     MSG_VALUE + 
                     addZeroToLeft((String)EEPROM.read(EPROM_ADDR_VALUE_CANDLEEFFECT_VELOCITY)));
      }

  }else if (Command == MSG_SET_STATE) {
      // accende i led secondo i valori attualmente impostati
      if (Value == STATE_ON){
        lightOn();

      } else if (Value == STATE_OFF){
        lightOff();   

      } else if (Value == STATE_PAUSE) {
        pause();   

      } else if (Value == STATE_RESUME) {
        resume();   

      } else if (Value == STATE_KARMAFADE_EFFECT){
         setup_karmafade_effect();

      } else if (Value == STATE_CANDLEEFFECT){
        setup_candle_effect();
      }

  // Imposta un colore
  } else if (Command == MSG_SET_RGB_COLOR) {
      State = STATE_ON;
      int R_Color = extractColor(Value, 1);
      int G_Color = extractColor(Value, 2);
      int B_Color = extractColor(Value, 3);
      SetRGBColor(R_Color, G_Color, B_Color);

  // Imposta un colore (modalità transizione)
  } else if (Command == MSG_GOTO_RGB_COLOR) {
      State = STATE_ON;
      int R_Color = extractColor(Value, 1);
      int G_Color = extractColor(Value, 2);
      int B_Color = extractColor(Value, 3);
      transictionFromTo (global_R_Color, global_G_Color, global_B_Color, R_Color, G_Color, B_Color, 1);

  // Imposta e salva i valori di Threshold per il White Balance
  } else if (Command == MSG_SET_RGB_WBT) {
      global_WB_R_Threshold = extractColor(Value, 1);
      global_WB_G_Threshold = extractColor(Value, 2);
      global_WB_B_Threshold = extractColor(Value, 3);
      // li scrivo nella eprom
      EEPROM.write(EPROM_ADDR_VALUE_WBT_R, global_WB_R_Threshold);
      EEPROM.write(EPROM_ADDR_VALUE_WBT_G, global_WB_G_Threshold);
      EEPROM.write(EPROM_ADDR_VALUE_WBT_B, global_WB_B_Threshold);
      // imposto nuovamente il colore
      SetRGBColor(global_R_Color, global_G_Color, global_B_Color);

  // Imposta i valori di luminosità
  } else if (Command == MSG_SET_BRIGHTNESS) {
      global_Brightness = stringToInt(Value);
      SetRGBColor(global_R_Color, global_G_Color, global_B_Color);

  // Imposta i valori di luminosità (modalità transizione)
  } else if (Command == MSG_GOTO_BRIGHTNESS) {
      goto_Brightness(stringToInt(Value));

  // Imposta i valori di velocità effetto karma
  } else if (Command == MSG_SET_KARMAFADE_VELOCITY) {
      global_KarmaFadeVelocity = stringToInt(Value);

  // Imposta i valori di velocità effetto candle
  } else if (Command == MSG_SET_CANDLEEFFECT_VELOCITY) {
      global_CandleEffectVelocity = stringToInt(Value);

  // Imposta e salva i valori di colore di accensione di default
  } else if (Command == MSG_SET_DEFAULT_RGB_COLOR) {
      int R_Color = extractColor(Value, 1);
      int G_Color = extractColor(Value, 2);
      int B_Color = extractColor(Value, 3);
      EEPROM.write(EPROM_ADDR_VALUE_R, R_Color);
      EEPROM.write(EPROM_ADDR_VALUE_G, G_Color);
      EEPROM.write(EPROM_ADDR_VALUE_B, B_Color);

  // Salva il valore di luminosità di default
  } else if (Command == MSG_SET_DEFAULT_BRIGHTNESS) {
      EEPROM.write(EPROM_ADDR_VALUE_BRIGHTNESS, stringToInt(Value));

  // Salva il valore di velocità karma di default
  } else if (Command == MSG_SET_DEFAULT_KARMAFADE_VELOCITY) {
      EEPROM.write(EPROM_ADDR_VALUE_KARMAFADE_VELOCITY, stringToInt(Value));

  // Salva il valore di velocità candle di default
  } else if (Command == MSG_SET_DEFAULT_CANDLEEFFECT_VELOCITY) {
      EEPROM.write(EPROM_ADDR_VALUE_CANDLEEFFECT_VELOCITY, stringToInt(Value));

  // Comando che esegue un soft reset di tutte le impostazioni (vengono azzerate le preferense utente)
  } else if (Command == MSG_SET_DEVICE_TO_DEFAULT) {
      setDeviceToDefault();
  }

}

int extractColor(String Value, int indxColor){
  //inxColor 1=R 2=G 3=B
  String Color;

  if (indxColor == 1){
      Color = Value.substring(0, 3);
  } else if(indxColor == 2){
      Color = Value.substring(3, 6);
  } else if(indxColor == 3){
      Color = Value.substring(6, 9);
  }
  return stringToInt(Color);
}

//--------------------------------------------------------
// accende i led secondo i valori globali
void lightOn(){
    State = STATE_ON;
    digitalWrite(ledPin, HIGH); //test

    transictionFromTo(global_R_Color, global_G_Color, global_B_Color, pre_global_R_Color, pre_global_G_Color , pre_global_B_Color, 8);
}

//--------------------------------------------------------
// accende i led secondo i valori preventivamente salvati
void lightOff(){
    State = STATE_OFF;
    digitalWrite(ledPin, LOW); //test

    transictionFromTo(global_R_Color, global_G_Color , global_B_Color, 0, 0, 0, 8);
}

//--------------------------------------------------------
// mette in pausa la funzione corrente
void pause(){

  digitalWrite(ledPin, LOW); //test

  // salvo lo stato precendete (serve per il ripristino)
  PreState = State;

  /*Serial.println("-PAUSA-");
  Serial.println("State " + (String)State);
  Serial.println("PreState " + (String)PreState);*/

  // salvo i colori precendeti (serve per il ripristino e per la trasmissione dei colori al telefono anche con lammpada spenta)
  pre_global_R_Color = global_R_Color;
  pre_global_G_Color = global_G_Color;
  pre_global_B_Color = global_B_Color;

  if (State == STATE_ON) {
      lightOff();
  }else if (State == STATE_KARMAFADE_EFFECT) {
      karmafade_effectAction.disable();
      lightOff();
  }else if (State == STATE_CANDLEEFFECT) {
      candle_effectAction.disable();
      lightOff();
  }

  State = STATE_PAUSE;

}

//--------------------------------------------------------
// ripristina la funzione messa in pausa
void resume(){

  digitalWrite(ledPin, HIGH); //test

  /*Serial.println("-RESUME-");
  Serial.println("State " + (String)State);
  Serial.println("PreState " + (String)PreState);*/

  if (PreState == STATE_ON) {
      lightOn();
  }else if (PreState == STATE_OFF) {
      lightOff();
  }else if (PreState == STATE_KARMAFADE_EFFECT) {
       setup_karmafade_effect();
  }else if (PreState == STATE_CANDLEEFFECT) {
       setup_candle_effect();
  }

}

//--------------------------------------------------------
// accende i led secondo i valori preventivamente salvati
//--------------------------------------------------------
// esempio formula white balance:
// Colore_in = 200, Threshold = 75 (il software mi invia 255 -  valore seekbar)
// calcolo max valore possibile visto il Threshold: max valore possibile = (255 - Threshold)  (255 - 75 = 180)
// calcolo moltiplicatore per valore out: moltiplicatore = (255 / max valore possibile)  (255 / 180 = 1,4166)
// Colore Out è uguale a colore_in diviso il moltiplicatore: Colore_out = (Colore_in / moltiplicatore) (200 / 1,4166 = 141) 
void SetRGBColor(int R, int G, int B){
    // setto il colore nelle variabili globali
    // att.ne il colore va settato prima di impostare la luminosità e il WB.
  global_R_Color=R;
  global_G_Color=G;
  global_B_Color=B;

   // invio il valore ai piedini corrispondenti
   // dopo aver settato il bilanciamento del bianco e la luminosità
  int maxRCol;
  int maxGCol;
  int maxBCol;
  float colRMoltip;
  float colGMoltip;
  float colBMoltip;
  float newRCol;
  float newGCol;
  float newBCol;

  int maxB_onRG;
  int maxG_onRB;
  int maxR_onGB;
  float colBMoltip_onRG;
  float colGMoltip_onRB;
  float colRMoltip_onGB;
  float newBCol_onRG;
  float newGCol_onRB;
  float newRCol_onGB;

  // calcolo nuovi valori di colore in base ai valori di treshold
  // relativi ai colori da tagliare per ottenere una tinta bilanciata.
  maxRCol = 255 - global_WB_R_Threshold;
  maxGCol = 255 - global_WB_G_Threshold;
  maxBCol = 255 - global_WB_B_Threshold;

  /*Serial.print("maxRCol\n");
  Serial.print(maxRCol);
  Serial.print(maxGCol);
  Serial.print(maxBCol);*/

  if(maxRCol > 0){
    colRMoltip = (float) 255 / maxRCol;
    newRCol = (int) R / colRMoltip;
  }else{
    newRCol = 0;
  }
  if(maxGCol > 0){
    colGMoltip = (float) 255 / maxGCol;
    newGCol = (int) G / colGMoltip;
  }else{
    newGCol = 0;
  }
  if(maxBCol > 0){
    colBMoltip = (float) 255 / maxBCol;
    newBCol = (int) B / colBMoltip;  
 }else{
    newBCol = 0;
  }

   /*Serial.print("colRMoltip\n");
   serialPrintFloat(colRMoltip, 3);
   serialPrintFloat(colGMoltip, 3);
   serialPrintFloat(colBMoltip, 3);

   Serial.print("newRCol\n");
   serialPrintFloat(newRCol, 3);
   serialPrintFloat(newGCol, 3);
   serialPrintFloat(newBCol, 3);*/

  // rebilanciamento in base a coppie di colori rimanenti
  // più il valore della coppia di colori rimanente si abbassa 
  // più il colore rimanente si alza a prescindere dal controllo di stabilizzazione del colore
  // calcolato in precedenza (vince il valore più alto).
  // serve a massimizzare i valori dei colori che si devono illuminare da soli.
  maxB_onRG =  B - (newRCol + newGCol);
  maxG_onRB =  G - (newRCol + newBCol);
  maxR_onGB =  R - (newGCol + newBCol);

  if(maxB_onRG > 0){
    colBMoltip_onRG = (float) B / maxB_onRG;
    newBCol_onRG = (float) B / colBMoltip_onRG; 
  }else{
    newBCol_onRG = 0;
  }
  if(maxG_onRB > 0){
    colGMoltip_onRB = (float) G / maxG_onRB;
    newGCol_onRB = (float) G / colGMoltip_onRB; 
  }else{
    newGCol_onRB = 0;
  }
  if(maxR_onGB > 0){
    colRMoltip_onGB = (float) R / maxR_onGB;
    newRCol_onGB = (float) R / colRMoltip_onGB; 
  }else{
    newRCol_onGB = 0;
  }

  if (newBCol_onRG > newBCol) {
    newBCol = newBCol_onRG;
  }
  if (newGCol_onRB > newGCol) {
    newGCol = newGCol_onRB;
  }
  if (newRCol_onGB > newRCol) {
    newRCol = newRCol_onGB;
  }

  analogWrite(led_R, setBrightness(newRCol));
  analogWrite(led_G, setBrightness(newGCol));
  analogWrite(led_B, setBrightness(newBCol));

   /*Serial.print("ricorrezione\n");
   serialPrintFloat(newRCol, 3);
   serialPrintFloat(newGCol, 3);
   serialPrintFloat(newBCol, 3);*/

}

void SetRColor(int R){
    SetRGBColor(R, global_G_Color, global_B_Color);
}

void SetGColor(int G){
    SetRGBColor(global_R_Color, G, global_B_Color);
}

void SetBColor(int B){
    SetRGBColor(global_R_Color, global_G_Color, B);
}

//--------------------------------------------------------
// funzione per la regolazione della luminosità
float setBrightness (int Value) {
  float newValue;  
  float Conts;

  Conts = (float)global_Brightness / 255;
  newValue = Value * Conts;

  return newValue;
}

//--------------------------------------------------------
// funzione per l'esecuzione di effetti di transizione
void transictionFromTo (int fromR, int fromG, int fromB, int toR, int toG, int toB, int velocity) {
    float R = fromR;
    float G = fromG;
    float B = fromB;
    float ContsR;
    float ContsG;
    float ContsB;
    boolean RComplete = false;
    boolean GComplete = false;
    boolean BComplete = false;

    // disabilito ricezione eventi
    mainAction.disable();

   // setup costanti di di discesa / salita
   if (R < toR){
     ContsR = (float)toR / 255;
   }else{
     ContsR = (float)fromR / 255;
   }
   if (G < toG){
     ContsG = (float)toG / 255;
   }else{
     ContsG = (float)fromG / 255;
   }
   if (B < toB){
     ContsB = (float)toB / 255;
   }else{
     ContsB = (float)fromB / 255;
   }

   /*serialPrintFloat(ContsR, 3);
   Serial.print(" ");
   serialPrintFloat(ContsG, 3);
   Serial.print(" ");
   serialPrintFloat(ContsB, 3);
   Serial.println("");*/

     do{

     if (!RComplete){
       if (R < toR){
        R = R + ContsR;
        if (R >= toR){
          RComplete = true;
        }
      }else{
        R = R - ContsR;
        if (R <= toR){
          RComplete = true;
        }
      }
     }

     if (!GComplete){
      if (G < toG){
        G = G + ContsG;
        if (G >= toG){
          GComplete = true;
        }
      }else{
        G = G - ContsG;
        if (G <= toG){
          GComplete = true;
        }
      }
     }

     if (!BComplete){
      if (B < toB){
        B = B + ContsB;
        if (B >= toB){
          BComplete = true;
        }
      }else{
        B = B - ContsB;
        if (B <= toB){
          BComplete = true;
        }
      }
     }

      /*serialPrintFloat(R, 3);
      Serial.print(" ");
      serialPrintFloat(G, 3);
      Serial.print(" ");
      serialPrintFloat(B, 3);
      Serial.println("");*/

      SetRGBColor(R, G, B);
      delay(velocity);

    }while(!(RComplete && GComplete && BComplete));

    // abilito ricezione eventi
    mainAction.enable();

}

//--------------------------------------------------------
// funzione per la regolazione della luminosità di transizione
void goto_Brightness (int toBrightness) {

  float fromBrightness = global_Brightness;
  boolean BrComplete = false;
  float ContsBr;

   // disabilito ricezione eventi
   mainAction.disable();

   if (fromBrightness < toBrightness){
     ContsBr = (float)toBrightness / 255;
   }else{
     ContsBr = (float)fromBrightness / 255;
   }

   do{

     if (!BrComplete){
       if (fromBrightness < toBrightness){
        fromBrightness = fromBrightness + ContsBr;
        if (fromBrightness >= toBrightness){
          BrComplete = true;
        }
      }else{
        fromBrightness = fromBrightness - ContsBr;
        if (fromBrightness <= toBrightness){
          BrComplete = true;
        }
      }
     }

     /*Serial.print("\n");
     serialPrintFloat(fromBrightness, 3);
     Serial.print(" ");*/

     global_Brightness = fromBrightness;

     SetRGBColor(global_R_Color, global_G_Color, global_B_Color);

     delay(1);

  }while(!BrComplete);

  // abilito ricezione eventi
  mainAction.enable();

}

//--------------------------------------------------------
// invia un valore di ritorno al dispositico connesso
void SendToDevice(String msgOut){
  Serial.println(MSG_START + MSG_INFO + msgOut + MSG_END);
}

//--------------------------------------------------------
// setup iniziale effetto fade karma
void setup_karmafade_effect(){
  State = STATE_KARMAFADE_EFFECT;
  // imposta timer di sistema
  kf_time=millis();
  kf_timeLedR=millis();
  kf_timeLedG=millis();
  kf_timeLedB=millis();

  kf_fadeValueR = global_R_Color;
  kf_fadeValueG = global_G_Color;
  kf_fadeValueB = global_B_Color;
  karmafade_effectAction.enable();
}

//--------------------------------------------------------
// esegue effetto fade karma
void karmafade_effect(){

  kf_time=millis();

  // esegue la funzione ogni tempo random
  if(kf_time>kf_timeLedR+kf_timeFadeR){
    if(kf_fadeValueR==kf_maxfadeValueR){
      kf_fadeDirectionR = 1;
      kf_maxfadeValueR = random(200, 255);
      kf_timeFadeR = random(10, 210) + global_KarmaFadeVelocity;
    }
    if(kf_fadeValueR==kf_minfadeValueR){
      kf_fadeDirectionR = 0;
      kf_minfadeValueR = random(0, 20);
      kf_timeFadeR = random(10, 210) + global_KarmaFadeVelocity;
    }
    SetRColor(kf_fadeValueR);
    if(kf_fadeDirectionR==0){
      kf_fadeValueR++;
    }else{
      kf_fadeValueR--;
    }
    kf_timeLedR=millis();
  }  

  if(kf_time>kf_timeLedG+kf_timeFadeG){
    if(kf_fadeValueG==kf_maxfadeValueG){
      kf_fadeDirectionG = 1;
      kf_maxfadeValueG = random(200, 255);
      kf_timeFadeG = random(10, 210) + global_KarmaFadeVelocity;
    }
    if(kf_fadeValueG==kf_minfadeValueG){
      kf_fadeDirectionG = 0;
      kf_minfadeValueG = random(0, 20);
      kf_timeFadeG = random(10, 210) + global_KarmaFadeVelocity;
    }
    SetGColor(kf_fadeValueG);
    if(kf_fadeDirectionG==0){
      kf_fadeValueG++;
    }else{
      kf_fadeValueG--;
    }
    kf_timeLedG=millis();
  }  

  if(kf_time>kf_timeLedB+kf_timeFadeB){
    if(kf_fadeValueB==kf_maxfadeValueB){
      kf_fadeDirectionB = 1;
      kf_maxfadeValueB = random(200, 255);
      kf_timeFadeB = random(10, 210) + global_KarmaFadeVelocity;
    }
    if(kf_fadeValueB==kf_minfadeValueB){
      kf_fadeDirectionB = 0;
      kf_minfadeValueB = random(0, 20);
      kf_timeFadeB = random(10, 210) + global_KarmaFadeVelocity;
    }
    SetBColor(kf_fadeValueB);
    if(kf_fadeDirectionB==0){
      kf_fadeValueB++;
    }else{
      kf_fadeValueB--;
    }
    kf_timeLedB=millis();
  }  

      /*Serial.print(fadeValueR);
      Serial.print(" ");
      Serial.print(fadeValueG);
      Serial.print(" ");
      Serial.print(fadeValueB);
      Serial.println("");*/

}

//--------------------------------------------------------
// setup iniziale effetto fade karma
void setup_candle_effect(){
  State = STATE_CANDLEEFFECT;
  // imposta timer di sistema
  ce_time=millis();
  ce_timeLedR=millis();
  ce_timeLedG=millis();
  SetBColor(0);
  candle_effectAction.enable();
}

//--------------------------------------------------------
// effetto candela
void candle_effect(){
  ce_time=millis();

  if(ce_time > ce_timeLedR + ce_timeFadeR){
      transictionFromTo(global_R_Color, global_G_Color, 0, random(180, 255), global_G_Color, 0, 0);
      ce_timeLedR=millis();
      ce_timeFadeR = random(10, 150) + global_CandleEffectVelocity;
  }

  if(ce_time > ce_timeLedG + ce_timeFadeG){
      transictionFromTo(global_R_Color, global_G_Color, 0, global_R_Color, random(80, 140), 0, 0);
      ce_timeLedG=millis();
      ce_timeFadeG = random(10, 150) + global_CandleEffectVelocity;
  }

}

//--------------------------------------------------------
// funzione che copia i dati di default se è la prima volta che viene acceso il device
void setDeviceToDefault(){
  EEPROM.write(EPROM_ADDR_FIRST_TIME_EXEC, 1);
  startDevice();
}

//--------------------------------------------------------
// funzione di start
void startDevice(){
  // controllo se è la prima volta che accendo il device ed imposto i valori di default  
  if (EEPROM.read(EPROM_ADDR_FIRST_TIME_EXEC) == 1){

    // pulisco memoria eprom
    //for(int i = 0; i < 256; i++){    
    //  EEPROM.write(i, 255);         
    //}

    // scrivo valori default per colori
    EEPROM.write(EPROM_ADDR_VALUE_R, DEFAULT_VALUE_R);
    EEPROM.write(EPROM_ADDR_VALUE_G, DEFAULT_VALUE_G);
    EEPROM.write(EPROM_ADDR_VALUE_B, DEFAULT_VALUE_B);
    // scrivo valori default per White balance
    EEPROM.write(EPROM_ADDR_VALUE_WBT_R, DEFAULT_VALUE_WBT_R);
    EEPROM.write(EPROM_ADDR_VALUE_WBT_G, DEFAULT_VALUE_WBT_G);
    EEPROM.write(EPROM_ADDR_VALUE_WBT_B, DEFAULT_VALUE_WBT_B);
    // scrivo valori default per parametri effetti e luimnosità
    EEPROM.write(EPROM_ADDR_VALUE_BRIGHTNESS, DEFAULT_VALUE_BRIGHTNESS);
    EEPROM.write(EPROM_ADDR_VALUE_KARMAFADE_VELOCITY, DEFAULT_VALUE_KARMAFADE_VELOCITY);
    EEPROM.write(EPROM_ADDR_VALUE_CANDLEEFFECT_VELOCITY, DEFAULT_VALUE_CANDLEEFFECT_VELOCITY);
    // resetto attributo di esecuzione per la prima volta
    EEPROM.write(EPROM_ADDR_FIRST_TIME_EXEC, 0);

    //   setupModem();
  }

  // accendo le luci e carico i valori globali
    State = STATE_ON;
    digitalWrite(ledPin, HIGH); //test

    global_Brightness           = EEPROM.read(EPROM_ADDR_VALUE_BRIGHTNESS);  // lettura luminosità
    global_KarmaFadeVelocity    = EEPROM.read(EPROM_ADDR_VALUE_KARMAFADE_VELOCITY);  // lettura luminosità
    global_CandleEffectVelocity = EEPROM.read(EPROM_ADDR_VALUE_CANDLEEFFECT_VELOCITY);  // lettura luminosità

    // recupero colore default da memoria
    int R_Color = EEPROM.read(EPROM_ADDR_VALUE_R);
    int G_Color = EEPROM.read(EPROM_ADDR_VALUE_G);
    int B_Color = EEPROM.read(EPROM_ADDR_VALUE_B);

    // recupero WB da memoria
    global_WB_R_Threshold = EEPROM.read(EPROM_ADDR_VALUE_WBT_R);
    global_WB_G_Threshold = EEPROM.read(EPROM_ADDR_VALUE_WBT_G);
    global_WB_B_Threshold = EEPROM.read(EPROM_ADDR_VALUE_WBT_B);

    transictionFromTo(0, 0, 0, R_Color, G_Color, B_Color, 8);

}

void setupModem(){
   // bluetooth.begin(9600);
   // delay(500);
    //bluetooth.println("AT+BAUD7"); 
    //delay(2000);
   // bluetooth.println("AT+NAMELEDLamp"); 
   // delay(2000);
}

//--------------------------------------------------------
// funzione di conversione stringa > int
int stringToInt(String string){
  // converte stringa > int
  char cValue[string.length() + 1];
  string.toCharArray(cValue, sizeof(cValue));
  int iValue = atoi(cValue);
  return iValue;
}

String addZeroToLeft(String in){
   String s;
   int count=0;

   while(count < 3-in.length()){
     s.concat("0");
     count++;
   }

   s.concat(in);
   return s;
}

//--------------------------------------------------------
// funzione di debug - stampare numeri float
// printFloat prints out the float 'value' rounded to 'places' places after the decimal point
void serialPrintFloat(float value, int places) {
  // this is used to cast digits
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;

    // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
  // if this rounding step isn't here, the value  54.321 prints as 54.3209

  // calculate rounding term d:   0.5/pow(10,places)  
  float d = 0.5;
  if (value < 0)
    d *= -1.0;
  // divide by ten for each decimal place
  for (i = 0; i < places; i++)
    d/= 10.0;    
  // this small addition, combined with truncation will round our values properly
  tempfloat +=  d;

  // first get value tens to be the large power of ten less than value
  // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take

  if (value < 0)
    tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) {
    tens *= 10.0;
    tenscount += 1;
  }

  // write out the negative if needed
  if (value < 0)
    Serial.print('-');

  if (tenscount == 0)
    Serial.print(0, DEC);

  for (i=0; i< tenscount; i++) {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }

  // if no places after decimal, stop now and return
  if (places <= 0)
    return;

  // otherwise, write the point and continue on
  Serial.print('.');  

  // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
  for (i = 0; i < places; i++) {
    tempfloat *= 10.0;
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    // once written, subtract off that digit
    tempfloat = tempfloat - (float) digit;
  }
}

/* HSVtoRGB
 (cc) 2008-2010 Kokiua (alias L.M.) from Sorbolo (Parma) - Italy
 Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/
 algoritmo rielaborato partendo da da http://www.cs.rit.edu/~ncs/color/t_convert.html

 da RGB a HSB (Hue/Tonalita' - Saturation/Saturazione - Brightness/Luminosita')
 HSB diventa HSV definendo Brightness = Value per distinguere la variabile B di RGB

 i valori RGB che tornano sono nel range da 0-255
 i valori in entrata sono:
 h = [0.0-360.0] ( Tonalita' in gradi)
 s = [0.0-1.0] (Saturazione in % dove 1 = 100%)
 v = [0.0-1.0] (Luminosita' in % dove 1 = 100%)

void HSVtoRGB( unsigned char x, float h, float s, float v )
{
  int i;
  float f, p, q, t, r, g, b;
  if( s == 0 ) {
    r = g = b = v;   // achromatic (grey)
    return;
  } else {
    h /= 60;            // sector 0 to 5
    i = floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i ) {
    case 0: r = v; g = t; b = p; break;
    case 1: r = q; g = v; b = p; break;
    case 2: r = p; g = v; b = t; break;
    case 3: r = p; g = q; b = v; break;
    case 4: r = t; g = p; b = v; break;
    default: r = v; g = p; b = q;  break; // case 5:
    }
  }
  led[x].r = 255 * r;   //converto i valori RGB dal range 0.0-1.0 a 0-255
  led[x].g = 255 * g;
  led[x].b = 255 * b;
}
*/

 


13 Kommentare

hansi@123.com · 10. April 2015 um 10:40

Eine 3Watt RGB-LED? Können Sie mir bitte mehr darüber erzählen?

    Avatar-Foto

    Shojo · 10. April 2015 um 12:09

    Inwiefern?
    Da müsse Sie schon etwas genauer werden. 😉

      hansi@123.com · 10. April 2015 um 14:29

      Wie heißt Ihre Power-LED und wie funktioniert das mit dem Kühlkörper?
      Ich möchte auch gerne wissen wie die Zuordnung der Pins vom MOSFET sind.
      Source/Drain/Gate –> ??? ??? ??? (RGB-Pins/Arduino-Pins/GND)

        Avatar-Foto

        Shojo · 12. April 2015 um 09:45

        Hi,
        ich hatte damals die 3W LED Emitter on Star genutzt.
        Als Kühlkörper habe ich einen alten Chipsatzkühler verwendet.
        Die Pinzuordnung kann oben aus dem Schaltplan entnommen werden.

        Gruß
        Shojo

Klaus · 9. August 2014 um 12:37

Mir ist aufgefallen, dass du an deinen Schaltplänen bei der RGB einen gemeinsamen Plus Pol hast. Bei deiner selbst zusammengebauten hast du allerdings einen Gemeinsamen minus Pol. Zu welchem passt das unten stehende Sketch? und wäre das ein unterschied?

Mfg Klaus

    Avatar-Foto

    Shojo · 9. August 2014 um 15:49

    Moin Klaus,

    der Sketch geht für beide „Versionen“!
    Es ist ja nur entscheidend ob Du nun Plus oder Minus über die MOSFET schaltest,
    und das ist für den Sketch irrelevant.

    Gruß
    Shojo

Steffen Wirth · 1. August 2014 um 13:35

Hey ich wollte mal nachfragen, der Sketch ist ja veraltet und wenn ich diesen bei mir im Programm Kompiliere zeigt er einige Fehler etc. wie hast du dieses Problem gelöst?

    Avatar-Foto

    Shojo · 1. August 2014 um 18:32

    Hi,
    Du muss das nur mit der Arduino ide Version 0023 kompelieren.
    (http://arduino.cc/en/Main/OldSoftwareReleases)

    Gruß
    Shojo

      Steffen · 1. August 2014 um 19:00

      EIne frage hätte ich noch, ist es für das Programm notwendig dass der BT- Chip mit einer Baudrate von 115200 läuft oder ist es egal?
      Vielen Dank 🙂

        Avatar-Foto

        Shojo · 2. August 2014 um 00:44

        Das kannst Du machen wie Du willst ….

        Muss dann hier aber angepasst werden
        Serial.begin(115200); // initialize serial communication:

Avatar-Foto

Shojo · 31. März 2013 um 13:25

So nun auch die 5 Volt Version verfügbar!

Avatar-Foto

Shojo · 10. März 2013 um 18:56

Code und Links hinzugefügt,
viel Spaß beim Basteln 😉

Jorge Rocha · 28. Februar 2013 um 05:21

Hi,

where can i find the arduino code ande the app ?

Thaks

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.