Difference between revisions of "LED christmas tree"
(added video link (plugin still doesn't work)) |
|||
Line 1: | Line 1: | ||
{{Project | {{Project | ||
− | |State= | + | |State=Completed |
|Members=Vicarious, Xopr | |Members=Vicarious, Xopr | ||
|Description=Blinken lights! | |Description=Blinken lights! | ||
}} | }} | ||
− | === synopsis === | + | === synopsis === |
− | |||
− | + | Create a christmas tree out of cartboard, leds, some RJ45 wire, tiny experiment print, headers, solder, Scotch-tape, a brown plastic instant-coffee container and an arduino. | |
− | + | ''I hereby declare freedom of firmware for the tree; change to whatever you want it; this was just a kick-start.'' | |
− | |||
− | + | === implementation === | |
− | + | Since the tree was already made two years ago, but the code (and/or Arduino) got lost, [[User:Xopr|Xopr]] took his [[Andon light]] arduino, and did an ugly rush job on making the leds identifiable. | |
− | === pics === | + | After identifying which port pin was which LED, I wrote some shifting logic to be able to call '''setLed( x, y )''' and '''clearLed( x, y )'''. |
− | Pics (or vid) or it didn't happen! | + | |
+ | Actually, I think writing about it on the wiki costs more time than actually pimping the tree, so here it is. | ||
+ | |||
+ | === pics === | ||
+ | |||
+ | Pics (or vid) or it didn't happen! | ||
{{#widget:Html5media | {{#widget:Html5media | ||
Line 23: | Line 26: | ||
|width=640 | |width=640 | ||
|height=360 | |height=360 | ||
− | }} | + | }} Since the video plugin still doesn't work, here a direct link: [[Media:Christmas_tree_and_message_ticker.mov]]. |
− | Since the video plugin still doesn't work, here a direct link: [[Media: | + | |
+ | === code === | ||
− | + | The current code running is the one pasted here (with some preparations on doing PWM) Arduino code (portable to plain avr-gcc): | |
− | The current code running is the one pasted here (with some preparations on doing PWM) | + | <pre>void setup() |
− | Arduino code (portable to plain avr-gcc): | ||
− | <pre> | ||
− | void setup() | ||
{ | { | ||
// Set tree pins as output | // Set tree pins as output | ||
Line 76: | Line 77: | ||
// Mapping | // Mapping | ||
byte g_mappedTree[4][4] = { | byte g_mappedTree[4][4] = { | ||
− | { 12, 9, 21, 13 }, // Row 1, Da Syntax helped me calculating the number 21 ;) | + | { 12, 9, 21, 13 }, // Row 1, Da Syntax helped me calculating the number 21 ;) |
{ 11, 29, 28, 27 }, // Row 2 | { 11, 29, 28, 27 }, // Row 2 | ||
{ 6, 4, 5, 30 }, // Row 3 | { 6, 4, 5, 30 }, // Row 3 | ||
Line 84: | Line 85: | ||
void loop() | void loop() | ||
{ | { | ||
− | for ( byte n = 0; n | + | for ( byte n = 0; n < 10; n++ ) |
horizontalBlink(); | horizontalBlink(); | ||
− | for ( byte n = 0; n | + | for ( byte n = 0; n < 10; n++ ) |
verticalBlink(); | verticalBlink(); | ||
− | for ( byte n = 0; n | + | for ( byte n = 0; n < 100; n++ ) |
randomBlink(); | randomBlink(); | ||
} | } | ||
Line 98: | Line 99: | ||
// Horizontal | // Horizontal | ||
− | for ( byte x = 0; x | + | for ( byte x = 0; x < 4; x++ ) |
{ | { | ||
// Vertical | // Vertical | ||
− | for ( byte y = 0; y | + | for ( byte y = 0; y < 4; y++ ) |
{ | { | ||
setLed( x, y ); | setLed( x, y ); | ||
Line 108: | Line 109: | ||
} | } | ||
// Horizontal | // Horizontal | ||
− | for ( byte x = 0; x | + | for ( byte x = 0; x < 4; x++ ) |
{ | { | ||
// Vertical | // Vertical | ||
− | for ( byte y = 0; y | + | for ( byte y = 0; y < 4; y++ ) |
{ | { | ||
clearLed( x, y ); | clearLed( x, y ); | ||
Line 126: | Line 127: | ||
// Vertical | // Vertical | ||
− | for ( byte y = 0; y | + | for ( byte y = 0; y < 4; y++ ) |
{ | { | ||
// Horizontal | // Horizontal | ||
− | for ( byte x = 0; x | + | for ( byte x = 0; x < 4; x++ ) |
{ | { | ||
setLed( x, y ); | setLed( x, y ); | ||
Line 136: | Line 137: | ||
} | } | ||
// Vertical | // Vertical | ||
− | for ( byte y = 0; y | + | for ( byte y = 0; y < 4; y++ ) |
{ | { | ||
// Horizontal | // Horizontal | ||
− | for ( byte x = 0; x | + | for ( byte x = 0; x < 4; x++ ) |
{ | { | ||
//setLed( x, y ); | //setLed( x, y ); | ||
Line 176: | Line 177: | ||
byte mappedPort = g_mappedTree[ _y ][ _x ]; | byte mappedPort = g_mappedTree[ _y ][ _x ]; | ||
// Determine the bit index (lower three bits) | // Determine the bit index (lower three bits) | ||
− | byte shiftBit = mappedPort & 7; | + | byte shiftBit = mappedPort & 7; |
// Find which port it is (shift out the lower three bits and get the index) | // Find which port it is (shift out the lower three bits and get the index) | ||
// And set the given bit | // And set the given bit | ||
− | switch ( mappedPort | + | switch ( mappedPort >> 3 ) |
{ | { | ||
case 0: | case 0: | ||
− | PORTB |= (1 | + | PORTB |= (1 << shiftBit); |
break; | break; | ||
case 1: | case 1: | ||
− | PORTE |= (1 | + | PORTE |= (1 << shiftBit); |
break; | break; | ||
case 2: | case 2: | ||
− | PORTG |= (1 | + | PORTG |= (1 << shiftBit); |
break; | break; | ||
case 3: | case 3: | ||
− | PORTH |= (1 | + | PORTH |= (1 << shiftBit); |
break; | break; | ||
} | } | ||
Line 208: | Line 209: | ||
byte mappedPort = g_mappedTree[ _y ][ _x ]; | byte mappedPort = g_mappedTree[ _y ][ _x ]; | ||
// Determine the bit index (lower three bits) | // Determine the bit index (lower three bits) | ||
− | byte shiftBit = mappedPort & 7; | + | byte shiftBit = mappedPort & 7; |
// Find which port it is (shift out the lower three bits and get the index) | // Find which port it is (shift out the lower three bits and get the index) | ||
// And clear the given bit | // And clear the given bit | ||
− | switch ( mappedPort | + | switch ( mappedPort >> 3 ) |
{ | { | ||
case 0: | case 0: | ||
− | PORTB &= ~(1 | + | PORTB &= ~(1 << shiftBit); |
break; | break; | ||
case 1: | case 1: | ||
− | PORTE &= ~(1 | + | PORTE &= ~(1 << shiftBit); |
break; | break; | ||
case 2: | case 2: | ||
− | PORTG &= ~(1 | + | PORTG &= ~(1 << shiftBit); |
break; | break; | ||
case 3: | case 3: | ||
− | PORTH &= ~(1 | + | PORTH &= ~(1 << shiftBit); |
break; | break; | ||
Revision as of 18:24, 4 September 2014
Project: LED christmas tree | |
---|---|
Featured: | |
State | Completed |
Members | Vicarious, Xopr |
GitHub | No GitHub project defined. Add your project here. |
Description | Blinken lights! |
Picture | |
Contents
synopsis
Create a christmas tree out of cartboard, leds, some RJ45 wire, tiny experiment print, headers, solder, Scotch-tape, a brown plastic instant-coffee container and an arduino.
I hereby declare freedom of firmware for the tree; change to whatever you want it; this was just a kick-start.
implementation
Since the tree was already made two years ago, but the code (and/or Arduino) got lost, Xopr took his Andon light arduino, and did an ugly rush job on making the leds identifiable.
After identifying which port pin was which LED, I wrote some shifting logic to be able to call setLed( x, y ) and clearLed( x, y ).
Actually, I think writing about it on the wiki costs more time than actually pimping the tree, so here it is.
pics
Pics (or vid) or it didn't happen!
Since the video plugin still doesn't work, here a direct link: Media:Christmas_tree_and_message_ticker.mov.
code
The current code running is the one pasted here (with some preparations on doing PWM) Arduino code (portable to plain avr-gcc):
void setup() { // Set tree pins as output DDRB = B11110000; DDRH = B01111000; DDRE = B00111010; DDRG = B00100000; // All lights on PORTB = B11110000; PORTE = B00111010; PORTG = B00100000; PORTH = B01111000; delay( 2000 ); // All lights off PORTB = 0; PORTE = 0; PORTG = 0; PORTH = 0; delay( 1000 ); } /* // Mapping of the pins on the tree are as followed (reverse-lookup pins from Arduino mega 1280): // {Port-and-pin-number}: {light-on-the-tree} {port-as-index-number,pin-number}: {resulting-mapping-index} PORTB7: top 0,7: 7 PORTB6: 3a 0,6: 6 PORTB5: 3c 0,5: 5 PORTB4: 3b 0,4: 4 PORTH6: 3d 3,6: 30 PORTH5: 2b 3,5: 29 PORTH4: 2c 3,4: 28 PORTH3: 2d 3,3: 27 PORTE5: 1d 1,5: 13 PORTE4: 1a 1,4: 12 PORTE3: 2a 1,3: 11 PORTE2: 1b 1,1: 9 PORTG5: 1c 2,5: 19 */ // Mapping byte g_mappedTree[4][4] = { { 12, 9, 21, 13 }, // Row 1, Da Syntax helped me calculating the number 21 ;) { 11, 29, 28, 27 }, // Row 2 { 6, 4, 5, 30 }, // Row 3 { 7, 7, 7, 7 }, // Top; yes it is only one led, so one pin }; void loop() { for ( byte n = 0; n < 10; n++ ) horizontalBlink(); for ( byte n = 0; n < 10; n++ ) verticalBlink(); for ( byte n = 0; n < 100; n++ ) randomBlink(); } void horizontalBlink() { // Add vertical strips of light: switch on clock wise // When all lights are on, switch them off clock wise // Horizontal for ( byte x = 0; x < 4; x++ ) { // Vertical for ( byte y = 0; y < 4; y++ ) { setLed( x, y ); } delay( 100 ); } // Horizontal for ( byte x = 0; x < 4; x++ ) { // Vertical for ( byte y = 0; y < 4; y++ ) { clearLed( x, y ); } delay( 100 ); } } void verticalBlink() { // In four steps, light a ring from bottom to top // When all lights are on, switch them off bottom to top // Vertical for ( byte y = 0; y < 4; y++ ) { // Horizontal for ( byte x = 0; x < 4; x++ ) { setLed( x, y ); } delay( 100 ); } // Vertical for ( byte y = 0; y < 4; y++ ) { // Horizontal for ( byte x = 0; x < 4; x++ ) { //setLed( x, y ); clearLed( x, y ); } delay( 100 ); } } void randomBlink() { // Pick a random row and column, a random state, // and apply that state to the indexed led // This is somewhat similar as the original tree had byte x = random( 4 ); byte y = random( 4 ); if ( random( 2 ) ) setLed( x, y ); else clearLed( x, y ); delay( 100 ); } void setLed( byte _x, byte _y ) { // This function does the led magic: it deduces the bit and port index from the mapping number // like this: xxxppbbb, there the lowest 3 bits are values 0-7, indicating the bit we're after // and the two bits after that determine the port // Yes, I could use the arduino port index, but this is faster // Fetch the mapping index for the given coordinate byte mappedPort = g_mappedTree[ _y ][ _x ]; // Determine the bit index (lower three bits) byte shiftBit = mappedPort & 7; // Find which port it is (shift out the lower three bits and get the index) // And set the given bit switch ( mappedPort >> 3 ) { case 0: PORTB |= (1 << shiftBit); break; case 1: PORTE |= (1 << shiftBit); break; case 2: PORTG |= (1 << shiftBit); break; case 3: PORTH |= (1 << shiftBit); break; } } void clearLed( byte _x, byte _y ) { // Same as setLed, except for the port bit banging // Yes, these functions can be combined, but the whole program was a quick hack // Fetch the mapping index for the given coordinate byte mappedPort = g_mappedTree[ _y ][ _x ]; // Determine the bit index (lower three bits) byte shiftBit = mappedPort & 7; // Find which port it is (shift out the lower three bits and get the index) // And clear the given bit switch ( mappedPort >> 3 ) { case 0: PORTB &= ~(1 << shiftBit); break; case 1: PORTE &= ~(1 << shiftBit); break; case 2: PORTG &= ~(1 << shiftBit); break; case 3: PORTH &= ~(1 << shiftBit); break; } }