Christmas Lights powered by an ATtiny13

While waiting for my bread to rise the other day, I moved my breadboard ATtiny13 circuit that blinked two leds to a small Radio Shack perfboard, added a couple of switching transistors (2N3904s) to power the LEDs, and built a small 7805 regulator (which doesn’t yet have any filter caps, I’ll get to that). But, I couldn’t resist powering it on. And after finding a small solder bridge (a hairlike strand that spattered and connected two of the microcontroller pins), it worked!

Hopefully this stuff will get mounted in a hat this weekend. Stay tuned for the final video.

Addendum: I received one request for the source code. It’s trivial. Here you go.

#define F_CPU   1200000UL

#include <avr/io.h>
#include <util/delay.h>

/*
 * xmas.c 
 *
 * A small program for the ATtiny13 that can control two strands of 
 * Christmas lights.   I found a set of batter powered LED Christmas 
 * lights at CVS on sale for $.99 each.   I took the lights out, and 
 * found that they consisted of two strands: one of 4 red and 4 yellow
 * LEDs, and the other of 4 blue and 3 green LEDS.  Each strand is 
 * wired in parallel and draws about 20ma at 3 volts.  I have a few
 * ATtiny13's lying around, which can use between 2.7 and 5.5 volts supply.
 * I think for this test, I'll wire up a little 7805 regulator to provide
 * 5V, and then control each strand with one of the two PWM outputs.
 * If I want to drive the strings directly from the microcontroller, 
 * I'll have to insert another 50 ohms of resistance to limit the current 
 * to around 20ma per pin.  I could also add a 1K resistor and a small 
 * NPN transistor to drive each pin at the higher voltage.  At 5V, the 
 * strand will draw about 120ma.  
 */

#define LED0    PB0             /* pin 5 on the ATtiny13 */
#define LED1    PB1             /* pin 6 on the ATtiny13 */
#define SWITCH  PB4             /* pin 3 on the ATtiny13 */

int brite, dir ;

int swd = 0 ;
int swu = 0 ;

int
main(void)
{
    DDRB |= (1 << LED0) ;       /* set both LEDs as outputs */
    DDRB |= (1 << LED1) ;
    DDRB &= ~(1 << SWITCH) ;    /* and the switch as an input */
    PORTB |= (1 << SWITCH) ;    /* and activate the internal pull up */

    /* This configures the PWM outputs to be in "Fast PWM" mode. */
    TCCR0A |= (1 << WGM01) | (1 << WGM00) ;

    /* Timer is clocked at F_CPU/8 */
    TCCR0B |= (1 << CS01) ;

    /* COM01 COM00 
     *   0     0     | normal port operation, output compare disconnected
     *   0     1     | toggle output on compare match
     *   1     0     | clear output on compare match
     *   1     1     | set output on compare match
     */
  
    TCCR0A |= ((1 << COM0A1))  ;
    TCCR0A |= ((1 << COM0B1))  ;
    OCR0A = 0;
    OCR0B = 0;

    for (;;) {
        /* SOLID ON */
        for (;;) {              
            OCR0A = 0xff ;
            OCR0B = 0xff ;
            _delay_ms(1) ;
            if ((PINB & (1<<SWITCH)) == 0) 
                break ;
        }
        while ((PINB & (1<<SWITCH)) == 0) ;
 
        /* CROSS FADE */
        brite = 0 ;
        dir = 1 ;
        for (;;) {
            OCR0A = brite ;
            OCR0B = brite ^ 0xFF ;
            brite += dir ;
            if (brite == 0 || brite == 255)
                dir = -dir ;
            _delay_ms(2) ;
            if ((PINB & (1<<SWITCH)) == 0) 
                break ;
        }
        while ((PINB & (1<<SWITCH)) == 0) ;

        /* BLINK */
        brite = 0xff ;
        for (;;) {
            OCR0A = brite ;
            OCR0B = brite ;
            _delay_ms(500) ;
            brite ^= 0xff ;
            if ((PINB & (1<<SWITCH)) == 0) 
                break ;
        }
        while ((PINB & (1<<SWITCH)) == 0) ;

        /* CROSS BLINK */
        for (;;) {
            OCR0A = 0xff ;
            OCR0B = 0 ;
            _delay_ms(500) ;
            if ((PINB & (1<<SWITCH)) == 0) 
                break ;
            OCR0A = 0 ;
            OCR0B = 0xff ;
            _delay_ms(500) ;
            if ((PINB & (1<<SWITCH)) == 0) 
                break ;
        }
        while ((PINB & (1<<SWITCH)) == 0) ;

    }
}