1
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Please provide more context. Which LEDs? part number? How fast do they have to change. Did you already play with beginner level boards such as an Arduino? \$\endgroup\$ – Blup1980 Jul 8 '14 at 10:26
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I've never used the rand() function on an AVR but I think without calling srand() to specify the seed this would give the same result each time. Maybe you could use EEPROM to keep the last seed rolling along or something a bit random like charging a cap on an I/O line and measuring how long it takes to go low at high resolution. But it looks like a good starting point. \$\endgroup\$ – PeterJ Jul 8 '14 at 12:24
  • \$\begingroup\$ Yeah, you're right, I completely forgot about that... \$\endgroup\$ – Golaž Jul 8 '14 at 12:37
  • \$\begingroup\$ @PeterJ, I doubt it's any different simply because of the context of use (i.e. on an AVR), so I'll add that rand() without an srand() will simply resolve to the case where srand(1) was used and will be added at compile-time. \$\endgroup\$ – sherrellbc Jul 8 '14 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.