There was a time when controlling RGB LEDs was not always an easy task. I this article I would like to show how to make it without difficulty using one ATtiny13 and LEDs based on WS2811/WS2811 driver.
The addressable LEDs are using protocol similiar to OneWire (very time-depended protocol) and can be connected together to create a strip of LEDs. The brightness of each LED color can be adjusted using pulse-width modulation to one of 256 different levels. That means there are 16,777,216 (2563) possible combinations of colors. We can produce any color from white (all colors on) to pseudo-black (all colors off).
There are a few existing libraries that can help us to do that on ATtiny13 – i.e. light_ws2812 (tested with v2.4) or pololu-led-strip-avr. In my projects I decided to use light_ws2812 because it occured to be more stable and predictible for this small chip. Due to ATtiny13 limitations we can’t controll huge number of addressable LEDs but it’s far enough to manage up to eight LEDs. I’ve created several demo examples which are presented bellow. Have fun!
Parts List
- ATtiny13 – i.e. MBAVR-1 development board
- LEDs – LEDs RGB WS2811 (12V) or WS2812 (5V)
Circuit Diagram
Examples
Classic Rainbow
Software for “Rainbow on single LED”
This code is written in C and can be compiled using the avr-gcc. More details on how compile this project is here. Complete code is on GitHub.
#include <avr/io.h> #include <util/delay.h> #include "light_ws2812.h" struct pixel { uint8_t g; uint8_t r; uint8_t b; }; int main(void) { struct pixel p = {255, 0, 0}; /* loop */ while (1) { if (p.r > 0 && p.b == 0) { p.r--; p.g++; } if (p.g > 0 && p.r == 0) { p.g--; p.b++; } if (p.b > 0 && p.g == 0) { p.r++; p.b--; } ws2812_setleds((struct cRGB *)&p, 1); _delay_ms(10); } }
Software for “Rainbow on several LEDs”
This code is written in C and can be compiled using the avr-gcc. More details on how compile this project is here. Complete code is on GitHub.
#include <avr/io.h> #include <util/delay.h> #include "light_ws2812.h" #define PIXEL_NUM (7) struct pixel { uint8_t g; uint8_t r; uint8_t b; } pixels[PIXEL_NUM]; int main(void) { uint8_t i; struct pixel p = {255, 0, 0}; /* loop */ while (1) { if (p.r > 0 && p.b == 0) { p.r--; p.g++; } if (p.g > 0 && p.r == 0) { p.g--; p.b++; } if (p.b > 0 && p.g == 0) { p.r++; p.b--; } for (i = 0; i < PIXEL_NUM; ++i) { pixels[i] = p; } ws2812_setleds((struct cRGB *)pixels, PIXEL_NUM); _delay_ms(10); } }
Circular LED chaser
This code is written in C and can be compiled using the avr-gcc. More details on how compile this project is here. Complete code is on GitHub.
#include <avr/io.h> #include <util/delay.h> #include "light_ws2812.h" #define PIXEL_NUM (8) #define DELAY (60) struct pixel { uint8_t g; uint8_t r; uint8_t b; } pixels[PIXEL_NUM]; static void setpixel(uint8_t id, struct pixel *p); int main(void) { uint8_t i, k = 0, r = 255, g = 0, b = 0; struct pixel p = {0, 0, 0}; /* loop */ while (1) { /* set the color */ p = (struct pixel){g, r, b}; for (i = k; i < (PIXEL_NUM + k); ++i) { setpixel(i % PIXEL_NUM, &p); _delay_ms(DELAY); } /* clear the color */ p = (struct pixel){0, 0, 0}; for (i = k; i < (PIXEL_NUM + k); ++i) { setpixel(i % PIXEL_NUM, &p); _delay_ms(DELAY); } /* choose next color */ if (r == 255) { g = 255; r = 0; } else if (g == 255) { g = 0; b = 255; } else { // b == 255 b = 0; r = 255; } /* set pixel shift */ k = ++k % PIXEL_NUM; } } void setpixel(uint8_t id, struct pixel *p) { pixels[id] = *p; ws2812_setleds((struct cRGB *)pixels, PIXEL_NUM); }
Hi
I’v problem to with cRGB in main.c
i’m using your program with ATtiny13
c:\WinAVR-20100110\t13_ws2812>make
MAKE Version 5.2 Copyright (c) 1987, 1998 Inprise Corp.
avr-gcc -std=c99 -Wall -g -Os -mmcu=attiny13 -DF_CPU=9600000 -I. -o main.o main.c light_ws2812.cpp
main.c:15: error: initializer element is not constant
main.c: In function ‘setpixel’:
main.c:118: warning: implicit declaration of function ‘ws2812_setleds’
cc1plus.exe: warning: command line option “-std=c99” is valid for C/ObjC but not for C++
** error 1 ** deleting all
c:\WinAVR-20100110\t13_ws2812>
Hi, you’re trying to compile C++ source (light_ws2812.cpp) with compiler flag “-std=c99” which is valid only for C-compiler.
/LP
Hi Lukasz
All is well 🙂
Thank you
you may be interested in this robot I made with an ATiny13
PCB Kicad 5.1.6: https://1drv.ms/u/s!All38Tl2pzx-jtdjggAFTdWnn1iCMA?e=ma4SzR
video: https://youtu.be/sAoR_p91vB8
Hi, Both project versions present wow-effect. I like it 🙂
/LP
I just can’t make any of the Arduino examples fit into ATTiny13
I’m using the arduino IDE to program the Tiny13
Did you try using this core – https://github.com/MCUdude/MicroCore ?
/LP
Hello Lukash, I really liked your project of the “Rainbow on several LEDs” luminaire, I really want to repeat it, but I am very weak in electronics, can I get a circuit for two ws2812 LEDs and firmware * .hex? do i need to flash the EEPROM? I will be glad to hear from you.
Hi Łukasz!
Is that possible to use your firmware with Attiny85?
Hi!
Which IDE have you used to make this project? I’m planning to use WinAVR.As I’ve very little knowledge of programming AVR.I need your suggestion.I’m using Windows 10.
hello , i want to know what is the limit of ws2812 led on a strip for the library, i currently have 144 led strip
and only 17 light up , i use this example 035_rainbow_on_several_leds_ws2812
i tried 20 doesnt work , only 17
this is what i edited in the main.c
define PIXEL_NUM (144)
thank you
Hi Steeve, if you want to control the LEDs separately then the 64B of RAM is your limit here.
/L
You are absolutely right! It’s all incorrect fuse bits. Now everything works!
Great! 🙂
/L
I work in Visual Micro (MS Visual Studio 2015) and before installing I set the frequency attiny to 9.6
If the fuse bits are set correctly then it should go fine. You can try with simple blinky program with 500ms delay and see whether it’s falshing once per second or not. It will prove that fuse bits and F_CPU=9.6MHz are ok.
Yes of course. I also tried 4.8 (<= 1.2 I see an error message) Also, in the file ws2812_config I put #define ws2812_resettime 50
Hi, Friend! I’m try to use your library (example “034_rainbow_on_single_led_ws2812”) with my attiny13a and have problem. My ws2812 led always white light. What is problem? PB0->DI, 5V power is common to tiny and led. Thanks!
Hi, did you set fuse bits to work with clock @9.6MHhz?
/L
1 this library does not work at all
2 why do you define pixel struct while there is already a cRGB struct available ?
Ad.1 This library works well on ATtiny13. It has been verified on several projects. What exactly the problem is?
Ad.2 This trick helps to redefine color field names for other LED drivers (RGB, GRB) and can be removed if not needed.