<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://pauljmac.com/projects/index.php?action=history&amp;feed=atom&amp;title=TruckTree%21</id>
	<title>TruckTree! - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pauljmac.com/projects/index.php?action=history&amp;feed=atom&amp;title=TruckTree%21"/>
	<link rel="alternate" type="text/html" href="https://pauljmac.com/projects/index.php?title=TruckTree!&amp;action=history"/>
	<updated>2026-04-21T13:59:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://pauljmac.com/projects/index.php?title=TruckTree!&amp;diff=11&amp;oldid=prev</id>
		<title>Paul: Created page with &quot;This project is for a Christmas tree that I put in the back of my truck each year around that time. It uses a strand (or 2) of individually addressable RGB LEDs. The LEDs have a WS2811 driver IC which communicates using 1 wire serial. This is NOT to be confused with the WS2801 which is a 2 wire serial IC, and quite frankly a lot easier to work with. Luckily though, people like [http://bleaklow.com/ Alan Burlison] have already done the hard work for everyone and have been...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pauljmac.com/projects/index.php?title=TruckTree!&amp;diff=11&amp;oldid=prev"/>
		<updated>2024-12-08T16:07:33Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;This project is for a Christmas tree that I put in the back of my truck each year around that time. It uses a strand (or 2) of individually addressable RGB LEDs. The LEDs have a WS2811 driver IC which communicates using 1 wire serial. This is NOT to be confused with the WS2801 which is a 2 wire serial IC, and quite frankly a lot easier to work with. Luckily though, people like [http://bleaklow.com/ Alan Burlison] have already done the hard work for everyone and have been...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This project is for a Christmas tree that I put in the back of my truck each year around that time. It uses a strand (or 2) of individually addressable RGB LEDs. The LEDs have a WS2811 driver IC which communicates using 1 wire serial. This is NOT to be confused with the WS2801 which is a 2 wire serial IC, and quite frankly a lot easier to work with. Luckily though, people like [http://bleaklow.com/ Alan Burlison] have already done the hard work for everyone and have been nice enough to share. Alan has written a very good AVR driver for the nasty WS2811 chip which covers about 95% of the work. His article on it can be seen [http://bleaklow.com/2012/12/02/driving_the_ws2811_at_800khz_with_a_16mhz_avr.html here]. &lt;br /&gt;
&lt;br /&gt;
My project uses his WS2811.h and would not be possible at all without it. Thanks very much Alan!&lt;br /&gt;
&lt;br /&gt;
=Operation=&lt;br /&gt;
The idea here is to have a nice little tree in your truck that fades slowly randomly R G and B and everything in-between. But when you apply the brakes it will cause the whole tree to fade to red. When the brake are released it will go back to its normal random color stuff.&lt;br /&gt;
&lt;br /&gt;
The brake lights are hooked up to an opto isolator on the board which tell the micro when the brake is applied. &lt;br /&gt;
&lt;br /&gt;
There is a DC to DC converter on the board that will provide power for everything. Be mindful about the current limitations of it. It should be fine for at least 100 LEDs.&lt;br /&gt;
&lt;br /&gt;
These strands of lights are found on ebay. Just search for WS2811. &amp;#039;&amp;#039;&amp;#039;THE MANUFACTURING QUALITY OF THESE LIGHTS IS NOT GREAT&amp;#039;&amp;#039;&amp;#039;. You will most likely have to fix some bad solder joints and/or other things like that. Everything is &amp;quot;potted&amp;quot; so it makes it that much more difficult. Just be ready to do this kind of work.&lt;br /&gt;
&lt;br /&gt;
In hindsight… I have no idea why I chose to use the beefy TI switching regulator. Maybe I had a good reason when I drafted the original schematic some months ago but I can’t remember what it is now.  Maybe I thought it would use more current than it actually does? Yea that’s it… we’ll go with that. The reality is 2 strings does not use that much current and you could probably get away with using a linear regulator with some good heat dissipation.&lt;br /&gt;
&lt;br /&gt;
=Video and Pics=&lt;br /&gt;
http://www.youtube.com/watch?v=dCNIRQI3RAA&lt;br /&gt;
&lt;br /&gt;
[[Image:20130119 181255.jpg|none|thumb|Tree with color!]][[Image:20130119 181305.jpg|none|thumb|Tree all red!]][[Image:DSCF0516.JPG|none|thumb|A completed board. ]]&lt;br /&gt;
&lt;br /&gt;
=Board and schematic=&lt;br /&gt;
[http://pauljmac.com/projects/images/4/4c/Main.pdf Schem]&lt;br /&gt;
&lt;br /&gt;
[http://pauljmac.com/projects/images/9/91/Truck_Tree_PCB.zip Gerbers]&lt;br /&gt;
&lt;br /&gt;
[http://pauljmac.com/projects/images/3/33/TruckTree_Eagle.zip EagleCAD]&lt;br /&gt;
&lt;br /&gt;
[[Image:TruckTree.png]]&lt;br /&gt;
&lt;br /&gt;
=BOM=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Qty	Value	Part Num	Package	Parts&lt;br /&gt;
3		*	FE08	PORTB, PORTC, PORTD&lt;br /&gt;
1		609-3218-ND	MA03-2	ISP&lt;br /&gt;
4	.1uF	311-1361-1-ND	C0805K	C4, C6, C7, C8&lt;br /&gt;
1	1.4K	RHM1.40KBDCT-ND	R1210	R1&lt;br /&gt;
1	2.2uF	490-1733-1-ND	C0805K	C3&lt;br /&gt;
1	4N25SM	4N25SM-ND	DIL6-SMD	OK1&lt;br /&gt;
1	16MHz	535-10226-1-ND	HC49UP	Q1&lt;br /&gt;
2	18pF	399-9179-1-ND	C0805K	C1, C2&lt;br /&gt;
1	21k	P21.0KCCT-ND	M0805	R2&lt;br /&gt;
1	330uF	338-1790-1-ND	153CLV-0810	C5&lt;br /&gt;
1	ATMEGA88PA	ATMEGA88PA-AU-ND	TQFP32-08	IC1&lt;br /&gt;
1	Brake Signal	WM4201-ND	22-23-2031	BRAKE&lt;br /&gt;
1	PTN78020WAH	296-20515-ND	PTH	DC&lt;br /&gt;
1	Power	WM4201-ND	22-23-2031	POWER&lt;br /&gt;
1	TPPAD1-13Y	*	P1-13Y	INHIB&lt;br /&gt;
1	Tree	WM4201-ND	22-23-2031	TREE&lt;br /&gt;
3	WM2012-ND&lt;br /&gt;
9	WM1114CT-ND	&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
I am only posting my edited example file from Alan. You will need to grab the WS2811.h from Alan&amp;#039;s page. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright 2012 Alan Burlison, alan@bleaklow.com.  All rights reserved.&lt;br /&gt;
 * Use is subject to license terms.&lt;br /&gt;
 */&lt;br /&gt;
/* Fuse settings&lt;br /&gt;
BOOTSZ = 1024W_0C00&lt;br /&gt;
BOOTRST = [ ]&lt;br /&gt;
RSTDISBL = [ ]&lt;br /&gt;
DWEN = [ ]&lt;br /&gt;
SPIEN = [X]&lt;br /&gt;
WDTON = [ ]&lt;br /&gt;
EESAVE = [ ]&lt;br /&gt;
BODLEVEL = DISABLED&lt;br /&gt;
CKDIV8 = [ ]&lt;br /&gt;
CKOUT = [X]&lt;br /&gt;
SUT_CKSEL = EXTXOSC_8MHZ_XX_258CK_14CK_4MS1&lt;br /&gt;
&lt;br /&gt;
EXTENDED = 0xF9 (valid)&lt;br /&gt;
HIGH = 0xDF (valid)&lt;br /&gt;
LOW = 0x8E (valid)&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;WS2811.h&amp;quot;&lt;br /&gt;
#include	&amp;lt;stdlib.h&amp;gt; &lt;br /&gt;
&lt;br /&gt;
#define BIT(B)           (0x01 &amp;lt;&amp;lt; (uint8_t)(B))&lt;br /&gt;
#define SET_BIT_HI(V, B) (V) |= (uint8_t)BIT(B)&lt;br /&gt;
#define SET_BIT_LO(V, B) (V) &amp;amp;= (uint8_t)~BIT(B)&lt;br /&gt;
&lt;br /&gt;
#define bit_get(p,m) ((p) &amp;amp; (m))&lt;br /&gt;
#define bit_set(p,m) ((p) |= (m))&lt;br /&gt;
#define bit_clear(p,m) ((p) &amp;amp;= ~(m))&lt;br /&gt;
#define bit_flip(p,m) ((p) ^= (m))&lt;br /&gt;
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))&lt;br /&gt;
#define BIT(x) (0x01 &amp;lt;&amp;lt; (x))&lt;br /&gt;
#define LONGBIT(x) ((unsigned long)0x00000001 &amp;lt;&amp;lt; (x))&lt;br /&gt;
&lt;br /&gt;
#define PAUSE  500    // msec&lt;br /&gt;
#define DELAY    10	// msec&lt;br /&gt;
#define CHASE_SPEED    10	// msec&lt;br /&gt;
#define FADE_TO_RED_SPEED 1 // msec&lt;br /&gt;
#define RAND_MAX 0xFF&lt;br /&gt;
#define NUMBER_OF_NODES 100&lt;br /&gt;
#define COLOR_CHANGE_SPEED 1000&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t direction=0, LED_num=0;&lt;br /&gt;
 &lt;br /&gt;
// Define the output function, using pin 0 on port b.&lt;br /&gt;
DEFINE_WS2811_FN(WS2811RGB, PORTC, 0)&lt;br /&gt;
&lt;br /&gt;
RGB_t rgb[NUMBER_OF_NODES];&lt;br /&gt;
volatile uint8_t colorchange=0;&lt;br /&gt;
volatile uint8_t desired_color[NUMBER_OF_NODES][3];&lt;br /&gt;
&lt;br /&gt;
void Blank (void);&lt;br /&gt;
void All_Red (void);&lt;br /&gt;
void Random (void);&lt;br /&gt;
void Chase (void);&lt;br /&gt;
void Random_fader(void);&lt;br /&gt;
void Update_Colors(void);&lt;br /&gt;
&lt;br /&gt;
void main(void){	&lt;br /&gt;
	// Configure pin for output.&lt;br /&gt;
	SET_BIT_HI(DDRC, 0);&lt;br /&gt;
	SET_BIT_LO(PORTC, 0);&lt;br /&gt;
	SET_BIT_LO(DDRC, 1); //an input&lt;br /&gt;
	SET_BIT_HI(PORTC, 1); //enable pull up&lt;br /&gt;
	Blank();&lt;br /&gt;
	for (;;) {&lt;br /&gt;
		WS2811RGB(rgb, ARRAYLEN(rgb)); //call the LED driver&lt;br /&gt;
		_delay_ms(DELAY);&lt;br /&gt;
		if(bit_get(PINC, BIT(1)) == 0 ){ //if 0 then pressed&lt;br /&gt;
			_delay_ms(FADE_TO_RED_SPEED);&lt;br /&gt;
			Fade_to_red();&lt;br /&gt;
		}&lt;br /&gt;
		else{&lt;br /&gt;
			_delay_ms(FADE_TO_RED_SPEED);&lt;br /&gt;
			Update_Colors();&lt;br /&gt;
			Random_fader();&lt;br /&gt;
		}&lt;br /&gt;
		//Chase();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Blank (void){ //blanks the color of all the LEDs&lt;br /&gt;
	 for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
		 rgb[i].r = 0;&lt;br /&gt;
		 rgb[i].g = 0;&lt;br /&gt;
		 rgb[i].b = 0;&lt;br /&gt;
	 }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void All_Red (void){ //blanks the color of all the LEDs&lt;br /&gt;
	for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
		rgb[i].r = 255;&lt;br /&gt;
		rgb[i].g = 0;&lt;br /&gt;
		rgb[i].b = 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Fade_to_red(void){&lt;br /&gt;
	for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
		 if (rgb[i].r &amp;lt; 255 ){&lt;br /&gt;
			 rgb[i].r++;&lt;br /&gt;
		 }&lt;br /&gt;
		 if (rgb[i].g &amp;gt; 0 ){&lt;br /&gt;
			 rgb[i].g--;&lt;br /&gt;
		 }&lt;br /&gt;
		 if (rgb[i].b &amp;gt; 0 ){&lt;br /&gt;
			 rgb[i].b--;&lt;br /&gt;
		 }&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Update_Colors(void){&lt;br /&gt;
	static dominant_color;&lt;br /&gt;
	if (colorchange++ == 255){ //its time to change the color&lt;br /&gt;
		for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
			dominant_color=random() % 3;&lt;br /&gt;
			switch (dominant_color){&lt;br /&gt;
				case 0: //red is dominant color&lt;br /&gt;
				desired_color[i][0] = random();&lt;br /&gt;
				desired_color[i][1] = random() % 95;&lt;br /&gt;
				desired_color[i][2] = random() % 95;&lt;br /&gt;
				break;&lt;br /&gt;
				case 1: //green is dominant color&lt;br /&gt;
				desired_color[i][0] = random() % 95;&lt;br /&gt;
				desired_color[i][1] = random();&lt;br /&gt;
				desired_color[i][2] = random() % 95;&lt;br /&gt;
				break;&lt;br /&gt;
				case 2: //blue is dominant color&lt;br /&gt;
				desired_color[i][0] = random() % 95;&lt;br /&gt;
				desired_color[i][1] = random() % 95;&lt;br /&gt;
				desired_color[i][2] = random();&lt;br /&gt;
				break;&lt;br /&gt;
				default: //white&lt;br /&gt;
				desired_color[i][0] = random();&lt;br /&gt;
				desired_color[i][1] = random();&lt;br /&gt;
				desired_color[i][2] = random();&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		colorchange=0; //reset colorchange timer&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Random_fader(void){&lt;br /&gt;
	 //adjust the driven LED color to get close to the desired color&lt;br /&gt;
		for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
			 if (rgb[i].r &amp;gt; desired_color[i][0]){	//if driven color is greater than desired color&lt;br /&gt;
				 rgb[i].r--;						//decrease driven color&lt;br /&gt;
			 }&lt;br /&gt;
			 else if(rgb[i].r &amp;lt; desired_color[i][0]){ //if driven color is less than desired color&lt;br /&gt;
				 rgb[i].r++;						//increase driven color&lt;br /&gt;
			 }&lt;br /&gt;
			 if (rgb[i].g &amp;gt; desired_color[i][1]){	//if driven color is greater than desired color&lt;br /&gt;
				 rgb[i].g--;						//decrease driven color&lt;br /&gt;
			 }&lt;br /&gt;
			 else if(rgb[i].g &amp;lt; desired_color[i][1]){ //if driven color is less than desired color&lt;br /&gt;
				 rgb[i].g++;						//increase driven color&lt;br /&gt;
			 }&lt;br /&gt;
			  if (rgb[i].b &amp;gt; desired_color[i][2]){	//if driven color is greater than desired color&lt;br /&gt;
				 rgb[i].b--;						//decrease driven color&lt;br /&gt;
			 }&lt;br /&gt;
			 else if(rgb[i].g &amp;lt; desired_color[i][2]){ //if driven color is less than desired color&lt;br /&gt;
				 rgb[i].b++;						//increase driven color&lt;br /&gt;
			 }&lt;br /&gt;
		}		&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Random (void){&lt;br /&gt;
	_delay_ms(PAUSE);&lt;br /&gt;
	static dominant_color;&lt;br /&gt;
	for(int i=0; i&amp;lt;NUMBER_OF_NODES ; i++){&lt;br /&gt;
		dominant_color=random() % 3;&lt;br /&gt;
		switch (dominant_color){&lt;br /&gt;
				case 0: //red is dominant color&lt;br /&gt;
					rgb[i].r = random();&lt;br /&gt;
					rgb[i].g = random() % 125;&lt;br /&gt;
					rgb[i].b = random() % 125;&lt;br /&gt;
					break;&lt;br /&gt;
				case 1: //green is dominant color&lt;br /&gt;
					rgb[i].r = random() % 125;&lt;br /&gt;
					rgb[i].g = random();&lt;br /&gt;
					rgb[i].b = random() % 125;&lt;br /&gt;
					break;&lt;br /&gt;
				case 2: //blue is dominant color&lt;br /&gt;
					rgb[i].r = random() % 125;&lt;br /&gt;
					rgb[i].g = random() % 125;&lt;br /&gt;
					rgb[i].b = random();&lt;br /&gt;
					break;&lt;br /&gt;
				default: //white&lt;br /&gt;
					rgb[i].r = random();&lt;br /&gt;
					rgb[i].g = random();&lt;br /&gt;
					rgb[i].b = random();&lt;br /&gt;
					break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Chase (void){&lt;br /&gt;
	_delay_ms(CHASE_SPEED);&lt;br /&gt;
	static int rand=89;&lt;br /&gt;
	if (direction == 0){ // value of 0 for direction means its increasing&lt;br /&gt;
			if (LED_num &amp;gt; 0){&lt;br /&gt;
				rgb[LED_num-1].r = 0;&lt;br /&gt;
				rgb[LED_num-1].g = 0;&lt;br /&gt;
				rgb[LED_num-1].b = 0;&lt;br /&gt;
			}&lt;br /&gt;
			rgb[LED_num].r =random();&lt;br /&gt;
			rgb[LED_num].g =random();&lt;br /&gt;
			rgb[LED_num].b =random();&lt;br /&gt;
			LED_num++;&lt;br /&gt;
			if (LED_num == NUMBER_OF_NODES)	{&lt;br /&gt;
				direction = 1; //switch directions&lt;br /&gt;
			}&lt;br /&gt;
	}&lt;br /&gt;
	else{ //else value if direction means decreasing&lt;br /&gt;
		if (LED_num &amp;lt; NUMBER_OF_NODES){&lt;br /&gt;
			rgb[LED_num+1].r = 0;&lt;br /&gt;
			rgb[LED_num+1].g = 0;&lt;br /&gt;
			rgb[LED_num+1].b = 0;&lt;br /&gt;
		}&lt;br /&gt;
		rgb[LED_num].r =random();&lt;br /&gt;
		rgb[LED_num].g =random();&lt;br /&gt;
		rgb[LED_num].b = random();&lt;br /&gt;
		LED_num--;&lt;br /&gt;
		if (LED_num == 0)	{&lt;br /&gt;
			direction = 0; //switch directions&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Paul</name></author>
	</entry>
</feed>