Saturday,30-January-2016
RGB LED control via Arduino and BT serial
| EN | BG |
| 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питна установка |
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 | настройка на Андроид приложението |
| And links to app what I use | И връзки към приложенията които ползвах |