Saturday,30-January-2016

RGB LED control via Arduino and BT serial

ENBG
In that topic will show my first attempt to create R-G-B LED control via timer`s PWM and serial commands based on HC-06 interface hardware and BT serial app for Android. Това е първият ми опит да използвам сериен порт базиран на блутут комуникация между Андроид телефон и ардуино нано. RGB диода се управлява посредством шим базиран на хардуерен таймер

Hardware setup Oпитна установка

bt-to-serial.jpg

Arduino Nano - HC-06 - RGB LED

1) USB to RS232 TTL PL2303HX

2) HC-06

3) Arduino IDE

My set up for HC-06 Mоите настройки за НС-06

USB to RS232 TTL PL2303HX - HC-06

+5V - VCC

GND - GND

RX - TX

TX - RX

Arduino IDE -> COM port: com(XX)

Arduino IDE -> Programmer : Parallel Programmer

Arduino IDE -> Serial monitor -> NO end line -> 9600 baud

Some of the versions of HC-06 require “Both NL/CR” set at 9600 bbp to get into AT mode

Plug PL2303HX into USB / поставете PL2303HX в USB-то

In serial window write: / В прозореца за серийни команди напишете:

SERIAL SEND: AT <enter>

SERIAL RETURN: OK

SERIAL SEND: AT+NAMERGB <enter> <- new name will be “RGB” / новото име ще е “RGB”

SERIAL RETURN: OKsetname

SERIAL SEND: AT+PIN0000 <enter> <- new pin will be “0000” / новият пин ще е “0000”

SERIAL RETURN: OKsetname

SERIAL SEND: AT+BAUD4 <enter> <- new baud “9600” / новата скорост ще е “9600”

SERIAL RETURN: OK9600

1 - 1200bps

2 - 2400bps

3 - 4800bps

4 - 9600bps (Default)

5 - 19200bps

6 - 38400bps

7 - 57600bps

8 - 115200bps

In one new HC-06 modules I bought in 2017 it keep as that:

AT+VERSION:

>VERSION:3.0-20170609

AT+NAME

>+NAME:HC-06

to set new, write: AT+NAME=NEW_NAME

AT+UART

> +UART:9600,0,0

Set new speed: > AT+UART:115200,0,0 <- set to 115200, stop bit1 (0-1bit / 1-2bit) , parity none(0-none/1-odd / 2-even)

AT+PSWD

>+PIN:”1234”

to set new, write: AT+PSWD=”0000” , set pin to 0000

It look to be something similar to HC-05, but work :))


// Arduino IDE settings for serial: [x] autoscroll - No line ednding - 38400baud

// example:

// 255000000d#<enter> - full red / само червено

// f <enter> - floating colors / преливащи цветове

// w <enter> - full white / само бял

// r <enter> - full off  / всичко спряно

// < or > <enter> - dec./inc. brightness  - усилване намалявне на яркостта

// d <enter> - return last state / върти обратно

// 0-off 255-pull 100% / за цвят - 0 - без, 255 - 100%

// based on http://www.easyrgb.com/index.php?X=MATH&H=19#text19

#define RED    6// D6 timer 0 oc0a

#define GREEN  5// D5 timer 0 oc0b

#define BLUE   3// D3 timer 2 OCR2B

int state = 0;

long previousMillis = 0; 

long serialDelay = 0;

int counter = 255;

char command[10]={0,0,0,0,0,0,0,0,0,'d'}; //R 0,0,0 G 0,0,0 B 0,0,0 Float 0 

int fill = 0;

int red,green,blue;

int brightUp,brightDown;

int rgbState[3] = {0,0,0}; // 0_R , 1_G , 2_B

int long hslState[3] = {0,0,0}; // 0_H , 1_S , 2_L

int luminSteps=0;

int rgbInit[3] = {0,0,0};

boolean rgb = false;

boolean white = false;

    int whiteStep=0;

void setup() {

pinMode(RED, OUTPUT);

pinMode(GREEN, OUTPUT);

pinMode(BLUE, OUTPUT);

TCCR0A = (1<<COM0A1) | (1<<COM0A0) | (1<<COM0B1) | (1<<COM0B0) | (1<<WGM01) | (1<<WGM00);

TCCR0B = (0<< FOC0A) | (0<<FOC0B)  | (0<<WGM02)  | (0<<CS02)   | (1<<CS01)  | (1<<CS00); 

TCCR2A = (1<<COM2A1) | (1<<COM2A0) | (1<<COM2B1) | (1<<COM2B0) | (1<<WGM21) | (1<<WGM20);

TCCR2B = (0<< FOC2A) | (0<<FOC2B)  | (0<<WGM22)  | (1<<CS22)   | (0<<CS21)  | (0<<CS20); 

//OCR0A = 255;

//OCR0B = 255;

//OCR2A = 255;

//OCR2B = 255;  

TCNT2=0;

TCNT0=0;

  Serial.begin(38400);

  Serial.println("Welcome to RGB!");

}

//----------------------------------------- additional to HSL to RGB ---------

int hue2rgb(float v1,float v2,float vh){

       if(vh < 0) vh +=1;

       if(vh > 1) vh -=1;

    if((6*vh) < 1) { 

          float tma = v1 + ((v2-v1)*6.0*vh);

          tma = (tma*255.0)+0.5;

          return(tma);

    }else if ((2.0*vh) < 1) {

          float tmb = (v2*255.0)+0.5;

          return (tmb);

    }else if ((3*vh) < 2 ){

          float tmc =  v1 + ((v2-v1)*((0.6666 - vh)*6));

          tmc = (tmc*255.0)+0.5;

          return (tmc);

    }else{

          v1 = (v1*255.0)+0.5;  

          return ( v1 );

    }

}

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

void printBack(){

// uncomment for debuging only  

//                       if(command[9] == 'f'){

//                             Serial.println("RGB float:ON");

//                       }else{

//                             Serial.print("RGB float:OFF | ");

//                             Serial.print("RED:");

//                             Serial.print(rgbInit[0],DEC);

//                             Serial.print(" Green:");

//                             Serial.print(rgbInit[1],DEC);

//                             Serial.print(" BLUE:");

//                             Serial.println(rgbInit[2],DEC);

//                             

//                             Serial.print("H:");

//                             Serial.print(hslState[0],DEC);

//                             Serial.print(" S:");

//                             Serial.print( hslState[1],DEC);

//                             Serial.print(" L:");

//                             Serial.println( hslState[2],DEC);

// 

                             Serial.print("R:");

                             Serial.print(rgbState[0],DEC);

                             Serial.print(" G:");

                             Serial.print(rgbState[1],DEC);

                             Serial.print(" B:");

                             Serial.println(rgbState[2],DEC);

//                             

//                             Serial.print("STEP:");

//                             Serial.println(luminSteps);

//                      }

}//end print

// --------------RGB to HSL -----

void rgb2hsl(){   

   float var_R =   (float) rgbState[0] / 255.0;

   float var_G = (float) rgbState[1] / 255.0;

   float var_B =  (float) rgbState[2] / 255.0;

   float tmpMax, tmpMin;

   

   if(var_B > var_G) { tmpMax = var_B; }else{ tmpMax = var_G; }

   if(var_R > tmpMax){ tmpMax = var_R; }   

   if(var_G < var_B) { tmpMin = var_G; }else{ tmpMin = var_B; }

   if(var_R < tmpMin){ tmpMin = var_R; }   

   float luminance, saturation, hue, delta, tmpA;

   tmpA = tmpMax+tmpMin;

   luminance = tmpA/2;

   delta = tmpMax-tmpMin;

   if(luminance < 0.5) { 

            saturation = delta/tmpA; 

   }else{ 

           saturation = delta/(2.0-tmpMax-tmpMin); 

   }

   if(delta == 0){

         hue = 0;

         saturation = 0;

   }else{

         float tmpA2 = tmpMax / 2.0; 

         float del_R = ((tmpMax - var_R)/6) + (tmpA2 / tmpMax);

         float del_G = ((tmpMax - var_G)/6) + (tmpA2 / tmpMax);

         float del_B = ((tmpMax - var_B)/6) + (tmpA2 / tmpMax);

         if(var_R == tmpMax){

                hue = (del_B - del_G)/delta;

         }else if(var_G == tmpMax){ 

                hue = 0.3333 + ((del_R - del_B)/delta);

         }else if(var_B == tmpMax){

                hue = 0.6666 + ((del_G - del_R)/delta);

         }

        

      if( hue < 0 ){ hue += 1;}

      if( hue > 1 ){ hue -= 1;}

      hslState[0] = hue*360.0;

      hslState[1] = saturation*1000.0;

      hslState[2] = luminance*1000.0;

  }

}//end rgb2hsl

//-------------------------------------- from HSL to RGB -----------------------

void hsl2rgb(){

  

     int nR,nG,nB;

     float var1,var2,newHue;

     float lumin = (float) hslState[2] / 1000.0;

     float satur = (float) hslState[1] / 1000.0;

   newHue = float(hslState[0])/360.0;

   if(satur == 0){

       nR = (float)255*lumin;

       nG = (float)255*lumin;

       nB = (float)255*lumin;

   }else{

          if(lumin<0.5){ 

               var2 = lumin*(1+satur); 

          }else{

               var2 = (lumin+satur)-(satur*lumin);

          }  

var1 = (2*lumin)-var2;

rgbState[0] = hue2rgb(var1,var2,newHue+0.3333); //R

rgbState[1] = hue2rgb(var1,var2,newHue); //G

rgbState[2] = hue2rgb(var1,var2,newHue-0.3333); //B

   }

}//end hsl2rgb

void loop(){

   

  while(Serial.available()>0) {

          char serialBuffer = Serial.read();

          

          if(serialBuffer != '#'){

                if(serialBuffer == 'w'){

                     white = true;

                     rgb = false;

                     if(command[9] == 'r'){

                             command[9] = 'd';

                     }else{

                        rgbState[0] = 255;

                        rgbState[1] = 255;

                        rgbState[2] = 255;

                     }

                     

                     //Serial.println("WHITE:ON");

                     

                }

               else if(serialBuffer == 'r'){

                          command[9] = 'r';           

                          //Serial.println("FULL:OFF");

                }

               else if(serialBuffer == 'f'){

                      command[9] = 'f';

                      //Serial.println("FLOAT:ON");   

                }

               else if(serialBuffer == 'd'){

                      command[9] = 'd';

                      //Serial.println("I`m back :)");   

                }

               else if(serialBuffer == '<'){

                               if(white == true){

                                         if(whiteStep < 4){

                                              whiteStep += 1;  

                                              rgbState[0] -= 63;

                                              rgbState[1] -= 63 ;

                                              rgbState[2] -= 63 ;

                                         } 

                               }if(rgb == true){              

                                        rgb2hsl();

                                     if(luminSteps < 4){

                                          luminSteps += 1;  

                                          hslState[2] -= 100;

                                     }

                                          hsl2rgb();  

                                          printBack();

                               }

                }else if(serialBuffer =='>'){

                               if(white == true){

                                         if(whiteStep > 0){

                                             whiteStep -= 1;  

                                             rgbState[0] += 63;

                                             rgbState[1] += 63 ;

                                             rgbState[2] += 63 ;

                                         } 

                               }else if(rgb == true){              

                                        rgb2hsl();

                                     if(luminSteps > 0){

                                          luminSteps -= 1;  

                                          hslState[2] += 100;

                                     }

                                          hsl2rgb();  

                                          printBack();

                               }

                }else{

                    command[fill] = serialBuffer;

                    fill++;

                }

          }          

          if(serialBuffer == '#'){

                    fill = 0;

                    white = false;

                    whiteStep = 0;

                    rgb = true;

                    rgbState[0] = 0;

                    rgbState[1] = 0;

                    rgbState[2] = 0;

                       //red

                       int r1 = (command[0]-48)*100;

                       int r2 = (command[1]-48)*10;     

                       int r3 = command[2]-48;

                       rgbState[0] = r1+r2+r3;

                       rgbInit[0] = rgbState[0];

                       //green

                       int g1 = (command[3]-48)*100;

                       int g2 = (command[4]-48)*10;     

                       int g3 = command[5]-48;

                       rgbState[1] = g1+g2+g3;

                       rgbInit[1] = rgbState[1];

                       //blue

                       int b1 = (command[6]-48)*100;

                       int b2 = (command[7]-48)*10;     

                       int b3 = command[8]-48;

                       rgbState[2] = b1+b2+b3;

                       rgbInit[2] = rgbState[2];

                       printBack();

         }

         

  }

if(command[9] == 'r'){

       OCR0A=255;  //R 

       OCR0B=255;  //G

       OCR2B=255;  //B

}

  

if(command[9] == 'd'){

       OCR0A=255-rgbState[0];  //R 

       OCR0B=255-rgbState[1];  //G

       OCR2B=255-rgbState[2];  //B

}

      

      

if(command[9] == 'f'){           

    if(millis() - previousMillis > 19) {

              previousMillis = millis();

              counter -= 1;

              if(counter <0){

                  counter=255; 

                  state += 1;

                  if(state > 7){state = 0;}

              }

    }

         switch(state){

          case 0: //RGB off -> RGB on

              OCR0A=counter;  //R 

              OCR0B=counter;  //G

              OCR2B=counter;  //B

          break;

          case 1: //GB on -> R off

              OCR0A=255-counter;  //R 

              OCR0B=0;            //G

              OCR2B=0;            //B

          break;

          case 2: //RB on -> G off

              OCR0A=counter;     //R 

              OCR0B=255-counter; //G

              OCR2B=0;           //B

          break;

          case 3: //RG on -> B off

              OCR0A=0;           //R 

              OCR0B=counter;     //G

              OCR2B=255-counter; //B

          break;

          case 4: //R on -> GB off

              OCR0A=0;            //R 

              OCR0B=255-counter;  //G

              OCR2B=255;          //B

          break;

          case 5: //G on -> RB off

              OCR0A=255-counter;  //R 

              OCR0B=counter;      //G

              OCR2B=255;          //B

          break;

          case 6: //B on -> RG off

              OCR0A=255;         //R 

              OCR0B=255-counter; //G

              OCR2B=counter;     //B

          break;

          case 7: //B on -> RGB off

              OCR0A=255;         //R 

              OCR0B=255;         //G

              OCR2B=255-counter; //B

          break;

          }//end switch

  }//end if FLOAT    

}//end loop

I use 38400baud set to the BT module, and Arduino serial window settings: [x] autoscroll - no line end - 38400baud That is all. Hope to be in use for some beginner as me. And why I use inverted mode in PWM? That is because when you write in normal PWM mode 0, somehow still there is kind of led activity. In that way is fully off. Използвам 38400baud за BT модула , както и Arduino настройка за прозореца: [x] autoscroll - no line end - 38400baud Te това е. Надявам се, да бъде от полза на хора начинаещи като мен. А защо таймерите са в инвертен режим? Това е така, тъй като при нормална работа ако се остави ШИМ на 0, все още има микро активно в диода и той мъждука. В този режим е напълно угасен.

setup Android BT terminal APP function настройка на Андроид приложението

btscreen1.jpg btscreen2.jpg btscreen9.jpg btscreen4.jpg

btscreen5.jpg btscreen10.jpg

And links to app what I use И връзки към приложенията които ползвах

Serial Android App

Color Grab