Introduction: Arduino Controlled Message in a Christmas Tree
Guests encounter a 3-foot Christmas tree decorated in colored lights. Green letters are scrawled one at a time to form a message. The words arrive slowly:
Ho Ho Ho The Mad Wrapper says hang your ornament here
Under the tree lay identically wrapped packages. The only thing unique about each is hidden within some electronics built into the ornament taped to it. When one of these ornaments is hung on a hook on the lighted tree the colors change and a new message begins. This one spells out a person’s name thus revealing the inheritor of the gift.
Eric
As you will see, this project involved quite a few steps and many hours of work. If you like this instructable I'd love to have your vote in the contests I am entering. Icing on the cake: I'd love to win one of those.
Thanks!
Step 1: Summary Behind the Scenes
A single strand of 200 individually selectable RGB LEDs surrounds the tree. One hundred are densely packed at the front of the tree providing a nice region to show a message. The other 100 LEDs are scattered around and used as background decoration. LED colors are controlled by an Arduino Uno microcomputer using the popular WS2811 library.
A hook is mounted above a RFID-RC522 IDUINO RFID reader which is wired to the Arduino using SPI connection. Ornaments found on each gift are actually RFID tags on key rings, each with a unique electronic code built into it. So, when someone hangs an ornament on the hook it comes into contact with the RFID reader allowing the Arduino to read the unique identifier. By matching a person to an RFID number, the Sketch program will write the name in lights.
This project was inspired by the great Instructable Arduino Controlled Positional RGB LED Christmas Tree by Osprey22. My Sketch program originated from the program posted there. I especially appreciate the calibration design from that project. I also use some of that functionality for subtle background effects as I print my messages.
The Sketch I ran on one of my trees is attached. Please download it and customize it however you need.
Note: I actually created two of these trees. One was mailed across the country to remote family members before Christmas. The other stayed home. If you notice inconsistencies between videos and images this may be due to filming of different trees.
Attachments
Step 2: Equipment List
You will need the following items to build a tree like mine:
- 3ft artificial Christmas tree
- Make sure the base is heavy or otherwise provides a solid foundation. Because LEDs will not be distributed evenly a poor base will make a tippy tree.
- Make sure the tree is fairly dense with branches. We need to solidly connect a lot of LEDs to it so the more branches available the better.
- Arduino Uno or any version of Arduino computer.
- Power supply:
- Generic option: I used an external power supply: 5 volts, 8 amps. This is plenty powerful enough to run the LEDs at full (blinding) brightness. But this is extreme overkill for normal use. In the early stages of development I was running the LEDs at full power so this external supply was required. If I had planned to run this outside for all the neighbors to see, I might consider running it at full brightness.
- Better option: You do not need any external supply if you dim the LEDs down to an eye-pleasing 8% power, which is what the attached Sketch program does. If this is the case, simply attach the Arduino USB port to your computer or to a 1 amp (or bigger) USB wall charger.
- 5.5x2.1mm Female DC power connector or connector. (Note: this is optional if you are not using an external power supply)
- Four strands of 50PCS WS2811 RGB Full Color 12mm Pixels digital Addressable LED String DC 5v
- Arduino case
- Right Angle Female Header
- 100 ft 22 gauge solid black wire
- 20ft 22 gauge red wire.
- Arduino Compatible MFRC522 RFID Reader
- 10PCS RFID 13.56MHZ Proximity ID Token Key Tag Keyfob Chain. (2 bags gives you 20 names).
- A dozen red Quick Splice Crimp Terminals Connectors suitable for 22 gauge wire.
- 2 orange wire nuts.
- Crimping tool.
Step 3: Test LEDs First
Before you start, before hanging the lights on the tree, test them all to verify that they all work. This is easily done by setting the attached Sketch program into test mode by defining LED_TEST
#define LED_TEST
This mode cycles through a simple pattern to verify that the LEDs are working. It does this:
- set all LEDs to red
- set all LEDs to green
- set all LEDs to blue
- then one at a time to purple
If nothing lights up:
- Verify that the correct end of the strand is wired to the Arduino. I have discovered that some brands of WS2811 require the female end of the connector be wired to the Arduino. Other brands require the male end to be connected to it.
- Verify that the data line is connected to the correct Arduino pin. (Pin D6 for the attached code.)
- Verify that “+” is attached to +5v on the power supply.
- Verify that ground is connected both the Arduino ground and the power supply ground.
If the tree briefly flashes bright white and other bright crazy colors you probably have a loose connection to the power supply.
- Verify that the cord leading from the wall to the power supply is solidly pushed in.
- Make sure the round connector at the 5 volt side of the power supply is fully plugged in.
- Recheck all the +5 and ground wires to make sure they make a solid connection to the supply.
If the colors are wrong your strand may be designed to use the reverse GRB order not RGB order. Try changing this line to use NEO_GRB as follows:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ400);
Step 4: String the Lights
Wire all the lights on the tree. Start by wiring the first 100 LEDs tightly together in one region. Then wire the rest of the lights evenly around the rest of the tree.
Before starting the mapping procedure described in the next section make sure all LEDs are tightly wired to the tree so they move very little or at least bounce back to their home position if they are moved.
At each end of all four LED strands you will find the following:
- A two-pin connector for signal and ground
- Connect the signal wire of the first strand directly to Arduino pin 6. This wire can be identified by closely inspecting the connection at one of the LEDs. It is usually (maybe always) the middle wire and is probably labeled data on the miniature circuit board of each LED.
- Connect the other wire of the first strand to the ground pin on the Arduino.
- For each strand of 50 lights, connect the male from one strand to the female of the next to form a long chain
- A red wire (+5)
- Using lengths of red wire, connect all of these wires directly to the +5 terminal of the power supply. If you do not connect all of these directly, the last strand of LEDs may become dim or discolored because it is not receiving enough power to illuminate it properly.
- A ground wire usually black or blue.
- Using lengths of black wire, connect all of these wires directly to the ground terminal of the power supply. If you do not connect all of these directly, the last strand of LEDs may become dim or discolored because it is not receiving enough power to illuminate it properly.
I used crimp connectors to connect most of my wires together. And I used electricians wire nuts to connect the power supply to the many ground wires and +5 wires that all come together at the base of the tree. If you choose to solder instead, be careful not to set your tree on fire!
Note that different brands of WS2811 RGB will orient their connectors differently. Some brands put the male connector at the beginning of the chain. Other brands put the female connector of the chain.
If possible, attach the power supply and Arduino at the back of the tree. Do this to provide some counter-balance to offset the weight of the 100 densely packed LEDs at the front of the tree. After it is completely wired, verify that your tree does not topple over when placed on a soft surface such as a rug or carpeting.
Step 5: Map the Pixels
After everything is wired tightly, define CALIBRATE in the Sketch program.
#define CALIBRATE
This mode flashes every light on the strand in sequence as follows:
- One at a time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- Flash these all on at the same time once: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
- One at a time: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
- Flash these all on at the same time twice: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
- One at a time: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
- Flash these all on at the same time three times: 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
- One at a time: 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
- Etc.
- When the LED number is greater than 100, the group will flash once in green (representing 100's digit) then flash up to nine times (representing the 10's digit as described above).
Step 6: Film the Calibration
Create a video of the tree while in calibrate mode described above. A 200 LED string of lights results in a 5 minute video that can be imported into iMovie or another movie editing software on your Mac or Windows computer. You will also need to import a grid of white lines into the movie editor. This grid is overlaid on top of the movie of the light sequence to help define X,Y coordinates for each LED.
Play back the movie, pausing and resuming as you go, and write down the coordinates of every light to the nearest half pixel. I chose to write the whole number if the light filled the middle of a grid square. And I added 0.5 if the light fell on a grid line. Once all the coordinates have been recorded, type them into the Arduino Sketch filling the array LEDPositions with valid numbers. The numbers entered into the array are actually the coordinates multiplied by 10. So every number ends in either 0 or 5. (Note: I defined “B” as “0,0” so I had something to assign to the LEDs that were hidden in back of the tree when I filmed it.)
For example:
const PROGMEM uint16_t LEDPositions[] = { // 0 1 2 3 4 5 6 7 8 9 B, B, 190,400, 180,420, 175,410, 170,420, 160,430, 140,400, 135,410,120,410, // 0 - 9110,400, 110,390, 130,400, 150,400, 150,420, 160,410, 170,405, 180,410, 190,410, 190,395, // 10 - 19 195,390, 170,390, 160,405, 155,405, 150,390, 140,390, 125,395, 145,395, 160,390, 170,400, // 20 - 29 180,390, 185,375, B, 190,360, 190,370, 180,385, 180,380, 170,385, B, 190,395, // 30 - 39 190,370, 140,370, 160,375, 150,380, 140,390, 130,390, 125,385, 115,385, 120,375, 130,380, // 40 - 49 …
Step 7: Generate an Image of a White Grid
I have attached the png image of the grid I used. You can download this or generate your own grid. I used both Microsoft Excel and Adobe Photoshop to accomplish this. I found that a grid 30 wide by 50 tall on an 8.5x11 inch sheet was good for my project. This is how I did it:
Create a new spreadsheet using Excel
- Number the rows from 0 to 50 down the left column.
- Number the columns from 0 to 30 along the top row.
- Show the grid lines.
- Resize the columns so they are all equal width and fit on one page. I found that 0.22 inches worked well.
- Resize the entire sheet so it fits on one page.
- Select the entire grid from 0,0 to 30,50
- Copy
Open Adobe Photoshop
- Create a new image that is sized 8.5x11 inches.
- Paste everything that was copied from Excel.
- You should now have a black numbered grid on an invisible background. Before exporting, we need convert the black image to white.
- Zoom in so any piece of the image is large enough to click on.
- Select the paint can.
- Make sure “continuous” is not selected.
- Set the foreground color to white.
- Click on any black part of the image. This should convert all black on the image to become white.
- Save for web to create a .png image.
Step 8: Make a Movie to Map the Coordinates
These instructions describe how to use iMovie to generate a video useful for mapping the coordinates of each LED.
Overlay the white grid into iMovie
- Import the previously created grid image into iMovie.
- Add it to the movie by dragging it above the video of the tree in calibration mode.
- Drag an edge so it spans the entire 5-minute movie from start to finish.
- Set cropping to “Fit”. (Not “Ken Burns”.)
- So both the grid and the tree video show, set opacity to something less than full. I found that around 50% was good for my image.
- Generate the movie.
Record X,Y positions of all LEDs onto a piece of paper.
- Watch the movie in full screen.
- Pause when an LED lights up.
- Onto a piece of paper record the position to the nearest half-square. The x and y numbers need to be in the range between 0 and 500. If the dot shows up fully within a square it will be divisible by 10 (e.g 130). If it lies half way (on a line) it will end in "5" (e.g. 135).
- Hit play until the next LED lights up.
- Hit pause.
- Repeat until all LEDs are mapped.
Step 9: Designing Letters
Letters are defined one at a time. I found that Microsoft Word was a very handy tool here.
Define PRINT_GRID so the Arduino will print a map of the tree in the Serial buffer.
#define PRINT_GRID
Open up the Serial Monitor and copy/paste the output into Microsoft Word. Make sure to select a mono-spaced font such as currier.
In Microsoft Word, create a single-letter watermark.
- Select Layout tab.
- Click on Watermark.
- Click the bullet item Text.
- Enter the letter you plan to design (e.g. "G")
Now, back on the Word page resize and reposition the numbers to line up (roughly) with the watermark.
- Select all numbers (^A)
- Adjust the font size. (Verify the font is mono-spaced. e.g. Currier New.)
- Adjust left margin to move left and right.
- Adjust top margin to move up and down.
- You won't get a perfect alignment so just get close enough so there is a good number of pixels within (or near) the watermark.
- Using the watermark as a guide, enter numbers into the appropriate array in the Arduino Sketch program.
const PROGMEM byte letterG[] = { 41,52,53,73, 42,28, 23,8,12,46,48,68,91,84,95,72 };
Step 10: Capture the RFID Numbers
When an RFID tag touches the reader the ID number is printed in the Serial Monitor.
0x42, 0xD0, 0xF8, 0xBA,
Copy/paste this number into the array knownRFIDs and, with a sharpie, write the index of the array onto the RFID tag:
byte knownRFIDs [] = { 0xDD, 0xD0, 0xD7, 0x35, /* 0 */ 0x32, 0xC4, 0xD7, 0x35, /* 1 */ 0xE5, 0x50, 0xC6, 0x55, /* 2 */ 0xDB, 0xED, 0x17, 0xC5, /* 3 */ 0xC4, 0x5B, 0xD8, 0x35, /* 4 */ 0x1B, 0xF2, 0x17, 0xC5, /* 5 */ 0x6B, 0x74, 0xC6, 0x55, /* 6 */ 0x27, 0x7E, 0xD8, 0x35, /* 7 */ 0x49, 0x75, 0xC9, 0x55, /* 8 */ 0x19, 0xEC, 0x17, 0xC5, /* 9 */ 0x44, 0x2B, 0xE3, 0xE9, /* 10 */ 0xE4, 0x7C, 0xA8, 0xEB, /* 11 */ 0xD3, 0x1E, 0x96, 0xF4, /* 12 */ 0x52, 0x41, 0x67, 0xA9, /* 13 */ 0x42, 0xD0, 0xF8, 0xBA, /* 14 */ 0xD2, 0x12, 0x3F, 0x96, /* 15 */ 0xF2, 0x99, 0x61, 0xA9, /* 16 */ 0x02, 0xF1, 0xF8, 0xBA, /* 17 */ 0x32, 0xF9, 0x70, 0x63, /* 18 */ 0xD2, 0x8B, 0x3B, 0x96, /* 19 */ 0xF2, 0x50, 0x77, 0x64, /* 20 */ 0x52, 0xFD, 0x6F, 0x63, /* 21 */ 0xD2, 0xFE, 0x60, 0xA9, /* 22 */ };
Step 11: Wire the RFID Reader
The RFID reader is SPI compatible so wire it to the Arduino SPI pins. Also, Vcc is +3.3 volts on my setup. The RFID will not work if you wire Vcc to +5. Here are the connections:
Pin layout: -------------------------------------------------- MFRC522 Arduino Arduino Arduino Arduino Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Signal Pin Pin Pin Pin Pin ------------------------------------------------- RST/Reset RST 9 5 D9 RESET/ICSP-5 SPI SS SDA(SS) 10 53 D10 10 SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 +3.3 VCC 3.3v GND GND GND
Note: I have only tested this on an Arduino Uno.
Step 12: Define Your Messages
There are two types of messages:
This message constantly cycles when the tree is idle, when no one has tapped the RFID:
char *defaultMessage = "HOHOHO THE MAD WRAPPER SAYS HANG YOUR ORNAMENT HERE! ! ! ! ! ! ! ! !";
Note: When the program encounters the character "!" it displays an arrow pointing to the RFID reader.
Each person's name
I have 22 RFID keychain tags so I defined 22 names. Since there are not actually 22 people on my gift-giving list I filled in the rest with something random and Christmasy. The last five RFIDs do not actually appear on gifts.
char *people [] = { "CHRIS", // 0 "DONALD", // 1 "LINNEA", // 2 "SANDY", // 3 "MIKE", // 4 "DIANE", // 5 "DAVID", // 6 "ERIC", // 7 "CAROLYN", // 8 "DANIEL", // 9 "BRIANA", // 10 "STEVEN", // 11 "KRISTIN", // 12 "KATEY", // 13 "BAILEY", // 14 "MOOSE", // 15 "SADIE", // 16 "MELLOW", // 17 "SANTA", // 18 "ELF", // 19 "RUDOLF", // 20 "COMET", // 21 "VIXEN", // 22 };
Step 13: Final Touches
I bought some stick-on foam Santa figures from the local craft store. It was quick to peel-and-stick these decorations onto the RFID key tags. I'm happy I went the extra step. It looks good.
I also wrapped the base of the tree in silver foil wrapping paper to create a bit of a Christmas touch.
Both trees were big hits at the two Christmas parties. Cheers all around. It sure was a nice Christmas this year.
The Mad Wrapper does it again!