LED christmas tree
Project: LED christmas tree | |
---|---|
Featured: | |
State | Active |
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!
I had to leave in a hurry, but hey, it's a wiki; anyone can put a goatse tree up here.
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; } }