I ordered a 5m strip of 5050 RGB analog LED’s – not the digital individually addressable ones, just the ones that the whole strip changes at once.

So I’ve combined my ATtiny85 plus ULN2803 project with my RGB LED project and came up with a tiny LED driver.

Essentially we have a 12V power supply that is tapped off into a 7805 to provide 5V to the ATtiny85 and ULN2803, and the raw 12V powers the LED strip:

img

I may add something like a trimpot or button to vary the colour/speed/mode later – for instance have it fixed at red, or green or blue, or fade.

I could have used N-channel MOSFETs or NPN transistors to control the LED strip as described here, but the ULN2803 is simpler, tidier and can cope with at least a metre of LED’s, who wants to use discretes?!

The code is unmodified from the RGB LED project, due to the way the ULN2803 and LED strips work, you can just move a couple of wires around and its done. I used the following Makefile to program the ATtiny85 using my usbasp:

ISP_PROG     	   = usbasp
BOARD_TAG          = attiny85at8
ALTERNATE_CORE     = arduino-tiny
ARDUINO_VAR_PATH   = ~/sketches/hardware/arduino-tiny/cores/tiny
ARDUINO_CORE_PATH  = ~/sketches/hardware/arduino-tiny/cores/tiny
AVRDUDE_OPTS       = -v

include /usr/share/arduino/Arduino.mk

I’ve also ordered some 5v/16MHz Sparkfun Pro Micro‘s to add a Boblight setup to my XBMC box.

The Pro Micro’s can be powered over USB and communicate with boblightd over USB (serial) too, so I can just make a breakout board to hold some transistors, take the 5v supply from the Vcc pin on the Pro Micro, and hold a DC barrel jack to feed 12v to the LED strips from a mains adaptor – no need to split the mains feed via a 7805 or UBEC.

It also uses the same ATmega32u4 chip as the Leonardo, so I might finally be able to debug/rewrite the reset code for arduino-mk, probably ditching the perl and going back to python but only using one script instead of 2-3 like before.

P.S. my weather station mk2 lasted a month on 2x AA eneloop batteries, a big improvement on the week I was getting before I added the P-channel MOSFET to cut the power to the peripherals.

Update: I added a pushbutton between pin 2 (D3) and GND to select the mode, and added some static colour/fade/flash functionality to the script:

// init vars
const int REDPIN = 1;   // pin 6
const int GREENPIN = 0; // pin 5
const int BLUEPIN = 4;  // pin 3
const int BUTTON = 3;   // pin 2
int red;
int green;
int blue;
int current_red;
int current_green;
int current_blue;
int previous = LOW;
int counter = 0;
unsigned long last_time = 0;

void doFade(int pin, int &val, int &current_val)
{
    // fade between random colours
    if (val > current_val)
    {
        current_val++;
        analogWrite(pin, current_val);
        delay(10);
    }
    else if (val < current_val)
    {
        current_val--;
        analogWrite(pin, current_val);
        delay(10);
    }
    else
    {
        analogWrite(pin, current_val);
        val = random(255);
    }
}

void fixedColour(int red, int green, int blue)
{
    // set individual leds
    analogWrite(REDPIN, red);
    analogWrite(GREENPIN, green);
    analogWrite(BLUEPIN, blue);
}

void setup()
{
    // set button to input with built-in pull-up
    pinMode(BUTTON, INPUT_PULLUP);

    // setup pin directions
    pinMode(REDPIN, OUTPUT);
    pinMode(GREENPIN, OUTPUT);
    pinMode(BLUEPIN, OUTPUT);

    // read from unconnected pin for entropy
    randomSeed(analogRead(2));
}

void loop()
{
    // take a reading
    int reading = digitalRead(BUTTON);

    // changed state - debounce=200ms
    if (reading == LOW && previous == HIGH && (millis() - last_time > 200))
    {
        // increment counter
        counter++;
        
        // store the time the button was pressed
        last_time = millis();
    }
    
    // store previous reading
    previous = reading;
        
    switch (counter)
    {
        case 0:
            // fade by default
            doFade(REDPIN, red, current_red);
            doFade(GREENPIN, green, current_green);
            doFade(BLUEPIN, blue, current_blue);
            break;
        case 1:
            // red
            fixedColour(255,0,0);
            break;
        case 2:
            // green
            fixedColour(0,255,0);
            break;
        case 3:
            // blue
            fixedColour(0,0,255);
            break;
        case 4:
            // cyan
            fixedColour(0,255,255);
            break;
        case 5:
            // magenta
            fixedColour(255,0,255);
            break;
        case 6:
            // yellow
            fixedColour(255,255,0);
            break;
        case 7:
            // white
            fixedColour(255,255,255);
            break;
        case 8:
            // flash randomly twice a second
            fixedColour(random(255),random(255),random(255));
            delay(500);
            break;
        case 9:
            // reset to fade
            counter = 0;
            break;
    }
}