Project tutorial
20$ RF smart controled RGB LEDS, for bikes

20$ RF smart controled RGB LEDS, for bikes © GPL3+

RGB coloured wheels with three different control modes. -analogRead 3 potentiometers -random smooth changing colours -copycat colour

  • 2,713 views
  • 0 comments
  • 7 respects

Components and supplies

Ard nano
Arduino Nano R3
ATMEGA168 do just fine, we will use half of the memory
×3
lipo battery 3S 11,1v
(i use 2200mah (overkill))
×2
lipo battery 2S 7,4V
for the emmiter, a 500mah will do, you can also use 3s 11,1v
×1
rgb stripes (the lenght you need, use your rusty calculus skills )
mines are 12v common cathode
×1
433mhz emitter and receiver couple
well use one transmitter and two receivers
×2
Fairchild semiconductor fqu13n06ltu image 75px
Power MOSFET N-Channel
3 each stripe you need to control, i need 3 for each wheel
×6
Mfr 25fbf52 221r sml
Resistor 221 ohm
for handling the current drain on the gate of the mosfets
×6
circuit plates
buy some of this, they will save your ass with your cool projects
×2
09939 01
Rotary potentiometer (generic)
i used some of 100k at first, i was wrong, use 10k at least better
×3
Omron b3f 1000 image 75px
SparkFun Pushbutton switch 12mm
with latching
×2
09264 1
RGB Diffused Common Cathode
for copycat
×1
light sensor
cheapest variable resistor by light
×1

Necessary tools and machines

09507 01
Soldering iron (generic)
ffssssshh

Apps and online services

Ide web
Arduino IDE
we all love you arduino ide

About this project

You could use this project and modify it to control the lights of your house matching the colour of the sun (indoors sunset) etc....I used to struggle with shitty low quality LED lights on my bike, my goal was to be noticed.

transmmiter still in breadboard (warning, spanish)

So i purchased some of the cheapest rgb stripes (they played me, the stripes were R,G and B on an individual LED each one) , a cuple of arduino nano , lipo batterys and transistors.

Now i have the most gaudy bike on the city, why?, because i know about electronics and i could do silly things whenever i please.

TRANSMITTER

The size, form and range that you find suitable for your project, i needed something strong and pocketsize.

Arduino nano with 433mhz transmmiter module on the back, three scavenged potenciometers from an old music amplifier(100kohm each), the potenciometers have a bad response to the arduino analog reading wich only recognices values at the low resistance levels if i do it again i will use 10k or lower.

It depends highly of your boxing and placement of the transmmiter in your project but you can archieve 100m range easily.

range test (spanish)

rgb detection with 1$ hardware spanish

RECEIVER

No big deal, the easy part of the project. Arduino nano with 433mhz receiver module and three power pnp mosfets for current gating the led stripe. We also are gonna need a bigger lipo of 11,1v (3S and the current mAh you find just okay for your needs) cause my RGBstripe is 12v.

Code

RX, receiver on the weelsC/C++
to upload into an arduino (nano in my case)
its reads an specific datagram with this concrete sintaxis
MaRRRRaGGGGaBBBB;

M->mode , 0 for waving colours, 1 for analog transmitted from the TX unit
RRRR-> RED VALUE
GGGG->GREEN VALUE
BBBB->BLUE VALUE
a->for separate the data
#include <VirtualWire.h>
//pin map, RX and pwm analogOutupts to PNP transistors
#define RX 3
#define pwmledRED 5
#define pwmledGREEN 6
#define pwmledBLUE 11

//arrays of data for build the final message
char datarraycharred  [(sizeof(int)*4+1)];
char datarraychargreen[(sizeof(int)*4+1)];
char datarraycharblue [(sizeof(int)*4+1)];
char datarraymodo     [(sizeof(int)*4+1)];
char datarrayclear    [(sizeof(int)*4+1)]={"FFFF"};//tricky thing to reorder the data
char datatotal        [(sizeof(int)*4+1)*4+4];

int datared =0;
int datagreen =0;
int datablue =0;
int bandera=0;
int i=0,j=0,index=0;
int indexchill=0;
int datamodo=3;//initialice with idle state all LED turned off

int ired=0,igreen=0,iblue=0;

void setup() {
  Serial.begin(9600);
  
    
    // VirtualWire 
    // Initialise the IO and ISR
    // Required for DR3100
    vw_set_rx_pin(RX);       //Config pin as RX
    vw_set_ptt_inverted(true); 
    // Bits per sec
    vw_setup(2000);         
    // Start the receiver PLL running
    vw_rx_start();  
    pinMode(pwmledRED,OUTPUT); //trt--->leds outuput
        pinMode(pwmledGREEN,OUTPUT);
            pinMode(pwmledBLUE,OUTPUT);    

} 



void loop(){
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    
    // Non-blocking
    if (vw_get_message(buf, &buflen)) 
    {
    int i;

           // Message with a good checksum received, dump it. 
        for (i = 0; i < buflen; i++)
    {            
          // Fill Sensor1CharMsg Char array with corresponding 
          // chars from buffer.   
          datatotal[i] = char(buf[i]);
    }
        
        datatotal[buflen] = '\0';
        
 // Convert Sensor1CharMsg Char array to TRUE integer, not the direct ASCII equivalent shit
chartointconvert();
}


  if(datamodo==0)// chill wabing colour mode
 modochill();



//write outupts
analogWrite(pwmledRED,datared);
analogWrite(pwmledGREEN,datagreen);
analogWrite(pwmledBLUE,datablue);



            // DEBUG 
        Serial.print(datatotal);
        Serial.print("      ");
        Serial.print(datarraymodo);
        Serial.print("  ");
        Serial.print(datarraycharred);
        Serial.print("  ");
        Serial.print(datarraychargreen);
        Serial.print("  ");
        Serial.print(datarraycharblue);
        Serial.print("     ");
        Serial.print(datamodo);
        Serial.print("  ");
        Serial.print(datared);
        Serial.print("  ");
        Serial.print(datagreen);
        Serial.print("  ");
        Serial.println(datablue);
        delay(50);

}










void chartointconvert(){
bandera=0;
strcpy (datarraymodo,datarrayclear);
strcpy (datarraycharred,datarrayclear);
strcpy (datarraychargreen,datarrayclear);
strcpy (datarraycharblue,datarrayclear);


  index=0;
  for(i=0;datatotal[i]!='a';i++)
  {
    datarraymodo[index]=datatotal[i];
    index++;
  }
  i++;
  j=i;
  index=0;

  for(i=j;datatotal[i]!='a';i++)
  {
    datarraycharred[index]=datatotal[i];
    index++;
  }
  i++;
  j=i;
  index=0;
  
   for(i=j;datatotal[i]!='a';i++)
  {
    datarraychargreen[index]=datatotal[i];
    index++;
  }
  i++;
  j=i;
   index=0;
  
   for(i=j;datatotal[i]!='a';i++)
  {
    datarraycharblue[index]=datatotal[i];
    index++;
  }

////arranging the char array
//WE NEED TRUE INTEGER DATA
for(i=0;i<4;i++)
{
if (datarraymodo[3]=='F')
{
datarraymodo[3]=datarraymodo[2];
datarraymodo[2]=datarraymodo[1];
datarraymodo[1]=datarraymodo[0];
datarraymodo[0]='0';
}
}

for(i=0;i<4;i++)
{
if (datarraycharred[3]=='F')
{
datarraycharred[3]=datarraycharred[2];
datarraycharred[2]=datarraycharred[1];
datarraycharred[1]=datarraycharred[0];
datarraycharred[0]='0';
}
}

for(i=0;i<4;i++)
{
if (datarraychargreen[3]=='F')
{
datarraychargreen[3]=datarraychargreen[2];
datarraychargreen[2]=datarraychargreen[1];
datarraychargreen[1]=datarraychargreen[0];
datarraychargreen[0]='0';
}
}

for(i=0;i<4;i++)
{
if (datarraycharblue[3]=='F')
{
datarraycharblue[3]=datarraycharblue[2];
datarraycharblue[2]=datarraycharblue[1];
datarraycharblue[1]=datarraycharblue[0];
datarraycharblue[0]='0';
}
}

 datamodo = atoi(datarraymodo);
 if(datamodo!=0)
 {
 datared = atoi(datarraycharred);
 datagreen = atoi(datarraychargreen);
 datablue = atoi(datarraycharblue);
datared=map(datared,0,1023,0,255);
datagreen=map(datagreen,0,1023,0,255);
datablue=map(datablue,0,1023,0,255);
 }
}


void modochill()
 {
//when first time on chill mode, set random numbers
      if(indexchill==0){
  datared=random(170, 255); 
    datagreen=random(85, 170); 
      datablue=random(0, 85); 
      indexchill=1;

    }

  //after first time just wave the values
  if(datared>=250)
  {ired=1;}
  if(datared<=3)
  {ired=0;}
  if(ired==0)
  {datared=datared+3;}
  if(ired==1)
  {datared=datared-3;}
  
  if(datagreen>=240)
  {igreen=1;}
  if(datagreen<=3)
  {igreen=0;}
  if(igreen==0)
  {datagreen=datagreen+3;}
  if(igreen==1)
  {datagreen=datagreen-3;}
  
  
  if(datablue>=240)
  {iblue=1;}
  if(datablue<=3)
  {iblue=0;}
  if(iblue==0)
  {datablue=datablue+3;}
  if(iblue==1)
  {datablue=datablue-3;}


 
  }
TX, transmitter with three different functionsC/C++
mode 0 0
just chill, the receiver waves the colours slowly

mode 1 0
read and send analog values

mode 0 1
read colours with rgb sensor

mode 1 1
calibrate rgb sensor
#include <VirtualWire.h>
#define LEDRED A0
#define LEDGREEN A1
#define LEDBLUE A2
#define LIGHTSENSOR A3
#define TX 10
#define buttonA 5
#define buttonB 6
//variables TX - RX
char separador [2] = {"a"};
char datarraycharred[(sizeof(int)*4+1)];
char datarraychargreen[(sizeof(int)*4+1)];
char datarraycharblue[(sizeof(int)*4+1)];
char datamodo[(sizeof(int)*4+1)];
char datatotal[(sizeof(int)*4+3)*3];


int index=0,ired=0,igreen=0,iblue=0;
int datared=0,datagreen=0,datablue=0 ; //cm/seg 
int modo=0;

//for led copycat
int ledArray[] = {2,3,4};
int red = 0;
int green = 0;
int blue = 0;
int avgRead;
float colourArray[] = {0,0,0};
float whiteArray[] = {0,0,0};
float blackArray[] = {0,0,0};


void setup() {
  pinMode(LEDRED,OUTPUT);
  pinMode(LEDGREEN,OUTPUT);
  pinMode(LEDBLUE,OUTPUT);
    pinMode(LIGHTSENSOR,INPUT);
  pinMode(buttonA,INPUT);
  pinMode(buttonB,INPUT);
  pinMode(TX,OUTPUT);
  //ledarray copycat
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
   digitalWrite(2,HIGH);
   digitalWrite(3,HIGH);
   digitalWrite(4,HIGH);
  
  Serial.begin(9600);
  pinMode(TX, INPUT);
   pinMode(TX, OUTPUT);
  vw_set_tx_pin(TX);          // Configura el pin  como TX
  vw_set_ptt_inverted(true);  // Requerido para DR3100
  vw_setup(2000);             // Bits por segundo
  

}

void loop() {
if(digitalRead(buttonA)==0&&digitalRead(buttonB)==0)
modochill();
  
  
if(digitalRead(buttonA)==1&&digitalRead(buttonB)==0)
modoanalogico();

if(digitalRead(buttonB)==1)
modoLEDcopycat();
 

//construccion del array de datos a enviar
strcpy (datatotal,datamodo);
strcat (datatotal,separador);
strcat (datatotal,datarraycharred);
strcat (datatotal,separador);
strcat (datatotal,datarraychargreen);
strcat (datatotal,separador);
strcat (datatotal,datarraycharblue);
strcat (datatotal,separador);



//DEBUG
//Serial.print(datatotal);
Serial.print("  ");
Serial.println(datatotal);



  
//ENVIO RX
 
 digitalWrite(13, HIGH); // Turn on a light to show transmitting
 vw_send((uint8_t *)datatotal, strlen(datatotal));
 vw_wait_tx(); // Wait until the whole message is gone
  delay(50); 
 digitalWrite(13, LOW); // Turn off a light after transmission

}







//mode chillout defined at receiver, just freeze the dataflow and send modo=0
void modochill(){
  modo=0;
  itoa(modo,datamodo,10);//10--> base decimal
  }


//mode and data rgb analog
void modoanalogico(){
  modo=1;
  itoa(modo,datamodo,10);//10--> base decimal
  //analog read and int to char conversion
datared=analogRead(LEDRED);
itoa(datared,datarraycharred,10);//10--> base decimal
datagreen=analogRead(LEDGREEN);
itoa(datagreen,datarraychargreen,10);
datablue=analogRead(LEDBLUE);
itoa(datablue,datarraycharblue,10);
}



void modoLEDcopycat()
{
      if(digitalRead(buttonA)==1&&digitalRead(buttonB)==1){setBalance();}


 for(int i = 0;i<=2;i++){
     digitalWrite(ledArray[i],LOW);  //turn or the LED, red, green or blue depending which iteration
     delay(100);                      //delay to allow CdS to stabalize, they are slow
     getReading(5);                  //take a reading however many times
     colourArray[i] = avgRead;        //set the current colour in the array to the average reading
     float greyDiff = whiteArray[i] - blackArray[i];                    //the highest possible return minus the lowest returns the area for values in between
     colourArray[i] = (colourArray[i] - blackArray[i])/(greyDiff)*255; //the reading returned minus the lowest value divided by the possible range multiplied by 255 will give us a value roughly between 0-255 representing the value for the current reflectivity(for the colour it is exposed to) of what is being scanned
     digitalWrite(ledArray[i],HIGH);   //turn off the current LED
     delay(100);
     
     }

//rgb con catodo comun , dar la vuelta al valor de intensidad con map
analogWrite(LEDRED,map(colourArray[0],0,255,255,0));
analogWrite(LEDGREEN,map(colourArray[1],0,255,255,0));
analogWrite(LEDBLUE,map(colourArray[2],0,255,255,0));

  
}


//asymetric blink for humans to notice
void piiipipi(){

   digitalWrite(10,LOW);
   digitalWrite(11,LOW);
   digitalWrite(12,LOW);
   delay(1000);
   digitalWrite(10,HIGH);
   digitalWrite(11,HIGH);
   digitalWrite(12,HIGH);
   delay(500);
   digitalWrite(10,LOW);
   digitalWrite(11,LOW);
   digitalWrite(12,LOW);
   delay(500);
   digitalWrite(10,HIGH);
   digitalWrite(11,HIGH);
   digitalWrite(12,HIGH);
   delay(500);
   digitalWrite(10,LOW);
   digitalWrite(11,LOW);
   digitalWrite(12,LOW);
   delay(500);
   digitalWrite(10,HIGH);
   digitalWrite(11,HIGH);
   digitalWrite(12,HIGH);
   delay(1000);   
   
}

//when two buttons pressed, calibrate the rgb readings with white and black objects
void setBalance(){

 piiipipi() ;
                             
  for(int i = 0;i<=2;i++){
     digitalWrite(ledArray[i],LOW);
     delay(100);
     getReading(5);          //number is the number of scans to take for average, this whole function is redundant, one reading works just as well.
     whiteArray[i] = avgRead;
     digitalWrite(ledArray[i],HIGH);
     delay(100);
  }
  //done scanning white, now it will pulse blue to tell you that it is time for the black (or grey) sample.
   //set black balance
 piiipipi() ;
  //go ahead and scan, sets the colour values for red, green, and blue when exposed to black
  for(int i = 0;i<=2;i++){
     digitalWrite(ledArray[i],LOW);
     delay(100);
     getReading(5);
     blackArray[i] = avgRead;
     //blackArray[i] = analogRead(2);
     digitalWrite(ledArray[i],HIGH);
     delay(100);
  }
  //delay another 5 seconds to allow the human to catch up to what is going on
delay(5000);
  }

//get the colour!
  void getReading(int times){
  int reading;
  int tally=0;
  //take the reading however many times was requested and add them up
for(int i = 0;i < times;i++){
   reading = analogRead(LIGHTSENSOR);
   tally = reading + tally;
   delay(10);
}
  }

Schematics

Transmitter module
Tx
receiver module
i have two of this , one for each wheel
Rx

Comments

Similar projects you might like

The Magnetic Field and RGB Tester

Project tutorial by Kutluhan Aktar

  • 3,530 views
  • 0 comments
  • 14 respects

Arduino RGB Color Mixer

Project tutorial by FIELDING

  • 3,199 views
  • 1 comment
  • 11 respects

Codename RGB

Project tutorial by Stefano Gerli

  • 5,486 views
  • 1 comment
  • 18 respects

RGB Camera Backlight Control With Android Mobile

Project tutorial by DIY Partners

  • 1,292 views
  • 1 comment
  • 7 respects

Christmas Star with RGB LEDs

Project tutorial by Team ArduinoNSK

  • 1,484 views
  • 0 comments
  • 5 respects

Arduino controlled RGB LED strip

Project tutorial by Raphael Nestler and Danilo Bargen

  • 21,695 views
  • 2 comments
  • 19 respects
Add projectSign up / Login