Building a Christmas Tree (Part 3)

light christmas DIY

Christmas is near. It's time to finish our LED Christmas tree project and add the electronics.

Let There Be Light

In the previous part of our LED Christmas tree project we built the wooden tree. While the tree is quite nice on its own, we want to have fun with electronics, on this blog. This means it's time to add them. In this final part of our project, I will guide you step-by-step through this process and explain the Arduino program, we will use for our tree. Let's go!

Building the Circuit

We need eight LEDs for our Christmas Tree and if we would connect them directly to our Arduino we would need to route a lot of wires out of the tree stand. A common solution for solving such an issue is using a shift register like the 74HC595. The circuit we are building is so common that it is even listed as an example circuit in some 74HC595 datasheets. The shift register itself is available from many manufactures, like many other standard logic ICs.

The shift register has 8 output pins Q0 - Q7. To control these outputs, eight bits of data need to be written into the shift register. A shift register consist of a bunch of flip-flops that are chained together (in this case eight of them.). The input for the first flip-flop input is connected to pin DS where the data bit to write can be signaled. This bit is transferred into the register when the clock pin ST_CP transitions from LOW to HIGH. After that the flip-flop one contains the bit inputted on DS, flip-flop two now contains the bit that was previously stored in flip-flop one and so on. On each LOW to HIGH transition the data is shifted one bit further into the shift register. Data shifted out of flip-flop eight is discarded, if you only use one shift register. To support more LEDs multiple shift registers can be chained together. The shift register has an additional output Q7' for this that can be connected to the DS pin of the next shift register. The 74HC595 has an additional output buffer for each output. If the SH_CP pin transitions from LOW to HIGH the output from the flip-flops is transferred into the output buffer. This allows us to write new data into the shift register without immediately changing the output. The 74HC595 also has an active-low master reset input (MR) to reset the flip-flop contents. We don't need that and can thus connect this pin to VCC. The only remaining pin is the output enable pin (OE). If we connect it to ground the shift registers outputs are enabled. If OE is HIGH all outputs are disabled even if the output buffer contains a one.

In the circuit shown below you can see that I added a 360 Ω in series resistor for each LEDs. This limits the current per LED. The LEDs reach their maximum intensity at 20 mA. However, the shift registers outputs can only handle 70 mA in total and 35 mA per output. This is why I chose to use such a high resistance value. It guarantees that the shift register is not damaged even when all eight LEDs are on simultaneously.

Christmas Tree Circuit

So much for the basics. Let's start building the circuit step-by-step.

Programming the Arduino

The tree is finished and the electronics are in place. It's now time to connect the tree to the Arduino and write a program for it.

I used the following pins for this project:

  • The OE input, that enables the shift registers output on a LOW voltage level, is connected to pin 9
  • The ST_CP input, that is the clock used to read in the next data bit, is connected to pin 2
  • The DS input, that is used to send the data bits to the shift register, is connected to pin 3
  • The SH_CP input, that moves the data from the flip-flops into the output buffer once all bits have been set, is connected to pin 4

All pins need to be initialized as output in the setup procedure. For the sparkling effect I chose to randomly enable LEDs. For this we can use Arduino's random function. For that, we need to initialize the pseudo-random number generator in the setup procedure.
We can do this like this:

randomSeed(analogRead(0));

What this line does is, it reads the analog value from the floating pin A0. The value that is read is undefined and can be used as our initial randomness source. We need this so that the pseudo random number generator does not produce the same patterns every time we turn on the Arduino.

With that done we need to think about the code that we execute in the loop procedure. With random(255) we can generate 8 random bits where a one means that the corresponding LED is turned on. This allows us to enable a random set of LEDs.

To send this data to the shift register Arduino provides a function called shiftOut(dataPin, clockPin, bitOrder, value). The data can be sent beginning with bit 0 (LSBFIRST) or with bit 7 (MSBFIRST). In our case this does not matter as we send a random byte as value anyway. The remaining two arguments are the number of the data pin and the clock pin. Once data is written into the shift register it has to be manually transferred into the output buffer by toggling pin 4.

To make the animation look a lot nicer we can use PWM at the output enable pin connected to pin 9 to fade the LEDs. The complete procedure consists of selecting a random set of LEDs, slowly increasing the brightness, then reducing the brightness again to finally select a new random set of LEDs in the next iteration. As the LED Christmas tree will be primarily used in the darkness, I don't wanted to use the full LED brightness. I fade between 0 and 150. A delay ensures that the fading is nice and slow. A call to analogWrite outputs a PWM signal according to the current brightness value. If you want to learn more about PWM you can have a look at this tutorial.

If we put everything together, we finally end up with the following code:

const int clockPin = 2; // ST_CP
const int dataPin = 3; // DS
const int latchPin = 4; // SH_CP
const int oePin = 9; // OE

void setup() {
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(oePin, OUTPUT);
  randomSeed(analogRead(0));
}

void loop() {
  // Enable random LEDs
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, random(255));
  digitalWrite(latchPin, HIGH);

  // Do fade animation
  for(int i = 0; i < 150; i++) {
    analogWrite(9, 255-i);
    delay(50);  
  }

  for(int i = 150; i >= 0; i--) {
    analogWrite(oePin, 255-i);
    delay(50);  
  }
}

The Result

Once the Arduino is programmed our Christmas tree starts to light up. You can watch it sparkle in the video below. While the project itself is done at this stage you can further experiment with the code and create your own animation. Remember, the OE input connected to pin 9 lets you control all LEDs at once. If you set pin 9 to HIGH all LEDs are turned off. The individual LEDs can be enabled by writing a one to the corresponding bit in the shift register. Have fun!

I wish you a merry Christmas and a happy new year! God bless you.

Previous Post Next Post