Project tutorial

Pac-Man LED Pixel Panel Costume © CC BY-NC-SA

Portable LED panels let you dress us like your favorite 8-bit video game characters.

  • 4,795 views
  • 3 comments
  • 85 respects

Components and supplies

Necessary tools and machines

Lasercutter
Laser cutter (generic)
Not *needed* but super helpful

About this project

Intro

First off, let's say 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.

Planning

The first step is always planning, but hey its worth noting, especially if you want to do a different 8-bit character.

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 Arduino board.

You can see by the layout 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. Meaning each pixel would be the same size on each costume. 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 tosee what 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.

That set our scale 22" / 14 pixels = 1.57"/pixel.

Materials

We wanted the costumes to be relatively easily worn around 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
  • Misc: DC Power Jack Adapters Breadboard jumper wires DC5V Power Supply, for testing Velcro Woven Duct Strap Duct Tape

The Base

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").

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.

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.

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.

Wiring

The wiring of the power to the lights and then to the board is done as shown in the diagram and photo.

The lead LED on the first string has an power in connection, there are two wires (hot/red and ground/white). These are connected to a female power jack adapter. The power supply is plugged into this adapter. Then we connect the power, ground, and data from that first LED's are connected to the 5v and GND connections on the Arduino and the DATA (middle) wire connects to the 3 PIN on the 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.

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.

The animation in action
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

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.

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

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!

Custom parts and enclosures

Ghost Laser Cutter File
Files to laser cut the ghost costume from 1/8" cardboard. It is set up for a 32" x 18" laser cutter bed size.
ghostlaser-1_8th_v5_feTmMAM4r0.dwg

Schematics

Wiring Diagram
How to plugin the LEDs, Ardunio, and portable power
Arduinolayout kchwsqmc6o

Code

LED Ghost Animation CodeArduino
This code runs the animation for the Ghosts
//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);

    }

}

Comments

Similar projects you might like

LoRa Gateway for DeviceHive

Project tutorial by DeviceHive IoT team

  • 1,494 views
  • 2 comments
  • 19 respects

Really Smart Box

Project tutorial by Stephen Harrison

  • 4,070 views
  • 2 comments
  • 15 respects

Raspberry Pi and Arduino Laptop

Project tutorial by Dante Roumega

  • 18,322 views
  • 6 comments
  • 45 respects

IoT Bird Feeder with Sigfox and Tweeter

Project showcase by Gaël Porté

  • 646 views
  • 0 comments
  • 9 respects

Arduino-Based Automatic Guitar Tuner

Project tutorial by Ben Overzat

  • 4,262 views
  • 0 comments
  • 16 respects
Add projectSign up / Login