“Dusty” The Crouching Ghoul

We started seeing a bunch of ‘crouching ghoul’ props being built, in an attempt to replicate this character: https://www.youtube.com/watch?v=Egksi_wWvFg . Special thanks to Rob Beach (Scares on Sequoia) for posting details of his build that gave us a leg up on the mechanism to get Dusty started.

The first order of business was to work out the side to side motion. There are a lot of ways to do this. Most of my props are based on a simple arm mounted to a 12v wiper motor. Two modifications I made to my original design was the addition of the lazy-susan for the pvc t-connector to ride on so it can rotate smoother. I also added a bracket behind the drive arm, with a small wheel so it can bear the weight of the ghoul above.

The wiper motor is controlled by a pulse-width-modulator (PWM), and powered by a 6-amp 12-volt power supply. The power supply I selected comes with a splitter cable, which definitely comes in handy! The PWM is mounted in a small food-saver box. I ran input and output wires using the same connector type as the power supply, which allows me to just drop the PWM inline between the power source and the motor.

The boxed up skeletons from CostCo are a great starting point, but their pose is very … stiff. Just look at the terrific posing options they advertise right on the box! We have standing bolt upright, sitting bolt upright, and that remarkable game-changer: walking bolt upright.

I like more relaxed poses, so I usually take the skeletons apart and use a curved length of conduit to give the spine a more natural curvature. spines don’t bend much along the rib-cage. Most of the flexing happens betwen the ribcage and the pelvis. To simulate this, the lower part of the spine needs to be broken apart into individual vertebrae, hollowed out to fit around the 1/2″ conduit, then hot-glued into position. This requires a fair bit of sanding and grinding down of the spine parts, but once you screw & glue it all back together, it all seems worthwhile. One “feature” of this creature is the way the shoulders “move”. After watching the video, it finally dawned on me that the shoulders are actually the only thing NOT moving on the prop. It’s as if the rib cage (and shoulders) are disconnected from the spine. In effect, the rib cage can spin freely on the spine…it just doesn’t spin freely because of the arms. So Dusty’s spine within the ribcage was ripped out, and replaced with a length of 3/4″ pvc pipe. The 1/2″ conduit of the new spine forms the axis of the spine. A word of warning … don’t curve the conduit before you insert the 3/4″ pipe. Trust me.

The curved spine piece is connected to the rocking mechanism just past the tailbone. The legs were detached from the pelvis. Each leg is kept intact, as they were out of the box. They are actually held together by an elastic band connecting the two hip sockets, through the pelvis. This allows them to have free movement as the ghoul rocks back and forth.

The next thing is how I want to move the head. I decided Dusty would be much creepier if the mechanism that turns his head operates on its own cadence…independent of the rest of the body. What you see here is a 28BYJ-48 stepper motor. I coupled that with a ULN2003 motor controller module, and hooked those up to an Arduino Nano as the brain. The sketch I created to drive the head is using the StepperAccel library and incorporates some pseudo-random movement. I ran 12v power up through the conduit (spine). the circuit boards are all inside the head.

This is the arduino sketch that drives the head movement. It utilizes an extension for the arduino called the AccelStepper library, which simulates a more natural motion.

#include <AccelStepper.h>
#define HALFSTEP 8
#define FULLSTEP 4

// You need the AccelStepper library for this sketch to run.  You can get it from here: http://aka.ms/AccelStepper

// The AccelStepper constructor expects the "pins" specified to be the ends of each coil respectively.
// First the ends of the Blue/Yellow coil, then the ends of the Pink/Orange coil (Blue,Yellow,Pink,Orange)

// However, 28BYJ connector, ULN2003 board, and our current configuration is that pins are arranged in the proper FIRING order, 
// Blue, Pink, Yellow, Orange.

// No biggie, that just means that we need to pay attention to what pins on our Arduino,
// map to which ends of the coils, and pass the pin numbers in in the proper sequence.  

// To help with that, I will specify my pin variables based on their color.

#define blue 2
#define pink 3
#define yellow 4
#define orange 5

// How many steps to go before reversing
int fullCircle = 2048;  //2049 steps per rotation when wave or full stepping
//int fullCircle = 4096;  //4096 steps per rotation when half stepping

int callibrationPosition = fullCircle / 2;
int centerPosition = callibrationPosition / 2;

int callibrationAngle = (callibrationPosition * 360) / fullCircle;

int sweepAngle = 140;
int lowAngle = (( callibrationAngle - sweepAngle ) / 2 );
int highAngle = lowAngle + sweepAngle;
int rangeLowPosition = ( lowAngle * fullCircle ) / 360;
int rangeHighPosition = ( highAngle * fullCircle ) / 360;

int state = 0;

// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
// Notice, I'm passing them as Blue, Yellow, Pink, Orange (coil ends order) not
// Blue, Pink, Yellow, Orange (firing order). 
AccelStepper stepper1(FULLSTEP, blue, yellow, pink, orange);

void setup() {
  Serial.begin(9600);
  
  //Set the initial speed (read the AccelStepper docs on what "speed" means
  stepper1.setSpeed(200.0);         
  //Tell it how fast to accelerate
  stepper1.setAcceleration(200.0); 
  //Set a maximum speed it should exceed 
  stepper1.setMaxSpeed(4000.0);    

  //Tell it to move to the target position
  callibrationPosition = fullCircle / 2;
  centerPosition = callibrationPosition / 2;
  callibrationAngle = (int)(((long)callibrationPosition * 360L) / (long)fullCircle)-10;

  lowAngle = (( callibrationAngle - sweepAngle ) / 2 );
  highAngle = lowAngle + sweepAngle;
  rangeLowPosition = (int)(((long)lowAngle * (long)fullCircle ) / 360L);
  rangeHighPosition = (int)(((long)highAngle * (long)fullCircle ) / 360L);
  
  state = 0;
  stepper1.moveTo(callibrationPosition);   
}

void loop() {

  //Check to see if the stepper has reached the target:
  
  if ( stepper1.distanceToGo() == 0 )
  {
    switch ( state )
    {
      case 0:   // Sweeping Right
        state = 1;
        Serial.print("New State ");  
        Serial.print(state);
        Serial.print("  moveTo ");
        Serial.println(centerPosition);
        stepper1.moveTo(centerPosition);  // Now Move to center
        break;
      case 1:   // Centering
        delay(1000);    // Take a break
        if ( random(0,2) == 0 )
        {
          state = 2;    // Sweep Left
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(rangeLowPosition);
          stepper1.moveTo(rangeLowPosition);
        }
        else
        {
          state = 4;    // Sweep Right
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(rangeHighPosition);
          stepper1.moveTo(rangeHighPosition);
        }
        break;
    case 2:   // Sweeping Left
        state = 3;  // Now Sweep Right
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(rangeHighPosition);
          stepper1.moveTo( rangeHighPosition );
        break;
    case 3:   // Sweeping Right
        state = 1;
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(centerPosition);
          stepper1.moveTo(centerPosition);  // Now Move to center
        break;
    case 4:   // Sweeping Right
        state = 5;
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(rangeLowPosition);
          stepper1.moveTo( rangeLowPosition ); // Now Sweep to the Left
        break;
    case 5:   // Sweeping Left
        state = 1;
          Serial.print("New State ");  
          Serial.print(state);
          Serial.print("  moveTo ");
          Serial.println(centerPosition);
          stepper1.moveTo(centerPosition);  // Now Move to center
        break;
   }
  }  
  //If the stepper still needs to move (distanceToGo() != 0)
  //continue to advance (step) the motor
  stepper1.run();
}

This is how he was looking just before we started giving him skin and built a pedestal…

I decided Dusty will be crouching on top of a small crypt…

The next step was to “corpse” the skeleton. This is my wife’s department. She uses a heat gun and a glue gun to stretch some plastic drop cloth over the skeleton. Then out comes the airbrush, and the new corpse gets a multi-layer color coat and then finished with a little dry-brushing.

Meanwhile, the pedestal gets a coat of paint…

Finally, because we live on a hill and have to put these things on uneven ground (and to protect against wind), I put four pegs on the bottom so I can sink them into the lawn and level the pedestal…

And finally, the finished prop in the yard:

After a couple of nights, we decided to change up the lighting on the new prop, and we also provided a more appropriate paint job on the crypt.