how to use single switch for intensity or color control of RGB led

Status
Not open for further replies.

for better idea and good technique please check out these pages with working code

http://picprojects.org.uk/projects/bigmosfetrgb/index.htm

http://picprojects.org.uk/projects/rgb2/index.htm

http://picprojects.org.uk/projects/simplergb/index.htm

**broken link removed**

regards
Fragrance
 

thanks for your reply
i have seen these pages earlier.
i am not having any problem in generating the pwm hence rgb mode also.
but my basic problem is to change the sequences manually by using a single switch
 

i have seen these pages earlier.
i am not having any problem in generating the pwm hence rgb mode also.
but my basic problem is to change the sequences manually by using a single switch
 

You need to break the problem down into a few pieces.
Generally, there are maybe four ways to do what you're trying to achieve, in order of preference (1 being the most preferred).
1. Use three PWM channels, and a while() loop that just checks for button-presses, and updates the PWM registers. The PWM feature automatically adjusts the LED brightness. It needs a device with three PWM channels
2. Use a timer function, i.e. a timer interrupt, and whenever the interrupt occurs, in the interrupt function, check to see if you need to update the LED output pins, and do so if needed. Have a while() loop similar to (1), and use it to update some global variables that the timer interrupt function uses. It has some debounce complications but they can be resolved by disabling the interrupt for a certain number of while() loops for example.
3. Have the switch connected to an interrupt input, and whenever a switch interrupt occurs, update some global variables. These variables will be checked in a main while() function that is responsible for controlling the LED output pins.
4. Implement it all in a very complex while() loop with if() statements and delays in the main code. It is hard to maintain and very ugly.

You need to decide which method, depending on your microcontroller. Change microcontroller if necessary. There are microcontrollers with three PWM channels (ATmega springs to mind). Use the best method for the task at hand.

Anyway, to get to your point, this is how to change sequences with a single switch. It should complete your code, if PWM
is already working for you.
Inspect this code, it is all commented:
Code:
  while(1)
  {
  
    if (SWITCH_ON) // is the button pressed/
    {
      __delay_cycles(1000); // wait a bit for contact bounce allowance
      if (SWITCH_ON) // // repeat the check
      {
        index++; // cycle the color
        if (index==10) // let's assume we only have 10 colors to cycle around
        	index=0;
        	
        update_registers(index); // this programs the PWM channels
        
        // now wait for the switch to be released
        for (i=0; i<2000; i++) // we're going to wait about a couple of seconds
        {
        	__delay_cycles(100); // tiny (1 msec) delay approx
        	if (SWITCH_OFF) // if the switch has been released, we're done!
        		break;
        }
        __delay_cycles(1000); // wait a bit for contact bounce allowance
      }
    }

Notice that the code calls a function update_registers(). That function would be used to set the levels for all three channels.
Study the code in Bigdogguru's reply #5, because that is quite a nice implementation, for what to do next. It also uses the PWM method and has
some nice functions to set the PWM channel values.
Or the channel values could be set using the array of colors method that I showed you in reply #7. The index variable is the
desired_colors variable, I just renamed it.

Just for completeness, here is a simple PWM set-up step-by-step for AVR because that's what I'm familiar with.
This is how simple it is to use a PWM channel.
First, have your include files:
Code:
#include <ioxxx.h>
#include <intrinsics.h>
#include <avr_macros.h>
#include <stdio.h>

Then, define your input and output pins:
Code:
// Port B
#define LED 0x01
#define BUTTON 0x02

Then, create some definitions to make life easy for you:
Code:
// inputs
#define SWITCH_ON (PINB & BUTTON) == 0
#define SWITCH_OFF (PINB & BUTTON) != 0

// outputs
#define LED_ON PORTB |= LED
#define LED_OFF PORTB &= ~LED

// This is the PWM register, it is called OCR0A
#define LED_BRIGHTNESS OCR0A



Now, in the main() code, or in an init() type of function, you can set up the PWM feature:
Code:
int
main( void )
{

  // initialise
  PORTB=0;
  DDRB=0x01; // LED pin is output the rest of port B is inputs
  PORTB=0x3e; // enable pull-ups on all input pins
  // turn off the LED:
  LED_OFF;

	// Set up the PWM:
  OCR0A = 255; // set the dim level to 255 (lamp off)
  TCCR0A = 0xc3; // set COM0A1, COM0A0, WGM00, WGM01
  TCCR0B=0x01; // clear WGM02. Set the prescaler to divide by 1
  // end of initialisation  
  
  // done! now we can control the brightness by setting OCR0A
  // (i.e. LED_BRIGHTNESS) to 0..255 (0 being the brightest,
  // 255 being the dimmest)

It's that easy (this is for AVR, but the principle is the same, you need to study the user docs for the
device you're using). This is only one channel (so choose a microcontroller with three channels).
 
thanks a lot Mr. sky_123
i am using atmega16 for this purpose.
i used here OC0 for blue, OC1A for red & OC1B for green.
i generate pwm using phase correct pwm mode.
i generate the rainbow mode by increment each OCR one by one.
& make some functions for different colors like white();, red();, yellow(); & so on....
now for each press of switch i have to call these different function for different press of switch & it should stay
in that function till next press of swith to enter in next function.
now i'll try to use your code & then i'll inform you definitely.
if you get any idea about the code for it after reading the process then please inform too.
Because it may be possible that any one of us all, can get a better idea!!!!!!!!!!!!!!!!
thanks a lot
 
The code described will do exactly that, i.e. on each switch-press, it will select a different color, e.g.
red->pink->yellow->blue etc., or whatever sequence you wish. You just need to make sure that the
sequence you wish is defined in the array in reply#7. The code will index through the array each time
you press the switch.
 

i'll put the code soon as it will be completed fully

- - - Updated - - -

dear sky_123 sir
i have made the function & call them using switch & case statement
is it not fine!!!!!
 
There's not a lot to go wrong, you'll need to describe a bit clearer what's wrong.
As you know, it's not possible to help unless you can explain clearer.

How is your switch connected (do you have a pull-up) and I'm not sure what case statement
you're using (the code I described didn't have a case statement).
 

ok sir
i'll make it ok & then send you either it works or not
 

your button is going to set a variable,s value for which you have decided any particular color from pwm in code
switch press pin high (now in interrupt ------ ,set a bit only ,exit)
now in code poll for this ,[(bit = 1 ) AND (pin = 0)] now clear bit, inc variable
hope you got it
 

dear sir
as you send the prototype code here,
Code:
while(1)
  {
  
    if (SWITCH_ON) // is the button pressed/
    {
      __delay_cycles(1000); // wait a bit for contact bounce allowance
     [B] if (SWITCH_ON) // // repeat the check
      {
        index++; // cycle the color
        if (index==10) // let's assume we only have 10 colors to cycle around
        	index=0;[/B]
        	
        update_registers(index); // this programs the PWM channels
        
        // now wait for the switch to be released
        for (i=0; i<2000; i++) // we're going to wait about a couple of seconds
        {
        	__delay_cycles(100); // tiny (1 msec) delay approx
        	if (SWITCH_OFF) // if the switch has been released, we're done!
        		break;
        }
        __delay_cycles(1000); // wait a bit for contact bounce allowance
      }
    }
in above code (bold one) suppose index is 0 & now switch is on so untill switch is on index will increase in each cycle then how we get the exact index value?
 
if u have only one push key in your design then it can do your work in following manner
system colour change by x= x+1 with condition x=10/11/12 whatever makes x=1 again
where 1 to 10/11/12 are colour combinations ++++(at first if system on then x = 1)[never make x 0 Bcoz]++++
code start
x=0 /\/\/\/\/\/\/ u should be here until x = 1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,(how x becomes 1 ?, nice see down)
key = 1 ' this is simple period polling
time waste some msecs
(1)** key = 0 : here do x = x+1
(2)** key = 1 : here do x = 0 (and this is off condition of your system with the same key)
condition 1 = small press
condition 2 = long press
here u see x=0 makes all pins 0 led,z off
hops it simplifies to you
good luck
 

now switch is on so untill switch is on index will increase in each cycle then how we get the exact index value
Holding the switch on will not make necessarily make it keep increasing.
If you look further down the code:
Code:
// now wait for the switch to be released
        for (i=0; i<2000; i++) // we're going to wait about a couple of seconds
        {
        	__delay_cycles(100); // tiny (1 msec) delay approx
        	if (SWITCH_OFF) // if the switch has been released, we're done!
        		break;
        }
        __delay_cycles(1000); // wait a bit for contact bounce allowance
You can see that there is a 2-second period where it waits for you to release the button.
If you release in less than 2 seconds, then it will have only increased the index by 1.
If you hold it pressed for longer than 2 seconds, then it will cycle.
If you don't ever want it to cycle, then you could set the value to something very high (e.g. 60 seconds)
or replace the count with an appropriate while statement.
Notice that once the switch is released, it instantly breaks out of the loop and executes the debounce.
So, you could (say) repeatedly press, for example once every second, and this will increment index once
for every press. It won't hold for 2 seconds (or 60 seconds or whatever) if you release it.

As with any code, of course initialize your variables, for example at the point of declaration.
There is nothing wrong with starting index at zero (in fact, this is the right thing to do, because
the first array entry is at index [0]). You first index can correspond to all colors off, if you wish.
The idea that Rajat has about holding down the button to turn of the light is a very good one.
It's quite easy to implement by adding a few lines immediately after this line:
Code:
__delay_cycles(1000); // wait a bit for contact bounce allowance
The lines to add are:
Code:
if (i>=2000)
{
  index=0;
  update_registers(index);
}
Very simple : )
 
Last edited:

dear sir
this is my code for this purpose using pwm. i am not getting the switch programming. i have done it again & again as per your suggestions but till now i couldn't be able to do it successfully. i am using atmega16 for it please complete it according to atmega16. i'll be very thankful to you.

Code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


int main()
{
	unsigned char i,j,k;
	
	DDRB = 0x08;
	DDRD = 0x30;
	
		OCR0 = 255;   //blue  pb3
 		OCR1AH = 00;
		OCR1AL = 255;  //red  pd5
		OCR1BH = 00;
		OCR1BL = 255;  //green  pd4
		TCCR0 = 0x63;
		TCCR1B = 0x03;
		TCCR1A = 0xA1;
	
	while(1)
	{					
		red();
		_delay_ms(2000);
		
		white();
		_delay_ms(2000);
			
		yellow();
		_delay_ms(2000);
		lightyellow();
		_delay_ms(2000);
		
		green();
		_delay_ms(2000);		
		
		bluishgreen();
		_delay_ms(2000);
		
		lightblue();
		_delay_ms(2000);
		blue();
		_delay_ms(2000);
		
	
		lvoilet();
		_delay_ms(2000);
		bluishvoilet();
		_delay_ms(2000);
		voilet();
		_delay_ms(2000);		
		darkvoilet();
		_delay_ms(2000);
		
		
		
		
				
	
	
	
	
	return 0;
}

white(void)
{
	char i=0;
	OCR0 = i;
	OCR1AL = i;
	OCR1BL = i;
}

lightyellow(void)
{
	char i=0;
	OCR0 = 180;
	OCR1AL = 0;
	OCR1BL = 0;
}
yellow(void)
{
	char i=0;
	OCR0 = 255;
	OCR1AL = i;
	OCR1BL = i;
}
red(void)
{
	char i=0;
	OCR0 = 255;
	OCR1AL = i;
	OCR1BL = 255;	
}

voilet(void)
{
	char i=0;
	OCR0 = i;
	OCR1AL = i;
	OCR1BL = 255;
}
lvoilet(void)
{
	char i=0;
	OCR0 = i;
	OCR1AL = i;
	OCR1BL = 128;
}
darkvoilet(void)
{
	char i=0;
	OCR0 = 128;
	OCR1AL = i;
	OCR1BL = 255;
}
tdarkvoilet(void)
{
	char i=128;
	OCR0 = 192;
	OCR1AL = i;
	OCR1BL = 255;
}

blue(void)
{
	char i=20;
	OCR0 = i;
	OCR1AL = 255;
	OCR1BL = 255;
}
bluishgreen(void)
{
	char i=0;
	OCR0 = 0;
	OCR1AL = 128;
	OCR1BL = 0;
}

green(void)
{
	char i=20;
	OCR0 = 255;
	OCR1AL = 255;
	OCR1BL = i;
}

- - - Updated - - -

i know that it is not a optimize code for this purpose but i'll convert it to optimize that is not a big issue. please complete it with switch code.
thanks a lot
 
1. What does your code currently do? Does it function?
2. Having separate functions for each color is not scalable. How are you going to optimize this as you say?
3. Once it is optimized (hint: use an array as mentioned so many times, or if you insist on a separate function for each color then you need to move it out into
a separate function and use a 'switch' statement or an 'if' statement to execute the desired color function) then what is stopping you from using the switch code that has been described in detail?
 

yes,
according to my code, i have used functions for each color.
after each 2 sec the color will change. but as i have to use here a switch(button), after it i'll use here switch-case statement in each case i'll put the function of each color. when button press it will increment a variable & the value of variable will used as case number
 
Great. At least you know that the PWM is working in principle. It should take you less than 10 minutes to move from that code to something a bit more
optimized (in whichever way you choose) and then working with the switch (all the switch code is in the posts above).
 

i know that you are laughing on my a little bit knowledge ;-): smile:
i know that you have given the code to me
but unfortunately i am not getting the result
please help

- - - Updated - - -

please arrange the code in a sequence for me
thanks & regards
 

please arrange the code in a sequence for me
Sorry, the entire code to do all you've requested is in this thread. I don't think any tiny bit is missing to be honest.
I'd suggest the knowledge transfer is complete for this topic.
And if any tiny fragment is missing (which I don't think so, but I may be wrong), it is a good opportunity to debug and learn,
and if you get stuck, just post your error.
All you need to do is literally copy-and-paste. If you're not confident doing that, how did you write your code
in the first place?
If on the other hand you just want someone's completed project, there are resources for that (I think you were given links
to existing projects).
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…