Christmas Lights powered by an ATtiny13

Published on 2011-12-16 by Mark VandeWettering

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.

[sourcecode lang=”cpp”]
#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) ;

}
}
[/sourcecode]