Illusion LED Strip RRFT1000 40RGBD

 
В этой статье я вам опишу как организовать управление RGB светодиодом или лентой при помощи телефона или планшета на системе Android
Хочу сказать спасибо сайту Паяльник, информацию какие мосфеты использовать я взял там вот ссылка на статью, также спасибо американцу который выложил в свободный доступ скетч и приложение для телефонов на android для управления RGB лентой вот ссылка на сайт и спасибо Дмитрию Осипову который ведёт свой канал на Youtube у него есть видео где он подробно рассказывает про блютус модули HC-05 вот ссылка на его канал.

 И так давайте приступим к сборке устройства. Для этого нам понадобиться следующие комплектующие:

maketkaRGB

1шт. Arduino любая

1шт. Блютус модуль HC-05

1шт. Стабилизатор напряжения LM7805

3шт. Сопротивления R1 ,R2 , R3 на 1кОм

2шт. Конденсаторы C3, C4 на 16в  220 Мкф C

2шт. Керамические конденсаторы C5, C6 на 0.1 Мкф

3шт. Мосфеты Q1, Q2, Q3    STP16NF06.

С лева представлена макетная плата, где показано что куда подключать + для удобства все линии связи имеют свой цвет

shemaRGB

 Фиолетовый цвет это питание (+12) автомобиля или какого нибудь блока питания. Черный цвет (- т.е GND). Оранжевый +5V который выходит с LM7805. Синий сигнальная линия для управления мосфетом и Синим цветом светодиода. Красный сигнальная линия для управления мосфетом и Красным цветом светодиода. Зеленый сигнальная линия для управления мосфетом и зеленым светодиодом. Бирюзовый для соединения лий TX ардуино с RX HC-05. Розовый для соединения линий RX ардуино с TX HC-05. 

На схеме обозначен обычный RGB светодиод подписан как RGB LED, но если вы используете обычную светодиодную ленту то резисторы R1, R2, R3 ставить не нужно! 

После того как собрали схему необходимо поменять параметры блютус модуля HC-05, это (переименовать модуль на LEDLamp и помень скорость соединения на 115200) Как это сделать смотрите видео Дмитрия Осипова под спойлером

Видео Дмитрия Опипова как перепрограммировать HC-05

После того как Вы успешно перепрограммировали модуль HC-05 необходимо загрузить скетч в arduino, но учтите, скетч написан давно поэтому он работает только на древнем Arduino IDE 0022  Скетч ооочень здоровый больше 1200 строк, я даже не разбирался что туда разработчик напихал, работает ну и ладно ;)

Скетч для ардуино, управление RGB лентой (1202 строки)

#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: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
// 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 = 5;    // LED Rosso (atmega pin 11) - in futuro 9*
const int led_G = 6;    // LED Verde (atmega pin 12) - in futuro 10*
const int led_B = 3;    // 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 = 125;
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() {

  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;
}
*/


Если не заработало попробуйте этот скетч

Скетч для ардуино, управление RGB лентой Beta7 (1193 строки)

#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: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
// 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 = 5;    // LED Rosso (atmega pin 11) - in futuro 9*
const int led_G = 6;    // LED Verde (atmega pin 12) - in futuro 10*
const int led_B = 3;    // 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 = 125;
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() {

  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 , 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;
}
*/

Закачали скетч в Arduino, осталось дело за малым) Скачаем на телефон приложение через GooglePlay LEDLamp вот Здесь

Включаем блютус ищем устройство LEDLamp, теперь мы можем спокойно управлять  RGB лентой. Приятного использования