Introduction: Pac-Man LED Pixel Panel Costume
Intro
First off, let's state the obvious: we like to do family costumes.
Last year we did space "aliens" which really looked more like people dressed in silver with LED strip accents. We really liked the LEDs since they are unique and make the kids easy to see when they are running around at night. We decided to do something that lights up again, but weren't sure what. It was my daughter that suggested Pac-Man, since she had recently played the Namco gem at a bowling alley a few weeks prior. That suggestion was all we would need. It was a great idea and we had to make it happen.
Note: Please excuse the lack of great process photos.I hadn't initially planned on doing a write up while I was making this. I hope it all still makes sense!
Step 1: Planning
The first step is always planning, but hey it's worth noting, especially if you want to do a different 8-bit character.
Choose the Characters
We chose Pac-Man characters for the family. Pac-Man, Ms. Pac-Man, and the ghosts Blinky and Pinky. I wanted it to be accurate and authentic to the original 8-bit characters so I began by looking up the original game sprites.
These help ensure we are getting the correct pixel pixel layout and shows each frame of the animations. For instance you can see the different frames of the ghost legs and Pac-Man's mouth in the sprites above.
I then laid out each frame of the animations in Excel so we know where the number of LEDs and the overall layout of each board. The individual numbers of the LEDs are needed later for programming the Ardunio board.
Number of LEDs
The Ghosts cover 170 pixels, Pac-Man is 137, and Ms. Pac-Man is 151, which means we needed 628 LEDs for the pixels. (170+170+137+151)
Size of Panels
You can see by the layout in Excel that the Ghosts are 14 pixels in height by 14 pixels in width. Pac-Man is 13x13 and Ms.Pac-Man is 14x14.
Once we knew the width and height by pixels we have to decide how big we wanted to make the panels. I wanted them all to be the same size relative to one another, so each pixel would be the same size on each costume.
The strings of LEDs we purchased had a distance of about 3" (75mm) between LEDs. This gives us the high end of how big we can make each pixel. To scale them properly we started by making sure it would be the right size for the smallest family member, my son. I measure him and held up some cardboard cutouts to see what was the largest size he could still comfortably put his arms over and still walk. We ended up at 22" as the size of the ghosts in height and width, but you may want to do a different size.
That set our scale of our pixels at 1.57" square (22" / 14 pixels, for the Ghost).
Step 2: Materials
We wanted the costumes to be relatively easily to wear and not too terribly cumbersome, so we opted for light materials rather than durable ones.
Base:
1/8" cardboard, laser cut and hot glued
Translucent Cover:
Drafting Paper (Vellum or Mylar)
LEDs :
12mm DC5V WS2811 Individually Addressable LEDs (Strings of 50)
Board:
Ardunio Uno R3
Power:
5V DC Portable Power Supply (Like a portable phone charger) + USB to DC Adapter
Note: You see a different one in the photos, I explain this in the wiring section
Misc:
DC Power Jack Adapters
Breadboard jumper wires
Velcro
Woven Duct Strap
Duct Tape
DC5V Power Supply, not needed, but helpful for testing
Step 3: The Panel
Luckily I have access to a laser cutter, so I knew I would be using it to make these. You won't need your own laser cutter. You can either send it out to be cut by a company that does laser cutting, or you can go the manual route and print the PDF and lay it out on the cardboard and cut it by hand.
The base is made from 1/8" cardboard sheets purchased from the local art/hobby store. Our laser cutter has a 32"x18" bed so I had them cut the sheets down to that size.
Panel
The panel is made up of a few main parts: the base, the slats, the cover, and the strap. The base holds the LEDs, the slate provide the pixels and overall stability of the panel, the cover diffuses the light, and the strap makes it portable.
Modeling
To make the files for the laser cutter I modeled the base using Rhino. I modeled the all the parts of the panel very accurately in an effort to let the laser cutter do as much work as possible.
I made each panel so that each vertical and horizontal fin would slide into each other and they would notch also into the base. Setting it up this way allows the parts of the panel to slide and notch together without the need for much glue, while also ensuring we would get perfect squares for the pixels.
Notes:
The notches and joints have a 1/64" clearance on both sides to let the cardboard slide together nicely. The slots end up being 5/32" wide (1/8" + 1/64" + 1/64").
I have added the 3d model in DWG format to the files for those interested.
Laser Cutting
As mentioned before our laser cutter is 32"x18" so the CAD files I made to do the laser cutting are set on that size. I have added the .dwg file for the Ghost costume. You can use it to laser cut your own, or you can print it out and use it as a template to hand cut the cardboard.
If you are going to do it by hand you can easily lay this out and cut strips of cardboard. You can could measure it out yourself, the pixels are about 1.5" square and 2" deep with a 12mm hole in the middle for the LEDs. You can also use the provided PDF as a template for cutting.
Notes:
We used 12mm LEDs and that's what size the holes are. The LEDs went in nicely, but since it is cardboard they got a little loose, especially if I had to take the LEDs out and put them back in. If I were to redo it I would make those holes slightly smaller.
Assembly
The base had to be cut in two pieces since our laser cutter bed's small dimension is 18", which is smaller than the 22" x 22" dimension of the base. I used good ole duct tape at the join to keep it together initially. This is really to keep it in place while adding the LEDs and slats. Once the slats were added to the base they provided the real support and stability.
Each slat is labeled by scoring either "H#" or "V#" for Horizontal (H) and Vertical (V) and which number (#) in order. The slats slide together nicely since we added additional 1/32" clearance. My first tests left a lot less room where they slid together and made it impossible to put it all together. Once the were all slid together we put the slats on the base. They notched in where the plus sign shaped holes in the base are. Once it was on the base I duct taped the slats to the base on the ends. Then I added a small bead of hot glue the top left corner where the slats meet to keep them in place and ensure they wouldn't slip.
The notches for the slats extend through the base so there is a small tab on the back of the base. I also added a bead of hot glue to these tabs to keep the slats securely on the base.
After thought
As you can see in the 3d model diagram I did not plan for an enclosure on the back of the panel. This was a mistake! I noticed this a couple of hours before tick-or-treating and I hastily cut 2.5" cardboard strips and added them to the back of the panel. to give something other than the LED wires to rest against the body.
This helped, but really it should have been fully enclosed. When walking around with the panels with the back open the LEDs tend to get pushed in. You can see in some of the pictures where the pixels are no longer really pixels, but point lights. This is where the LEDs were pushed or fell in. I stopped the family a few times to fix these over the night or tick-or-treating.
Note:
If you are going to make these, plan for a back panel to enclose the LEDs. Don't make the same mistake.
Step 4: LED Layout
The planning for the LEDs strings occurred in Excel where I laid out the 170 individual LEDs in order from 0-169 for the Ghosts.
Excel Layout
The important things to note are the distances between pixels and the start point.
If you don't want to cut and rewire the pre-strung lights you need to make sure you can reach from one hole to the other in your sequence. In my case distance between the individual LEDs on the pre-strung bundle is about 3 inches (75mm). This meant the pixels had to be adjacent to one another when laying them out.
For the starting point just make sure it is close to where you can mount the Arduino and power supply.
Placing The LEDs
Following the pattern laid out in Excel we push the LEDs from the back into place in the cardboard.
Note: The layout is mirrored since the excel layout it looking from the front, and we are pushing them in from the back. The 0 LED is on the left in Excel and on the right in the picture of the base from the back.
The LEDs have a small flange that keeps them in place. I found that the cardboard is a bit flimsy so the LEDs did move around a bit when walking around. If you want to keep them in place more securely you could put a dab of hot glue on them.
Step 5: Wiring
Power Supply
The best way to power this is with a 5V DC rechargeable battery (aka: a portable phone charger). Then use a USB to DC adapter to plug into your lights which should now be wired with the female DC adapter.
I made a mistake and used a 8xAA Battery Pack with an On/Off switch that I had from the previous year's costumes. It was only while writing this did I realize it has a 12V output and I was using 5V LEDs. (I am no rocket surgeon but I think this is bad). Since I had the battery pack around I just picked it up and plugged it in and everything worked and I didn't second guess it ¯\_(ツ)_/¯
Interestingly enough the battery packs I used gave us only about 2 hours of on-time. After figuring out that they were the incorrect power supply for the panels I tested the panels with the correct 5VDC portable phone charger and they lasted much much longer.
I tested a 2200 mAh and a 7800 mAh portable charger and the panels ran for 3h 40m and 12h 43m respectively. This means with a cheap "lipstick charger" you can get nearly 4 hours of on time.
Note: The on-time I got from my test were with the ghost costumes (170 LEDs) running at 40 brightness out of 255 (The brightness is set in the code section)
LEDs
I used strings of 12mm WS2811 individually addressable LEDs for outdoor signage. I bought them on Amazon and they came in strings of 50. Since I needed over 600 I bought the 500 pack which came with a bit of a discount.
Wiring
The wiring of the power to the lights and then to the board is done as shown in the diagram and photo.
The first LED on the string has a power-in connection. There are two wires (hot/red and ground/white). These are wired to a female power jack adapter. The power supply is plugged into this adapter.
The 5V, GND, and DATA from that first LEDs 3pin JST connector/input port are connected to the 5V, GND, and 3 PIN connections on the Arduino board. Make sure you check your string of LEDs before wiring it up. My LED wires were Red(5V), Green (DATA), White(GND), but yours may be different.
Notes:
When using the USB to power the Arduino, unplug the 5V connection, but leave the GND
Do not mix up the 5v and GND - that can fry your board. I know from experience, it doesn't smell good :(
Step 6: Code
Once you are all wired up the lights won't do anything when you plug them in. Maybe they will briefly blink. They need to be told what to do first and this is how I did it.
I am not covering how to program an Arduino board. If you don't know how to do this there is a great article on Arduino's Website: Getting Started with Arduino
FastLED
I used the FastLED library for these. Its easy to use and easy to find examples to help figure everything out. It was useful that they use Web Colors so you can set any LED to any color by using the name.
My Code
Below is the code for the Ghost, I have also uploaded the Arduino code file. The basic outline for the logic is to fill all LEDs with the main color, then change the color of, and turn off the individual sets of LEDs to make each "frame". Once we have a set for each "frame" of the animation, we loop through them at X speed X number of times to make up the whole animation. There may be a smarter way of doing this, but this is how I did it and it worked for me. Notes: You can turn the brightness up and down it will have an effect on how long the batteries last. Change the //fill body color to change the color of the Ghost (its Red below) You can change the speed of the animations by changing the number and speed of the loops
//ANIMATED PACMAN GHOST LED #include "FastLED.h" #define NUM_LEDS 170 #define DATA_PIN 3 CRGB leds[NUM_LEDS]; void setup() { delay(2000); FastLED.addLeds<ws2811, data_pin,="" rgb="">(leds, NUM_LEDS); FastLED.setBrightness(40); //Number 0-255 FastLED.clear(); } //looking left int eyes_pixels_l[] = {17, 20, 21, 24, 37, 38, 39, 40, 41, 47, 48, 49, 94, 102, 103, 106, 119, 120, 121, 122, 123, 129, 130, 131}; int pupils_pixels_l[] = {15, 16, 22, 23, 92, 93, 104, 105}; //looking right int eyes_pixels_r[] = {38, 39, 40, 46, 47, 48, 49, 50, 63, 66, 67, 75, 120, 121, 122, 128, 129, 130, 131, 132, 145, 148, 149, 152}; int pupils_pixels_r[] = {64, 65, 76, 77, 146, 147, 153, 154}; //remove pixels around feet int void_pixels_1[] = {8, 29, 30, 31, 83, 84, 85, 86, 138, 139, 140, 161}; int void_pixels_2[] = {7, 31, 55, 56, 57, 112, 113, 114, 138, 162}; int sad_ghost[] = {11, 26, 35, 48, 49, 53, 60, 64, 65, 80, 89, 104, 105, 109, 116, 120, 121, 134, 143, 158}; int eyes_seconds = 2; int reg_ghost_seconds = 10; int feet_delay = 120; //delay in ms b/w feet v1 v2 int eye_loop = (eyes_seconds*1000)/feet_delay; // how many times to look left and right before switching int reg_ghost_loop = reg_ghost_seconds/eyes_seconds; int sad_ghost_loop = 50; int sad_ghost_blink_loop = 10;< void loop() { for(int i = 0; i < reg_ghost_loop; i++){ for(int i = 0; i < eye_loop; i++){ //fill body fill_solid(leds, NUM_LEDS, CRGB::Red); //set eyes for (int i = 0; i < 24; i++){ leds[eyes_pixels_l[i]] = CRGB::White; } //set pupil for (int i = 0; i < 8; i++){ leds[pupils_pixels_l[i]] = CRGB::DarkBlue; } //remove around feet (v1) for (int i = 0; i < 12; i++){ leds[void_pixels_1[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); //fill body fill_solid(leds, NUM_LEDS, CRGB::Red); //set eyes for (int i = 0; i < 24; i++){ leds[eyes_pixels_l[i]] = CRGB::White; } //set pupils for (int i = 0; i < 8; i++){ leds[pupils_pixels_l[i]] = CRGB::DarkBlue; } //remove around feet (v2) for (int i = 0; i < 10; i++){ leds[void_pixels_2[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); } for(int i = 0; i < eye_loop; i++){ //fill body fill_solid(leds, NUM_LEDS, CRGB::Red); //set eyes for (int i = 0; i < 24; i++){ leds[eyes_pixels_r[i]] = CRGB::White; } //set pupils for (int i = 0; i < 8; i++){ leds[pupils_pixels_r[i]] = CRGB::DarkBlue; } //remove around feet (v1) for (int i = 0; i < 12; i++){ leds[void_pixels_1[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); //fill body fill_solid(leds, NUM_LEDS, CRGB::Red); //set eyes for (int i = 0; i < 24; i++){ leds[eyes_pixels_r[i]] = CRGB::White; } //set pupils for (int i = 0; i < 8; i++){ leds[pupils_pixels_r[i]] = CRGB::DarkBlue; } //remove around feet (v2) for (int i = 0; i < 10; i++){ leds[void_pixels_2[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); } } //sad ghost regular for(int i = 0; i < sad_ghost_loop; i++){ //fill all red fill_solid(leds, NUM_LEDS, CRGB::Blue); //set eyes for (int i = 0; i < 20; i++){ leds[sad_ghost[i]] = CRGB::Yellow; } //remove around feet (v1) for (int i = 0; i < 12; i++){ leds[void_pixels_1[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); //fill body fill_solid(leds, NUM_LEDS, CRGB::Blue); //set eyes for (int i = 0; i < 20; i++){ leds[sad_ghost[i]] = CRGB::Yellow; } //remove around feet (v2) for (int i = 0; i < 10; i++){ leds[void_pixels_2[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); } //sad ghost blinking for(int i = 0; i < sad_ghost_blink_loop; i++){ //fill body fill_solid(leds, NUM_LEDS, CRGB::Yellow); //set eyes for (int i = 0; i < 20; i++){ leds[sad_ghost[i]] = CRGB::Red; } //remove around feet (v1) for (int i = 0; i < 12; i++){ leds[void_pixels_1[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); //fill body fill_solid(leds, NUM_LEDS, CRGB::Blue); //set eyes for (int i = 0; i < 20; i++){ leds[sad_ghost[i]] = CRGB::Yellow; } //remove around feet (v2) for (int i = 0; i < 10; i++){ leds[void_pixels_2[i]] = CRGB::Black; } FastLED.show(); delay(feet_delay); } }
Step 7: Add the Cover
I recommend leaving the cover to the end since it is made of paper and can rip. It is also useful to be able to reach the LEDs from the front when you are putting them in place or making adjustments.
I used a roll of drafting paper I had lying around. I am pretty sure it is vellum, but it might be mylar. Either way what you want to a translucent paper that is wide enough to cover the whole thing so you don't have to deal with a seam. You can get rolls of drafting paper at an art store or online.
To keep the paper in place I put a line of regular old Elmers glue along the top edge of the vertical fins. I didn't do the ones horizontal ones as all you really need is for the paper to stay mostly in place. Keeping the paper glued down makes sure the grid read through and make the panel look like individual pixels.
After you get the glue down lay the paper on top and put books or something heavy-ish on top to keep it in place and let the glue set.
Once the glue sets you can cut the excess paper off. Leave a little extra bit of paper around the edges to fold over and tape down, this helps ensure the edges won't peel up or come loose.
Step 8: Road Ready
For the finishing steps we get it ready to go on the road.
- Mount the Arduino and power supply to the back with Velcro
- Tape the connections together so they don't come loose
- Add a strap to carry it around. I used woven duct strap for this (like the drafting paper I had it around).
- Load up some Pac-Man music and sound effects on your phone and bring a bluetooth speaker
Step 9: Profit
Once you are all done you can send out your 8-bit family into the neighborhood to impress the neighbors and collect your sweet sweet candy profits.
Thanks for reading! If you have any questions feel free to ask!