Difference between revisions of "LED christmas tree"
(created christmas tree light) |
(No difference)
|
Revision as of 01:58, 21 December 2013
| 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;
}
}
