Color Changing LED Circuit upon power on

ledrgb

The circuit I plan to make will have 3 RGB LEDs in it and what I would Like is for it to change colour each time it turns on to a random colour. I'm a beginner level so any help will be greatly appreciated.

Best Answer

One way would be to use a microcontroller, if you're familiar with them. 3 output pins of a microcontroller (ANODE1, ANODE2, ANODE3) would get connected to 3 anodes of all RGB LEDs. Then 3 more output pins of a microcontroller (SELECT1, SELECT2, SELECT3) to 3 bases of NPN transitors, connected to 3 cathodes of the LEDs.

schematic

simulate this circuit – Schematic created using CircuitLab

So, to change a color of a single RGB LED, you would have to set one of the SELECT pins high and other two low, then you would need to set ANODE pins to random (high or low). Of course due to multiplexing you would have to do this over and over again to make it appear like all of RGB LEDs are on all the time. But the good thing is, you could use a small microcontroller like AVR attiny25 with only 8 pins.

If you'd be working with AVR, the code would look something like this:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define WORK_DDR     DDRD
#define WORK_PORT    PORTD
#define ANODE1       PIND0
#define ANODE2       PIND1
#define ANODE3       PIND2
#define SELECT1      PIND3
#define SELECT2      PIND4
#define SELECT3      PIND5   

// From: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=254771
#define RANDOM       (uint8_t)((double)rand() / ((double)RAND_MAX + 1) * 2)     

// Generate states for each LED and save them for further use:
// 3 states (red, green, blue) either on or off for 3 LEDs
uint8_t led_states[3][3] = 
{
    {RANDOM, RANDOM, RANDOM}, // RGB for first LED
    {RANDOM, RANDOM, RANDOM}, //RGB for second LED
    {RANDOM, RANDOM, RANDOM} // RGB for third LED
};

volatile uint8_t selected_led = 0; // Currently selected RGB LED for display

int main(void)
{
    WORK_PORT = 0; // Set all pins to low
    WORK_DDR |= ((1<<ANODE1) | (1<<ANODE2) | (1<<ANODE3) |
             (1<<SELECT1) | (1<<SELECT2) | (1<<SELECT3)); // Set defined pins as outputs

    sei(); // Enable interrupts
    // Set timer0 for changing the selected RGB LED:
    TCCR0A = (1<<WGM01); // Timer0 CTC mode
    TIMSK = (1<<TOIE0); // Enable interrupt on timer0 overflow
    OCR0A = 31; // ~60Hz on 1MHz clock
    TCCR0B = (1<<CS02); // Start Timer0 with 256x prescaler

    // Infinite loop
    while (1) {

    }
}

// Timer0 overflow interrupt
ISR(TIMER0_OVF_VECT) 
{
    // If we have currently selected last (third) LED, select first one, else just select next one
    if (selected_led == 2) {
        selected_led = 0;           
        WORK_PORT = (1<<SELECT1); // Select first RGB LED
        WORK_PORT |= ((led_states[0][0]<<ANODE1) | (led_states[0][1]<<ANODE2) |  
                  (led_states[0][2]<<ANODE3)); // Update first RGB LED with saved RGB status
    } else {
        // Select next RGB LED
        selected_led += 1;

        if (selected_led == 1) {
            WORK_PORT = (1<<SELECT2);
            WORK_PORT |= ((led_states[1][0]<<ANODE1) | (led_states[1][1]<<ANODE2) | 
                      (led_states[1][2]<<ANODE3)); // Update second RGB LED with saved RGB status
        } else {
            WORK_PORT = (1<<SELECT3);
            WORK_PORT |= ((led_states[2][0]<<ANODE1) | (led_states[2][1]<<ANODE2) | 
                      (led_states[2][2]<<ANODE3)); // Update third RGB LED with saved RGB status
        }
    }
}

Note that this is not tested, so I'm not enterely sure this will work, but feel free to try it and let me know if something isnt working.