Introduction: PCB Christmas Tree

Picture of PCB Christmas Tree

So I spent a lot of time here on Instructables looking at all the cool stuff, but I couldn't decide on what to build. Last Christmas I saw a really cool PCB Christmas tree at a friends place, and I decided to make one (or a few) for this year, and share it here to give something back to the community. In the end I made 10, and they made great gifts for the family!

I started Googling a bit to see if I find something similar, but in the end I only found 2D variants, and I wanted to have a real tree, that can stand on it's own, made from multiple PCB-s connected by right-angled pin headers. Funnily enough, after I was finished with my designs, I found a blogpost on the original tree I saw last year. Make sure to check it out as well, and also the previous version of the same tree, if you don't want to do so much SMD soldering.

So here are the functions I wanted to have on the tree:

  1. should be able to stand by itself
  2. should have a lot of LEDs, ideally multiple colors showing different patterns
  3. should be portable and wireless - operate on battery
  4. some kind of user interaction desired - touch sensitive button
  5. hard switch to power on/off

Since I already have an Arduino, and I felt pretty comfortable with it, I decided to use it to control the LEDs. However a full Arduino is way too bulky for such a thing (also too expensive), so I decided to try my luck with something more integrated: a standalone ATMega328P chip directly soldered on the Christmas tree. Although it's probably doable with the standard DIP version of the chip, I opted for the SMD version, the ATMega328P-AU. I had 3 reasons: it's much smaller, easier to place it on the PCB; no pointy legs; plus I also wanted to learn SMD soldering, so this seemed like a good excuse. Because of this, I also selected mostly SMD components, except for the pin headers which in this case will also serve for mechanical support, so I thought the through-hole would be better here.

Step 1: Necessary Tools, Skills, and Components Used

Picture of Necessary Tools, Skills, and Components Used

This is what you'll need:

Necessary tools:

  • Arduino (or any other device capable of programming an ATmega328)
  • soldering iron (preferably with temperature control)
  • fine solder (not bigger than 0.5mm in diameter)
  • flux pen
  • multimeter
  • fine tweezers
  • pliers
  • sandpaper

Optional (but handy) tools:

  • Scotch tape
  • fume extractor
  • anti-static mat

Components for the tree:

  • Custom design tree-shaped PCB; see further steps
  • ATmega328P-AU
  • 1× TI TPS-61070 DC/DC booster IC
  • 12× dual color SMD side LED (KPBA-3010SURKCGKC)
  • pin headers:
    • 2 1×9 female
    • 2 1×9 right-angled male
  • DIP switch (DS-01)
  • 4× AAA battery clips
  • 3× P-type MOSFET SOT23 package (IRLML9303TRPBF)
  • 0805 smd resistors:
    • 4× 68 Ω (for red LEDs)
    • 4× 62 Ω (for green LEDs)
    • 2× 10 kΩ
    • 1× 180 kΩ
    • 1× 1 MΩ
  • 0805 smd capacitors:
    • 2× 0.1µF
    • 2× 4.7 µF
    • 1× 10 µF
  • smd inductor:
    • 1× 4.7 µH (L-USWE-TPC)

Well, now looking at it all written down, it sure seems like a lot of things, but its managable. Lets get going!

Step 2: Circuit Design 1: LED Multiplexing

Picture of Circuit Design 1: LED Multiplexing

I wanted to have 12 dual color LEDs, which means controlling 24 digital lines. Individually addressing these is not possible with the Arduino, since it only has 14 digital lines. Because of this, multiplexing is necessary. This is a technique where the LEDs are wired up in a rectangular grid, and they can be addressed basically with the 2 coordinates on the grid. For more information on how multiplexing works, check out these instructables:

amandaghassaei: Multiplexing with Arduino and the 74HC595

perez1028: Multiplexing with Arduino - Transistors

For the grid I choose 3x8 (see schematics on image), which means instead of 24, only 3+8=11 pins are needed to control all the LEDs, so this should work without a problem.

I also added current limiting resistors at the end of each column. This is sufficient, because only one row at a time will be active, so at any time only one LED will light up from each column. Since the green and red LEDs need different voltages (see data sheet) to reach the 20 mA current, these resistors are also slightly different for the red and green columns: 62 Ω for the green, and 68 Ω for the red.

One more thing to consider is the current sinking and sourcing capabilities of the ATmega (Arduino). There is no problem on the C1..8 pins, because these need to sink maximum 20 mA of current, and this should work without any worries. The pins selecting the rows however, should be able to source up to 8×20 mA = 160 mA, which is well above the 20 mA limit. For this reason, I added some P-MOSFETs between the pins and the LEDs to act as a switch. When the gate of the MOSFET is pulled low, it activates the switch, and current can flow to the LEDs. A very nice explanation on how to use MOSFETs as a switch can be found here.

Step 3: Prototype on Breadboard + Test Program

Picture of Prototype on Breadboard + Test Program

Of course I wanted to know if this is all feasible, so I had to test a few things. First, programming the ATmega without the clock; and second, testing the 3x8 LED multiplexing.

To start, I checked the guide on the Arduino website on how to program a standalone ATmega which is quite comprehensive, and works most of the time. There are 2 main steps: using an Arduino as a programmer burn the bootloader, and then upload the program. There is a catch, however, that is if you have an ATmega chip that was already configured to use an external clock (e.g. taken out of an Arduino), then the only way to program this chip is to provide an external clock signal on XTAL1. Even if you want to configure the chip to use the internal clock later, this is a necessary step before you can do anything. So there are two options: connect an crystal to the ATmega; or if you don't have a crystal, you can also use the ArduinoISP2 program by Adafruit which will actually generate a clock signal on pin 9. In the end I chose this option, because I didn't have a spare crystal I could use. After configuring the chip to use the internal clock, it can be programmed without needing an external crystal, because burning the bootloader also sets the appropriate fuses.

After the bootloading worked, I built a small prototype on breadboard with only 12 LEDs, just to see how the multiplexing would work. First I tried it by using the digitalWrite() function, but it turned out to be too slow, so I had to change it and set the pin registers directly. This is a bit more cumbersome, but fortunately it's very well documented on the Arduino website.

First, some global variables should be defined:

const int NR_ANODE = 3;
const int NR_CATHODE = 4;

// pin choice only depends on how the LEDs are wired up to the controller
const int anodePins[NR_ANODE] = { 3, 4, 5 };           // Arduino pins 3, 4, 5
const int cathodePins[NR_CATHODE] = { 7, 6, 1, 0 };    // Arduino pins 7, 6, 1, 0

// pins 3 4 5
const int anodeBits = B00111000;
// pins 6 7 0 1
const int cathodeBits = B11000011;

unsigned long int loopCounter = 0;

And an array to store the LED brightness values:

int val[NR_ANODE][NR_CATHODE] = { { 0, 0, 0, 0 },
                                  { 0, 0, 0, 0 },
                                  { 0, 0, 0, 0 } };

Then in the main loop, the loopCounter is incremented at every iteration, and its remainder by 50 is compared to each element of the value array, which will determine if the LED is on or off for that iteration. I chose 50, because it still worked without any flickering, and already gave a fine enough resolution for what I needed.

rem = loopCounter % 50;
i = loopCounter % NR_ANODE;    // at every iteration use a different anode
// turn cathode pins high, this will turn off all LEDs
PORTD = PORTD | cathodeBits;
// turn anode pins low
PORTD = PORTD & ~anodeBits;
// turn anode_pins[i] high - select row i
PORTD = PORTD | (1 << (3+i));
// turn cathode pins low if rem >= corresponding val
PORTD = PORTD & ~(( (rem < val[i][0]) << cathodePins[0]) |
                  ( (rem < val[i][1]) << cathodePins[1]) |
                  ( (rem < val[i][2]) << cathodePins[2]) |
                  ( (rem < val[i][3]) << cathodePins[3]) );

At this point I just tried the program by writing fixed values in the val array to see if it works without any issue, and when I was happy with it I started the PCB design, because I knew manufacturing would take some time and I could finish the rest of the program then.

Step 4: Circuit Design 2: Power Supply

Picture of Circuit Design 2: Power Supply

Before jumping in to board layout design, I still had to consider the power supply.

Although using 2 AAA batteries in series seems straightforward because they give 3 V, this is only true when the batteries are brand new, and when they get older, the voltage will drop all the way to 1.6 V. See the attached graphs on battery voltage vs time for constant current and constant power applications. Both curves are very similar, and they show a rapid voltage drop at the beginning and the end of the battery life, with a longer, mostly constant region in the middle. Graphs are taken from the Energizer E92 AAA battery data sheet.

So basically the voltage from a battery can vary between 1.6 V and 0.8 V, and is nowhere near constant 1.5 V. Since I didn't want any change in the LED brightness because of the dropping battery voltage, plus probably the ATmega chip is also happier with a constant voltage supply, I had to use a DC/DC boost converter that can provide a 3.3 V output. To choose an appropriate one, I had to consider the following things:

  • input voltage is between 3.2 V and 1.6 V
  • output voltage is constant 3.3 V
  • maximum necessary output current is ...

So what is maximum current the components can draw? Lets check the datasheet for the LEDs, and for the ATmega328P. If turns out that the LEDs draw maximum 20 mA each, and the ATmega at 3.3 V and 8 MHz, well it's not explicitly there, but there is a graph that shows supply current vs operating frequency and input voltage. From this at 3.3 V and 8 MHz clock the ATmega would need maximum 4 mA (very rough estimate). We also have a 10k pullup resistor, which will also draw 3.3/10000 = 0.33 mA .

So all in all we can estimate a maximum current draw of 24×20 + 4 + 0.33 + s (some extra from gut feeling just to be safe) = 484.33 mA + s ≈ 550 mA. Which seems really quite a lot, and I had a hard time finding a DC/DC converter that could actually do this. Then I was thinking a bit more, and realized, that because of the multiplexing, actually only 1/3 of the LEDs are on at any time. So actually it's only 8×20 + 4 + 0.33 + s = 164.33 + s ≈ 200 mA.

So this is a bit more realistic now, and I managed to find a converter that fits these requirements, and I could also buy it from where I ordered the other parts: TI TPS61070

I decided on this based on 2 parametes: maximum output current, and efficiency for 3.3 V output when input is between 1.6 V and 3.2 V. See the corresponding graphs in the attached figures.

For a more thorough explanation by an expert on battery capacity see Episode #140, and on choosing the appropriate DC/DC booster see Episode #139 of EEVblog, I highly recommend them.

Step 5: Circuit Design 3: Capacitive Touch

For the user interaction I wanted to use a capacitive touch button, which I find very cool. This can be directly made from the PCB itself by having a larger copper are acting as one plate of a capacitor. This capacity is then "somehow" measured by the micro-controller to determine if it was touched or not. I found a very nice explanation behind the principle in an application note by Texas Instruments.

Fortunately, for the Arduino a few different libraries are already available that implement touch sensing based on this principle. The one that I used in the end is AnalogTouch 1.0.0 by NicoHood, which is based on the ADCTouch library on the Arduino Playground. They both only use 1 pin, which is very convenient, and exploit quite a lot of the inner workings of the ATmega. How it works is very well explained and illustrated by Thomas Nylund. The only extra compontent (actually optional) is a 10k resistor between the sensing pad and the chip to avoid ESD damage. It basically just limits the current flowing to the chip in case an electrostatic discharge happens when someone touches sensor pad.

Step 6: Circuit Design 4: Final Touches

Picture of Circuit Design 4: Final Touches

Finally, we can integrate everything together into a single schematic. The main parts again: ATmega328P microcontroller, grid of LEDs, and power supply circuitry. So far I only discussed the LEDs, so I'll quickly try and explain the rest.

To place the necessary resistors and capacitors for the ATmega, I looked at the schematics of the Arduino Nano, since it also uses the same chip. I ended up only using 3 components for this: 1 pullup resistor on the RESET pin, and 2 decoupling capacitors for power and analog reference.

For the power supply circuit fortunately everything is well explained with examples in the data sheet of the TPS61070. I was lucky enough that one of the examples was exactly matching my application, with an output voltage of 3.3 V, so I could just take it as it is. This chip also has an evaluation module, and I even found the board layout in its data sheet, so I could use that as a reference when designing my own layout.

So now the LEDs are hooked up, we have power and also a touch sensor. But, one important thing not to forget is, how to upload the program to the microcontorller? Fortunately the board already has some pin headers to connect the 3 parts, so I used these to double as a programming interface. Both headers have connections to power, ground and reset; I wired TX and RX to one header; and MISO, MOSI, and SCK to the other. Although usually it's not recommended to use the TX/RX pins of the Arduino (ATmega) for any other kind of I/O, this is only true if one wants to use them for serial communication as well. Since I didn't want to do that, I had no problem using them to control the LEDs.

Step 7: Board Layout

Picture of Board Layout

To design the board I used the free version of Eagle 7.4.0, which you can download from here. I really like this software, because it comes with a huge library of components, and since it's very popular, it's easy to find tutorials and extra libraries for it. If you'd like to learn it, I recommend the 3 part video tutorial by Jeremy Blum:

For extra parts I also downloaded the libraries by Adafruit and Sparkfun. These have a lot of common components in them that are not in the default Eagle library (such as the ATmega328P-AU itself). Unfortunately I still couldn't find anything for the battery clips, and for the LEDs, which are really quite important, so I ended up making a small library for this project with only these two components. I also made another part which is just a huge arrow with a letter inside to use as a guide for assembly, because I put the touch sensor on one of the side boards, and I didn't want to mix them up.

For the board layout I had a few constraints. Obviously the whole thing had to look like a Christmas tree in the end, so I started with a few milling paths to separate the board into 3 part. I left a some tabs to keep them together, and added some holes along the line where it has to break. Then, I placed the LEDs on the edges, followed by the pin headers.

The batteries also gave me a bit of a headache, because they need a lot of space. Originally I wanted them horizontally on the bottom, with the side boards cut out, but I couldn't put them on top of each other, because I only found through a hole version. In the end I put them vertically next to the side boards on opposite sides of the main board (just because I like symmetry...).

Finally I placed all the other components in a way that would more or less minimize the distances. For the power supply, as I already mentioned, I just copied the layout from the evaluation board.

I also modified the layout of a few components to make hand soldering easier: I made the pads tor the ATmega and the TPS61070 much longer, and also increased the pad size for the LEDs. This really helped at the assembly. I also moved away all components from the ATmega, so soldering would be easier. Since it's recommended to have the capacitors very close to the chip, I place them on the other side of the board, directly below the chip.

As a finishing touch I also drew some snow on the silkscreen layer, so it would look more like a real tree.

Step 8: Assembly

Picture of Assembly

After I finished with the design, I ordered the boards (10) from Actually I used the beta version of their new website, I think it ended up to be a bit cheaper when ordering from there. The main reason for choosing them is because for this 3-part design many PCB manufacturing companies charge extra, as they consider this to be panelizing. At DirtyPCBs, however, they don't care, actually they even encourage incorporating multiple designs in a single panel.

Fortunately assembly was pretty straightforward. I just had to pay attention not to mix up (or loose) the tiny components. Just break the PCB in 3 parts, break off the small tabs with pliers, and smoothen the edges with sandpaper. I started the soldering with the ATmega, since this is the most difficult to solder. If you never did surface mount soldering, or indeed any kind of soldering, just watch these videos from EEVblog, and you'll be an expert in 2 hours:

I haven't actually soldered any surface mount components before this project, so just to be sure I took and old LED controller board and practiced a bit on it. It had some 0805 resistors and two SO-8 ICs, so it was relatively close, although not as difficult as the TQFP package of the ATmega. But with the right tools and with a lot of flux, it's actually not that hard. Just watch the videos, it's really worth it.

One more tip: use a lot of Scotch tape. It's really handy to temporarily fix the headers before soldering, and also to glue the tapes to the desk, so the tiny surface mount parts don't fly all over the place.

Step 9: Programming

Picture of Programming

So the final step is to finish the program, and upload it on the assembled tree. The program has 4 main parts: initialization, interrupt for the touch button, main loop to blink the LEDs, and a lot of smaller functions to calculate the different patterns for the tree. I have some comments in the code that explains it a bit how it works.

I set an interrupt using the TimerOne library that will check every 0.1 s if the sensor is touched. If it is, it will change the pattern, or wake the tree up, if it was in standby. If no touch event is recorder for 10 s, if will automatically change the pattern randomly. If no touch event happens for 3 mins, it will go back to standby. The program also checks for holding the sensor for 3 seconds, when that happens, the tree will go to furious random blinking.

To upload the program, first you have to burn the bootloader on the ATmega chip, which will also configure it to use the 8 MHz internal clock. This can be done by using an Arduino, as I already mentioned in Step 4. To do this, follow the instructions on the Arduino website for the "Minimal Circuit". This basically involves downloading the hardware configuration file and hooking up the ATmega to the Arduino.

Before you can proceed with the programming, however, the Arduino itself needs to have the Arduino as ISP program uploaded to it, because this will be used to send the program over to the Christmas tree. After this is done, connect the 3.3 V and GND of the Arduino to the 3.3 V and GND of the tree. Then, connect Arduino pin 10 to RESET, pin 11 to MOSI, pin 12 to MISO and pin 13 to SCK. If you have an Arduino Uno, also connect a 10 µF capacitor between RESET and GND pins of the Arduino, so it wont actually reset itself.

After you have the Arduino as ISP uploaded, and all the connections, change the programmer in the Arduino IDE to Arduino as ISP, and the target board to ATmega328 on breadboard (8 MHz internal clock). Now, you can burn the bootloader. After this is done, open the pcb_xmas_tree.ino in the Arduino IDE, and select Upload using programmer. This will take a few seconds, but you'll know it's ready if the LED next to the touch sensor starts blinking slowly.

Step 10: TL;DR

So in the end it all worked out, I learned a lot during the design process, and managed to make some nice gifts for my friends and family.

Here is a quick recap on the most important parts:

  1. Download eagle / gerber files, and order a few boards, or etch your own
  2. Order components (bill of materials inside the eagle file)
  3. Assemble
  4. Download necessary libraries: AnalogTouch, TimerOne
  5. Download program (pcb_xmas_tree.ino)
  6. Using an Ardunio as ISP burn bootloader on the tree, then upload the program
  7. Done!

Thanks for reading, I hope you liked my first instructable!


therazor253 (author)2016-11-17

Very nice project. I also want to make some of this, but can you tell, or send a screenshot of with all the settings that you need to set to make pcb exactly like yours? And what file to attach?

bluqesh (author)therazor2532016-11-18

I'm glad you like it. You should upload the file. For the order you'll need to set the following options: size: max 10x10cm, thickness: 1.6mm, and color: green of course. See the attached screenshot. After you add it to the cart (might require registering), it should generate a preview, so you can double check if everything is correct before placing the order. Let me know how it turned out!

therazor253 (author)bluqesh2016-11-18

One more thing, is it possible to change text to mine, translate it to be precise, in an easy way? I've downloaded eagle, I think I can change it, but I don't know how to export it to these gerbers files. Can you help me with this?

I'd like to change yours "Boldog Karácsonyt!" to "Wesołych świąt!" and text on the button to "Naciśnij tutaj". I would be very grateful if you would help me with this :)

bluqesh (author)therazor2532016-11-18

To generate the gerber files yourself I recommend downloading the CAM file from the dirtyPCB website: (Exporting Gerbers from Cadsoft Eagle)

You can read the detailed instructions here:

If you anyways do some modifications I recommend moving the LEDs a bit closer to the edge (like by 0.5 mm), so they will be better visible from the other side of the board as well. I wasn't sure about the manufacturing precision, that's why I had more space to the edge, but it all turned out perfectly.

therazor253 (author)bluqesh2016-11-18

Thanks for your answer. I'll give it a try.

fulda (author)2016-01-14

It is very interesting way how are you working with PCB. Very "clean" work.

BTW - you can have two enhances:

1 - add serial port + arduino boot loader to be cool in those days

2 - use charlieplexing to have more leds see: (8 pins = 56 leds) :)

But in principle it is very good project with excellent result.

bluqesh (author)fulda2016-01-14

Well, not everything is as nice as it seems :) I only organized everything so neatly because of the photo.

Thanks your suggestions, maybe I'll try charlieplexing for my next project. As for the serial port, I actually connected them as well, but to the other header, so it might not be visible on the photos. In the end I didn't use them for programming, because somehow it didn't work for all of the trees, and the ISP programmer didn't have this issue.

ossum (author)2016-01-11

The end result is fantastic, and you explained the whole design process really well. This is a brilliant mid-level "introduction to electronics" kind of project, because it is interesting, covers all sorts of design aspects/choices and still provides you with something cool you will actually use at the end. (Voted)X3

bluqesh (author)ossum2016-01-12

Thanks a lot for the feedback, I really appreciate it! Just for this single comment, it was already worthwhile to write this all down :)

Just4Fun Media (author)2016-01-11

Those look awesome!

bluqesh (author)Just4Fun Media2016-01-12

Thanks, I'm glad you liked it!

About This Instructable




More by bluqesh:PCB Christmas tree
Add instructable to: