Introduction: How to Make a Musical, Motorized Glow-in-the-dark-ghost Mobile

This instructable describes how to design and build a motorized glow-in-the-dark, 3D-printed-ghost mobile.  It is not too difficult to make these cute decorations assuming you own or have access to a 3D printer and glow-in-the-dark printing material.  When the lights go out the ghosts take on a whole new "life" at night with their eerie glow!

The original plan was based on just this simple design, but my over caffeinated imagination couldn't stop there.  It decided to go high-tech on this one.  Added to the design was a motor to turn the mobile, a light to charge the glowing material and some additional components to trigger some action.  The cherry on the cake is to synchronize this behavior with a spooky sound track.

This instructable will walk you through all of the steps to replicate the entire project.  However, you can alway stop at any step from just printing off a ghost, to just building the mobile or taking it all the way to the end.

Step 1: Tools and Materials

For this project you will need the following tools and materials:

Tools:
3D Printer
3D CAD Program (I'm using AutoDesk Inventor)
Exacto Knife
Small Drill Bit and Drill
Wire Cutters
Needle Nose Pliers
Pen (for writing labels)
Digital Scale
Arduino SDK

Materials:
Glow-in-the-dark Printing Material (glowing ABS filament is available at amazon.com)
Sturdy Wire (you can use an old wire coat hanger, I'm using 1mm SS welding rod)
Small Hook (for hanging the mobile)
Masking Tape (for temporary labels)
Various Jumpers/Wires

Electronics:
Arduino Board
IR remote kit
IR LED
Stepper Motor and Controller
Remote Controlled CD Player with Spooky Sound Track CD

Step 2: Sketching Out the Design

This should always be the first step of any project you are designing yourself.  Grab a piece of paper and a pen and draw out the vision in your head of what this should be.  You'll find that when you have to translate an idea onto a piece of paper that your mind will begin thinking about aspects and details that were overlooked when it was just in your head.

The original scale of this concept was to just design a glow-in-the-dark ghost.  My over-caffeinated mind took this idea and ran with it.  "Why stop there?" it said, "Many cute ghosts are better than just one! And why not make them fly?"  So the idea of creating a mobile to make the glowing ghosts fly came to be; which led to the idea of motorizing the mobile; which led to the idea of using a beam-breaking detection circuit to start the motor; which led to the the idea of using a light to "charge" the glow effect that would turn off when the beam was broken; which led to the idea of adding a spooky sound-track that would start playing when this happened.  And who am I to ignore myself?



The point of all of this is that putting your thoughts down on paper can lead to a much more interesting design than just jumping straight into making something.  If you don't already do this, give it a try on your next project.

Now that the basic design is completed we can start making something!

Step 3: Roughing Out the Ghost Body

First launch your CAD program and create a new part.  I'll be using AutoDesk Inventor for this project and this is what you will see in the illustrations.  The first thing to create is a base of the ghost that is ~1" by 1" somewhat offset from the origin.  Then form an extrusion approximately 1" tall from this sketch.  This will form the main block from which we will carve out the rest of the ghost.



Next create a work suface that is aligned with the vertical extrusion and the x,y plane.  Draw a circle ~3/4" in diameter located at the top edge of the extrusion.  Make sure that the circle is a little off center--you will see why in the following steps.



Now, using the spline tool create a moderately squiggly line that extends tangentially from the circle you drew down to the bottom corner of the furthest edge of the extrusion.



Draw a line that extends perdendicular from the top edge of the extrusion, through the center point of the circle and down to the bottom edge of the extrusion.



Next draw a line connecting the bottom point of the line you just drew to the bottom point of the spline you drew.  This last line will create a closed shape that will be the profile of a revolving cut procedure to create the ghosts shape. 



Trim away the remaing line segments we will not use for this profile.



A rotational cut of this profile should now be performed using the vertical line as the rotational axis and the "outside" shape as the face.  You want to have a "lopsided" revolve such that there is a long flat region on one side of the extrusion.  The illustration shows this more clearly.  If this area is too small adjust the sketch that formed the template for the revolve operation to one side to increase this area.




Step 4: Creating a Hollow Shell

To hollow out the ghost use the "shell" tool located in the "Modify" menu item.  After selecting this option click on the surface you want to be the opening for the hollowed out shape.  Think of it like you have one half of a watermellon and you want to scoop out the yummy goodness.  The top surface you would scoop out is the surface you should select.  You may have to experiment with different widths to find the right thickness of the shell.




After selecting the face and executing the shell operation your model should look something like this.

Step 5: Making the Eyes and Mouth

Now you must remove material to form the space for the eyes and mouth.  First create a work plane that is parallel to the X,Z plane and offset just beyond the surface of the model.




Now create a new sketch with three ovals for the eyes and mouth. The mouth oval should be slightly larger than the eyes.




Now perform a cut extrusion that goes completely through one side of the ghost body but not through the back side of the form.


Step 6: Smoothing the Edges Over

Now we can smooth out all of the hard edges on the ghost.  To do this use the "Fillet" tool under the "Modify" menu for this process. 




Select each edge one at a time and adjust the diameter of the fillet until there is a smooth transition.  Make sure you do this for all portions of the model that have an abrubt transition or hard edge.  The following images show where my model was smoothed out.

Step 7: Adding Arms to Our Ghost

Finally arms must be added to our friendly ghost.  This first requires a work plane to be defined where the cross section of the arm will be drawn.  To get the right angle of these planes first create a 3D sketch and add two points on the surface of the model where the tangential plane is about right.




Now create a work plane based on the "Tangent to Surface Through Point" method.  Select the model near the point you created followed by the point itself.




Create a new sketch on this work plane and draw a small circle on the body just below the center of the mouth.




Now extrude this circle so that it connects with the model and extends out from the model a little bit.




Repeat this process for the other side.




Finally smooth the joints where the arms meet the body using a fillet process and round out the "hands" using the same tool.




You now have your finished ghost!!!

Step 8: Printing the Ghosts

After completing the model you will need to export the model as an STL file.  To do this with AutoDesk Inventor click on the menu icon in the top left corner and select the "Export" option.  You will have the choice of different types of files.  Select the STL model and export this model using high quality settings.

Open the STL file you just saved in the printing program you are using (in my case the UP! 3D application) and place the model on the platform.  Adjust the size of the model to a size of your preference.

For the UP! 3D printer I like to always perform a print preview before actually printing.  This will tell you about how long the printing process will take as well as approximately how much material it will use up.  After this completes  configure the printer to print at high quality and kick off the actual printing process.  Now sit back and watch the magic happen....




For the mobile you will need to print multiple copies of the model.  For my project I've chosen to use 7 copies with slightly adjusted sizes for each copy.  Some were printed skinny and tall, some short and fat and as well as other variations.  You can do this with the UP! 3D printing software by first selecting the model and then using the scaling icon to selectively "stretch" each dimension by an appropriate amount. 

Have some patients as it will take a number of hours to print them all of the ghosts.  I had to spread the printing process over a few days to print all seven ghosts.  With the UP! 3D it should take between 30 minutes to 2 hours depending on small or large each ghost is.

Step 9: Drilling Holes in the Ghosts' Heads

They are already dead, don't worry about hurting them.  Use the small drill bit listed in the tools list of this instructable to slowly drill through the top of the each of the ghosts.  This hole must be large enough to accommodate the wire you will use to connect the ghosts to the structure of the mobile.  Do this for all of the ghosts.


Step 10: How Much Does a Spirit Weigh?

A mobile balances its elements by having equal force applied to both opposing sides of each fulcrum in the structure.  To equalize this force you can apply the same basic priniciple as a lever.  The force applied to a lever is proporitional to the mass of an object and the distance this object is located from the fulcrum.



As an example, if you have two ghosts--one weighing 3 grams and another weighing 9 grams--you will need to place the 3 gram ghost thrice as far from the fulcrum as the 9 gram ghost to balance this group.  Each additional ghost added to a side will add to the equation.  Example 2: 5g ghost at 5 inches plus 1g ghost at 15 inches will balance with a 4g ghost at 10 inches  (5*5 + 1*15 == 4*10) 

To figure out where the balance point is for each fulcrum will be you must first weigh each ghost.  Since each model is slightly different in size each will be slightly different in weight.  Measure and write the weight of each model on a piece of tape and stick this lable to each model.  It does not need to be exact, just approximate to help when assembling the different groups of ghosts and their relative position with resect to their shared fulcrum.

Step 11: Attaching Fasteners to the Ghosts

This step describes how to create small fasteners that will connect your ghosts to the mobile.  You will need wire cutters, needle nose pliers and the sturdy wire you will be using to build the scaffold of the mobile.  Start by cutting approximately 1/2 inch lengths of wire.  You will need one piece for each ghost.  Now using the need nose pliers bend a small loop in the end similar to what you see in the illustration.  This will form the inside of the fastener.



Once you have finished making a complete set you will use the needle nose pliers to hold the looped end of the fastener and feed it through the hole that was drilled through the hop of the head.



Now, use the same technique to bend another loop at the outside end of the fastener.



Now repeat for all of the remaining ghosts until they are all equipped with fasteners.

Step 12: Placing the Ghosts

Now that each ghost has been weighted it is time to apply the fulcrum theory to the mobile design.  Begin by selecting the different ghosts that you want to include on each section of the mobile.  Then for each group of ghosts sketch out the relative placement of each ghost within a tier balancing them around the fulcrum.

Start with the bottom tiers as you will need to take the total weight of each tier into account when balancing the tiers that they are attached to above.  Once you have defined the groupings and approximate placement figure out where you want the fulcrum in the tier above it and add any additional ghosts that may be needed to balance out this level.



Remember that the total mass of a tier is what will be taken into account for the applied weight on the tier it is attached to.  Include this in your sketch and it will help you to estimate where you can add weight to balance out the design.

For my design I stayed with a simple three tier design, but you can apply this process to as many tiers as you like.

Once you have the basic layout begin constructing each layer by bending small "gaps" on the lever where the inside and outside ghosts should be.  Then place the ghosts in their position and add a third ghost in the approximate location you mapped out.  Shift this ghost around a little until the whole tier balances perfectly around the fulcrum.  Do this by adding a "bump" where the fulcrum should be and then support it with a vertical length of wire with a bend at the end.  And one last bend where the middle ghost should be for perfect balance.  Complete this for all of the tiers and assemble the mobile.


Step 13: Adding the Motor

For the motor I used a very inexpensive stepper motor that came with a controller from www.dx.com.  The axle on this stepper motor is keyed to accept a coupler with two retaining screws.  You could special order a part that would fit, but that would take too much time and money.  Instead you can measure out the dimension and design a tension coupler to fit snugly on the axle. 



I did this in inventor and then printed out the piece.  It fits perfectly and will do the job just fine.



You can see the gist of the design here.  After printing it out I found that it popped right onto the axle with a snug fit.  I added some through-holes to the opposite end where you will attach the mobile hanger.



After printing out the part you are ready to go mechanically, but you will still need something to hold the motor and need to program the Arduino to control the motion of the mobile.  Since there are other items that will also interface with the Arduino we will cover all of this in one section near the end of the instructable.

Step 14: Build a Haunted Housing for the Motor

You will need to build some sort of house for the motor and the controller.   This is necessary as without one the mobile will be dangling from wires and not be stable.  Your design doesn't need to be as complicated as this.  You could cobble together something in a project box with some hot glue and accomplish the same goal.  If you do want a more refined design you can replicate what I've done. Otherwise heat up that hot glue gun and hack away.

The instructions to make this housing are very high level and will not go in to details--this will be described in greater detail in a future instructable.  Feel free to use the attached STL files to print out a facsimile of my design, assuming you are using the same motor/controller combination.

I first designed the bottom half of the motor housing with mounting holes and an opening to accomodate the motor and the coupler that was designed earlier.  There was also an opening to accomodate the chasis of the motor where the wire protruded.

Download STL model





Then I built the top half to house the stepper motor controller also with holes for mounting the board.  A small opening a couple millimeters wide was added to allow the wires that will provide the control signals to exit the housing.  At the top of this half a small eyelet was added to allow the housing to hang from a hook or chain.

Usign the STL files I printed out the housing and found that the motor and control board fit perfectly snug within the housing.

Download STL model



Clean up the printed object by removing the support material and insert the components into the appropriate half of the housing.




Now connect the stepper motor wires to the control board.  Wrap the extra wire around and tuck them in so they stay within the housing.




Connect the power cables being careful not to connect them the wrong way!  Then connect the data cable, again being careful to remember which wires map to which input pin on the controller.



Finally feed the controll and power wires through the narrow opening and close up the housing.  You can design tabs to create a mechanical linkage between the top and bottom halves, however in my first attempt I designed these tabs to be to small to have sufficient durability and ended up removing them.  In a rev 2 of this project I would redesign these to be about 3x the size of the originals.  For now i'm just using masking tape to hold the two sides together. 



The last thing I did was to print out a 4 AAA battery holder from thingiverse and attached it with tape to the housing.  4 AAA batteries in series will deliver 6V to the stepper motor providing sufficient power and elliminating the need to route power along with the data cables.  This model was graciously provided by member obijaun of thingiverse--thanks!

Step 15: Adding the Audio

For this step I've decided to dig up an old Kenwood portable CD player that came with a slim remote.  The idea here is to use the arduino to send the same signals that play and skip tracks normally sent by this remote.  For this to work we need to be able to capture the encoded IR signal and then just send these same signals when the appropriate trigger occurs.  It sounds terribly complicated, but with an inexpensive IR kit and an IR LED we can achieve this with some existing code.

First setup the IR receiver by following the instructions provided at Ken Shirriff's blog.  Using the IRrecord example provided in the library point the remote control at the IR receiver and press the button corresponding to the signal you want to capture.  The two buttons I used were "play" and "skip".  You will need to have the serial monitor in the Arduino SDK up in order to read the code.  Write these codes down and save them for the next step.



Now that you have the codes captured for the functions you wish to use we want to install an IR LED to the system that will be used to control the CD player. 

Step 16: Tying It All Together With an Arduino

Finally, everything is tied together in an Arduino sketch.  This sketch performs the following functions:

  • Controls the stepper motor to rotate the ghost mobile
    • Rotates in a sinusoidal pattern to make them look more "autonomous"
    • Rotates for 10 seconds (aligned perfectly with the audio)
  • Converts IR codes from the remote control that came with the IR remote kit into the correct IR codes for the Kenwood CD player
    • Provides an IR read function to capture and display the exact IR code data from the original remote
    • Contains a hard-coded list of button press codes for use in translating the remote button pushes
    • Sends the appropriate IR code based on the key press on the new remote
    • Sends "Pause" and "Skip" codes 10 seconds after the play button is pushed
  • The code also sends some debug messages to the serial port console in case you are interested in the details under the hood while it is running.

Originally I was planning to also control lighting to turn the lights off when a motion sensor was tripped.  Unfortunately I broke the hardware I was using and did not have the time to replace it so the system will be controlled entirely by the remote control.

The following list maps the Arduino Mego 2560 board pins to the respective component:

  • Status LED: PWM Pin 13
  • IR Receiver Data Input: PWM Pin 11
  • IR Emitter to CD Player: PWM Pin 8
  • Stepper Motor Control Signals: PWM Pins 4, 5, 6 and 7
  • Grounds routed to appropriate pins as necessary

Two existing pieces of code were used and heavily modified.  These include the IRremote library provided by Ken Shirriff and the stepper motor sample code included in the Arduino SDK.  And at last, here is the code (which leveraged and credited previous works):

/////////////////////////////////////////////////////////////////////////////////////////
/*
Stepper Motor Control - sinusoidal rotation

This program drives a unipolar or bipolar stepper motor.
The motor is attached to digital pins 4 - 7 of the Arduino.
The motor should revolve one direction
following a sinusoidal rate of rotation. 

The program also allows the user to remotely activate and deactivate the
glowing ghost mobile of doom.  It sends control signals to the mobile for 10
during which time the audio from the disk in the CD player will play 10
seconds of audio.  After 10 seconds the code will send the pause and skip
command to go to the next track.

Created on Nov. 4th, 2012

(Some parts based on Stepper Motor Control program by Tom Igoe
  Created 11 Mar. 2007
  Modified 30 Nov. 2009)

(Some parts based on IRrecord program by Ken Shirriff
  Created September, 2009)
*/
#define PAUSE_PLAY_BUTTON 0x6D92C837
#define REPEAT_BUTTON 0x6D929867
#define SKIP_BUTTON 0x6D92E817

#define POWER 0x00FFA25D
#define BUTTON_MODE 0x00FF629D
#define BUTTON_PAUSE_PLAY 0x00FF22DD
#define BUTTON_SKIP 0x00FFC23D
#define BUTTON_0 0x00FF6897
#define BUTTON_1 0x00FF30CF
#define BUTTON_2 0x00FF18E7
#define BUTTON_3 0x00FF7A85
#define BUTTON_4 0x00FF10EF
#define BUTTON_5 0x00FF38C7
#define BUTTON_6 0x00FF5AA5
#define BUTTON_7 0x00FF42BD
#define BUTTON_8 0x00FF4AB5
#define BUTTON_9 0x00FF52AD

#include <Stepper.h>
#include <IRremote.h>

int RECV_PIN = 11;
int BUTTON_PIN = 12;
int STATUS_PIN = 13;

IRrecv irrecv(RECV_PIN);
IRsend irsend;

decode_results results;

int step_enabled = LOW;
const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution for your motor
const float max_speed = 10;  //sets the maximum rotational speed of the motor
const float resolution = 100;  //sets the frequency by which the motor speed will change
float rotational_vel = 0;  //holds the current rotational velocity scalar

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 4,5,6,7);           

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(BUTTON_PIN, INPUT);
  pinMode(STATUS_PIN, OUTPUT);
}

// Storage for the recorded code
int codeType = NEC; // The type of code
unsigned long codeValue = 0x6D92C837; // The code value if not raw
int codeLen = 32; // The length of the code
int toggle = 0; // The RC5/6 toggle state
int buttonState = LOW; //virtual button press

// Stores the code for later playback
// Most of this code is just logging
void storeCode(decode_results *results)
{
  codeType = results->decode_type;
  int count = results->rawlen;
  if (results->value == REPEAT)
  {
    // Don't record a NEC repeat value as that's useless.
    Serial.println("repeat; ignoring.");
    buttonState = LOW;
    return;
  }
  Serial.print("storing code: ");
  Serial.print(results->value, HEX);
  codeValue = results->value;
  codeLen = results->bits;
  Serial.print("; code length: ");
  Serial.println(codeLen);
  buttonState = HIGH;
}

void sendCode(int repeat) {
  if (repeat)
  {
    irsend.sendNEC(REPEAT, codeLen);
    Serial.println("Sent NEC repeat");
    buttonState = LOW; //turn off virtual button after sending code
  }
  else
  {
    Serial.println("Sending non-repeat code.");
    switch (codeValue) {
    case POWER:
      irsend.sendNEC(PAUSE_PLAY_BUTTON, 32);
      codeValue = PAUSE_PLAY_BUTTON;
      Serial.print("Sent pause play code: ");
      Serial.println(PAUSE_PLAY_BUTTON, HEX);
      buttonState = LOW; //turn off virtual button after sending code
      break;
    case BUTTON_PAUSE_PLAY:
      irsend.sendNEC(PAUSE_PLAY_BUTTON, 32);
      Serial.print("Sent pause play code: ");
      Serial.println(PAUSE_PLAY_BUTTON, HEX);
      buttonState = LOW; //turn off virtual button after sending code
      break;
    case BUTTON_MODE:
      irsend.sendNEC(REPEAT_BUTTON, 32);
      Serial.print("Sent repeat code: ");
      Serial.println(REPEAT_BUTTON, HEX);
      buttonState = LOW; //turn off virtual button after sending code
      break;
    case BUTTON_SKIP:
      irsend.sendNEC(SKIP_BUTTON, 32);
      Serial.print("Sent skip code: ");
      Serial.println(SKIP_BUTTON, HEX);
      buttonState = LOW; //turn off virtual button after sending code
      break;
    }
  }
}

int lastButtonState = LOW;
int i = 1;

void loop() {
  if (i > resolution)
  {
    i = 1;
  }

  // If button pressed, send the code.
  //buttonState = digitalRead(BUTTON_PIN);
  if (lastButtonState == HIGH && buttonState == LOW) {
    Serial.println("Released");
    lastButtonState = LOW;
    irrecv.enableIRIn(); // Re-enable receiver
  }

  if (buttonState) {
    Serial.println("Sending IR code");
    digitalWrite(STATUS_PIN, HIGH);
    sendCode(lastButtonState == buttonState);
    digitalWrite(STATUS_PIN, LOW);
    step_enabled = HIGH;
    lastButtonState = HIGH;
    //delay(50); // Wait a bit between retransmissions
  }
  else if (irrecv.decode(&results)) {
    Serial.println("Reading IR code");
    digitalWrite(STATUS_PIN, HIGH);
    storeCode(&results);
    irrecv.resume(); // resume receiver
    digitalWrite(STATUS_PIN, LOW);
  }

  //Serial.println("rotate the motor");
  rotational_vel = abs(max_speed * sin(float(i)*3.14159/10) + 2);  //program a sinusoidal velocity for the stepper motor
  myStepper.setSpeed(rotational_vel);
  if (abs(rotational_vel) > 0.001 && step_enabled == HIGH)  //a velocity of 0 will lock up the stepper.h library.
  {
    Serial.println("valid stepper function entry");
    if (i < resolution && step_enabled == HIGH)
    {
      Serial.print("iteration: ");
      Serial.println(i);
      Serial.print("Velocity: ");
      Serial.println(rotational_vel);
      myStepper.step(10 * rotational_vel);
      i++;
    }
    else
    {
      step_enabled = LOW;
      i = 0;
      Serial.println("Pausing Playback and Skipping");
      digitalWrite(STATUS_PIN, HIGH);
      codeValue = BUTTON_PAUSE_PLAY;
      sendCode(1 == 2);
      delay(100); //Wait between transmissions
      codeValue = BUTTON_SKIP;
      sendCode(1 == 2);
      digitalWrite(STATUS_PIN, LOW);
      lastButtonState = HIGH;
    }
  }
}

Step 17: Showtime!

I'm very pleased with the way this turned out.  Please enjoy the videos!!!




As you may recall in the original design, I wanted to make this motion activated and also control the lights to turn off.  I had to pull this feature at the last minute, but will continue on a second rev (when I have the time) to implement this feature.  We are all familliar with dead lines and I really wanted to get this one in for the Halloween contest. 

Thanks for making it to the end and please let me know if you make something similar or have suggestions for the future.

Halloween Decorations Contest

Third Prize in the
Halloween Decorations Contest

DIY Audio

Participated in the
DIY Audio

Hack It! Contest

Participated in the
Hack It! Contest