Skip to content

ATtiny85 Driving WS2812

  • by

I’m working on driving some WS 2812 lights with an ATtiny85 using the WS 2812 library from this github project.

Setup AVR Tools For Mac

Using homebrew I installed the avr-gcc (AVR C code cross compiler) and avrdude (tool to write data to AVR chips)

brew tap osx-cross/avr
brew install avr-gcc
brew install avrdude

I’m using a SparkFun Tiny AVR Programmer with a socket for the ATtiny85 built in. I pop the ATtiny85 in the programmer and the programmer in my USB port at run a test to make sure everything is working:

FlyerII:~ ben$ avrdude -p attiny85 -c usbtiny

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b (probably t85)

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

Note the default fuse values (E:FF, H:DF, L:62).

Change ATtiny85 Clock Fuse

The library I’m using to drive the WS 2812 lights requires a clock of at least 8MHz. The ATtiny85 has a built in 8MHz clock but it is subdivided to run at 1MHz by default. To get it running at 8MHz I use avrdude to change lower byte fuse value from the default value 0x62 to the new value 0xE2. This sets the CKDIV8 fuse bit to 0 causing the microcontroller to run at the full 8MHz clock rate.

FlyerII:~ ben$ avrdude -p attiny85 -c usbtiny -U lfuse:w:0xE2:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: reading input file "0xE2"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.01s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xE2:
avrdude: load data lfuse data from input file 0xE2:
avrdude: input file 0xE2 contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:E2)

avrdude done.  Thank you.

Note the modified fuse values (E:FF, H:DF, L:E2)

Build & Flash

I opened the file light_ws2812/light_ws2812_AVR/Makefile and changed the CPU clock frequency setting to

F_CPU = 8000000

So that it matches the ATiny85’s 8MHz internal clock rate.

Next, from the light_ws2812/light_ws2812_AVR directory, I built the examples with a simple make command

make

This creates several *.hex files. I flashed the RGB_blinky.hex like this.

FlyerII:light_ws2812_AVR ben$ avrdude -p attiny85 -c usbtiny -U flash:w:RGB_blinky.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "RGB_blinky.hex"
avrdude: input file RGB_blinky.hex auto detected as Intel Hex
avrdude: writing flash (358 bytes):

Writing | ################################################## | 100% 0.47s

avrdude: 358 bytes of flash written
avrdude: verifying flash memory against RGB_blinky.hex:
avrdude: load data flash data from input file RGB_blinky.hex:
avrdude: input file RGB_blinky.hex auto detected as Intel Hex
avrdude: input file RGB_blinky.hex contains 358 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.62s

avrdude: verifying ...
avrdude: 358 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:E2)

avrdude done.  Thank you.

Wiring Up The Lights

I soldered pins headers onto these WS 2812 lights to make them easy to chain together with different lengths.

WS2812 Lights

I wire up the light to the programmer pins that connect to the ATtiny85.

  • 5V to Vcc (Top right pin)
  • Dout to PB2 (Below Vcc)
  • Gnd to Gnd (Bottom left pin)
From https://github.com/MCUdude/MicroCore

Then there was red, green, and blue light

Ping Pong

For a bit more of a challenge I wrote a new program based on the example that drives three lights and looks like a light is bouncing back and forth.

/*
* Makes a light appear to bounce back and forth.
*/

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "light_ws2812.h"

struct cRGB led[3];
float position = 0;
float velocity = 0.004;
const uint8_t dt_ms = 50;
float MIN_POS = 0;
float MAX_POS = 2;

void UpdatePosition() {
    position += velocity * dt_ms;
    if (position >= MAX_POS) {
        position = MAX_POS;
        velocity *= -1;
    } else if (position <= MIN_POS) {
        position = MIN_POS;
        velocity *= -1;
    }
}

int main(void)
{
    while(1)
    {
        uint8_t red = 20;
        uint8_t green = 20; 
        UpdatePosition();
        uint8_t light1 = position < 1.0 ? 255 * (1.0 - position) : 20;
        uint8_t light2 = position < 1.0 ? 255 * position : 255 * (2.0 - position);
        uint8_t light3 = position < 1.0 ? 20 : 255 * (position - 1.0);

        led[0].r=red;led[0].g=green;led[0].b=light1;    // Write red to array
        led[1].r=red;led[1].g=green;led[1].b=light2;    // Write red to array
        led[2].r=red;led[2].g=green;led[2].b=light3;    // Write red to array

        ws2812_setleds(led,3);
        _delay_ms(dt_ms);
    }
}

This is saved as PingPong.c so I modified the Makefile to build it instead of the examples.

EXAMPLES  = PingPong

That produced PingPong.hex. After flashing it with avrdude and my Tiny AVR Programmer, I chained three WS2812 lights together I got this

Pitfalls

The header comments in RGB_blinky.c say to connect Dout to pin PB4. However, the default pin for Dout is actually PB2. The Dout pin is defined in light_ws2812/light_ws2812_AVR/Light_WS2812/light_ws2812.h. It took me too long to figure out why I didn’t see any data coming out of PB4.

Leave a Reply

Your email address will not be published. Required fields are marked *