Introduction: Halloween Props That Turn to Look at You As You Walk By

Picture of Halloween Props That Turn to Look at You As You Walk By

Interactive Halloween props are always fun and they are surprisingly easy to make. This year I designed a simple system that rotates a skull to face you and follows you movements as you walk by.

To accomplish this I used light sensors to detect a person's shadow. An Arduino microcontroller then calculates where they are standing and activates a servo that turns the skull to face them. When they move, the skull turns to follows them.

Step 1: Select a Halloween Prop to Use

Picture of Select a Halloween Prop to Use

The first thing that you need to do is select a Halloween prop that will turn and follow people walking by. Look for props that are both creepy and light weight. I chose to use a foam skull but there are a lot of other props that can also work. Use your imagination.

Step 2: The Light Sensors

Picture of The Light Sensors

This project uses an array of light sensors to detect where a person is standing. I used CdS photoresistors but you could also use phototransistors.

When using photoresistors, you need to be aware that CdS photoresistors can vary quite a lot in their output characteristics. Even if you purchase a set of photoresistors that are the same type from the same manufacturer, the output of one photoresistor can still be very different from the next. There are several ways that you can compensate for this. You could change the other circuit components to match the photoresistors in the desired lighting. Another option is to change the Arduino code to compensate for different values of the photoresistors. You can add in a simple adjustment factor to any inputs, or you can write code that calibrates itself by referencing its average value. If all else fails you can purchase more photoresistors than you need in the hopes that you can get a group of them with approximately the same output characteristics.


 

Step 3: The Microcontroller

Picture of The Microcontroller

The brain of this project is the Arduino UNO microcontroller. This board has six analog input ports that are used to measure the voltages coming from the light sensors. The Arduino monitors these voltages over time and calculates which sensor experiences the greatest drop in voltage. This typically results from a person walking in front of that sensor and casting a shadow on it. The arduino then activates a servo to turn the skull to face that sensor and the person standing in front of it.

Step 4: The Code

Picture of The Code

//  Here is the Arduino code that I used.
// Open up the Arduino environment. Then copy and paste it into a new sketch.
// Then upload the code to the Arduino board.



#include <Servo.h>
Servo myservo;                                         //create servo object to control a servo

int ResetTimer=0;                                      //sets delay to reset position
int GoalPosition=3;                                    //stores the goal postion (1-5) where the person is standing
int GoalPositionDegrees;                               //stores the goal position in degrees (30-150)
int CurrentPositionDegrees=90;                         //stores the current position in degrees (30-150)
int AveragingSpeed=100;                                //sets how quickly the average values adjust (a lower value changes average value quickly)                                                                           //quickly. A value of 100 changes the average value slowly
                                                       // his effectively sets the speed at which the sensors recalibrate themselves to changing light conditions
int PinOneCurrent;                                     //stores current value of pins 1-5
int PinTwoCurrent;
int PinThreeCurrent;
int PinFourCurrent;
int PinFiveCurrent;

float PinOneAverage;                                    //stores the average value of pins 1-5
float PinTwoAverage;
float PinThreeAverage;
float PinFourAverage;
float PinFiveAverage;

float RatioPinOne=0.00;                                 //stores the ratio of current pin value to average pin value
float RatioPinTwo=0.00;
float RatioPinThree=0.00;
float RatioPinFour=0.00;
float RatioPinFive=0.00;

float Threshold=0.95;                                    //sets minimum threshold for sensors

void setup()
{
myservo.attach(13);                                      //attaches servo to digital pin 13


PinOneAverage = analogRead(1);                           //reads from sensors to set initial average pin value
PinTwoAverage = analogRead(2);
PinThreeAverage = analogRead(3);
PinFourAverage = analogRead(4);
PinFiveAverage = analogRead(5);
}




void loop()
{
                                                                                    //read analog pins 1-5 and set the result as current value  
   PinOneCurrent= analogRead(1);                                               
   PinTwoCurrent= analogRead(2); 
   PinThreeCurrent= analogRead(3);
   PinFourCurrent= analogRead(4);
   PinFiveCurrent= analogRead(5);

                                                                                    //adjust average pin values
   PinOneAverage=PinOneAverage+(PinOneCurrent-PinOneAverage)/AveragingSpeed;
   PinTwoAverage=PinTwoAverage+(PinTwoCurrent-PinTwoAverage)/AveragingSpeed;
   PinThreeAverage=PinThreeAverage+(PinThreeCurrent-PinThreeAverage)/AveragingSpeed;
   PinFourAverage=PinFourAverage+(PinFourCurrent-PinFourAverage)/AveragingSpeed;
   PinFiveAverage=PinFiveAverage+(PinFiveCurrent-PinFiveAverage)/AveragingSpeed;

                                                                                    //calculates ratio of current pin value to average pin value
   RatioPinOne=(float)PinOneCurrent/PinOneAverage;
   RatioPinTwo=(float)PinTwoCurrent/PinTwoAverage;
   RatioPinThree=(float)PinThreeCurrent/PinThreeAverage;
   RatioPinFour=(float)PinFourCurrent/PinFourAverage;
   RatioPinFive=(float)PinFiveCurrent/PinFiveAverage;


                                                                                 //determine which ratio is the largest and sets the goal position
                                                                                 //set goal position

   if (RatioPinThree < Threshold && RatioPinThree < RatioPinOne && RatioPinThree < RatioPinTwo && RatioPinThree < RatioPinFour && RatioPinThree < RatioPinFive)
    {    GoalPosition=3;     
         ResetTimer=0;   }
   else if (RatioPinOne < Threshold && RatioPinOne < RatioPinTwo && RatioPinOne < RatioPinThree && RatioPinOne < RatioPinFour && RatioPinOne < RatioPinFive)
    {    GoalPosition=1;     
         ResetTimer=0;   }
   else if (RatioPinTwo < Threshold && RatioPinTwo < RatioPinOne && RatioPinTwo < RatioPinThree && RatioPinTwo < RatioPinFour && RatioPinTwo < RatioPinFive)
    {    GoalPosition=2;     
         ResetTimer=0;   }
   else if (RatioPinFour < Threshold && RatioPinFour < RatioPinOne && RatioPinFour < RatioPinTwo && RatioPinFour < RatioPinThree && RatioPinFour < RatioPinFive)
    {    GoalPosition=4;     
         ResetTimer=0;   }
   else if (RatioPinFive < Threshold && RatioPinFive < RatioPinOne && RatioPinFive < RatioPinTwo && RatioPinFive < RatioPinThree && RatioPinFive < RatioPinFour)
    {    GoalPosition=5;     
         ResetTimer=0;   }
   else if (ResetTimer > 100)                                     //after delay resets to position 3
    {    GoalPosition=3;  
         ResetTimer=0;   }
   else
    {    ResetTimer=ResetTimer+1;  }


GoalPositionDegrees=GoalPosition*25+15;                               //converts the goal position to degrees
         
myservo.write(GoalPositionDegrees);                             //sets the servo position according to the scaled value

delay(30);                                                         //sets how quckly the servo turns (lower numbers turn more quickly)
                                 

}

Step 5: Attach the Servo to Your Prop and a Base

Picture of Attach the Servo to Your Prop and a Base

To be able to turn your prop you need to attach it to a servo motor. How you attach your prop to the servo will depend on the geometry of your prop. Try to find an area where the servo can be easily hidden. If people can see the servo, it will be less impressive. 

The skull that I am using has a flat recessed area on the bottom behind the jaw. This made a convenient place to mount the body of the servo. To attach the servo to the skull I applied a generous amount of hot glue to the bottom of the servo and pressed the two together for several minutes. Then I applied more hot glue around the edges.

To mount the skull and servo, I attached the rotor of the servo to piece of cardboard that will act as the base. First make sure that your servo is in the center position. This will make sure that it is oriented properly and can go through the full range of motion. I applied hot glue to the center of the cardboard and to the rotor. Then I pressed the two together for several minutes until the glue hardened. To make it a little more secure, I applied more glue around the edges. 

Step 6: Setup the Light Sensor Array on a Breadboard

Picture of Setup the Light Sensor Array on a Breadboard

To assemble the photosensor array each CdS photoresistors is wired in series with a fixed 10kohm resistor. The fixed resistor is connected to GND and the photoresistor is connected to 5VDC . The center pin is connected to an analog input of the arduino. This forms a light sensitive voltage divider. As the light changes, so does the resistance of the photoresistor. This results in a change in voltage at the center pin that is detected by the microcontroller. I used five of these sensors in this project. But you can use as many sensors as you have analog input pins on your Arduino.

First I assembled the sensors on a breadboard. I ran a jumper wire from the 5V pin on the Arduino to one of the power rails on the breadboard. Then I ran a jumper wire from the GND pin on the Arduino to the other power rail. Then I added the photoresistors and 10k resistors between the power rails as shown in the picture above. Then I added a jumper wire from the center pins of each sensor to the analog input pins 1-5 on the Arduino.

Step 7: Attach the Servo to the Breadboard and the Arduino

Picture of Attach the Servo to the Breadboard and the Arduino

Now you need to connect the servo to the Arduino. The servo has three wires. The ground wire is typically black or brown. This should be connected to one of the GND pins on the Arduino. The signal wire is typically yellow, orange or white. This should be connected to one of the digital pins on the Arduino. The positive power wire is typically red. This needs to be connected to the 5V pin from the Arduino. Unfortunately there is only one 5V pin on the Arduino and that is already being used to power the light sensors. So you should connect this wire to the positive positive power rail on the breadboard.

Step 8: Test the System

Picture of Test the System

Now you need to test the system to make sure that it is working properly. 

Plug the Arduino into your computer and upload the code. If everything wired up correctly, the skull should turn to face one of five positions when you cover the photoresistors with your hand. These five positions should correspond to the five photoresistors.

If the skull is facing the opposite direction from the sensor that you are covering, you can correctly this by switching which analog pins the jumper wires are connected to.

You will probably need to make some adjustments to the code to fine tune how it performs. But that can wait until everything is setup in the final location.

Step 9: Add Extension Wire for Each Photoresistor

Picture of Add Extension Wire for Each Photoresistor

In order to be able to mount the photoresistors in their final locations, you need to add extension wires to them.

Cut ten pieces of thin insulated wire that are each several feet long. Then strip the insulation off the ends. You can use individual wires or multi-wire bundle such as a computer connector cable. Remove one of the photoresistors from the breadboard. Then take two of the wires and connect one end of each piece to the locations on the breadboard where the photoresistor leads where inserted. Then connect the other ends to the leads of the photoresistor. For the best connection, you should solder them together.

After connecting the wires you should insulate the contacts. You can do this with either heat shrink tubing or tape. Repeat this process for each of the other photoresistors. Doing them one at a time helps to avoid crossed wires. 

Step 10: Mount Everything in Its Final Location

Picture of Mount Everything in Its Final Location

Now it is time to setup everything in its final location. The ideal location for this is a shelf that is between waist height and head height. Place the skull on top of the shelf. If possible, use fabric to cover up the base and to help hide the servo.

Mount the photoresistors on the bottom side of the shelf along the front edge. The easiest way to do this is to just stick it in place with tape. Run the wires to a nearby place where you can hide the Arduino and the breadboard. Adding other decorations can help to hide the wires.

To power the system, you can run a USB cable to a nearby computer or you can use a 5VDC adapter that is plugged into a wall outlet or extension cord.

Step 11: Make Adjustments to the Code

Picture of Make Adjustments to the Code

The code that I included has several variables that you can change to adjust the performance of the skull. You can adjust the sensitivity of the sensors. You can change how quickly the system re-calibrates itself to changing light conditions. You can set the time delay before the skull resets its position. Try making adjustments until it performs the way that you like. 

Comments

engdar (author)2016-10-20

hey, is there a certain min characteristics for the servo? I have this one:is it strong enough to rotate a paper prop?

It all depends on your specific prop and servo. The best way to find out is to try it out.

tomoguisuru (author)2014-10-14

awesome project. my six year old daughter and I had fun making this one.

Awesome. Thanks for sharing.

nodoubtman (author)2014-09-30

Hi! Nice project :)

What happens if you close completly the lights?

thanks!

marC:)

This project requires a direct light source in order to work. You could make something similar that would work in the dark, but that would require infrared LEDs and receivers.

mlesage (author)2014-08-04

Hi! I would like to know if it's possible to do this project with an HC-SR04 ultrasonic proximity? I want to use that project on the Halloween day, outdoor at night, so the photoresistor should have some problems to detect the shadow!

Thanks!

It will probably work as long as the signal is 5 volts or less

Nice! I'll try it!!! (When I will get my HC-SR04 from china! lol! Thanks Ebay!!


Thanks!! :)

Kenshow6873 (author)2014-07-28

Hey really liked this project so much that i just finished making my own copy of it however it keeps spazzing out every time i plug it in, i use the original code but i don't know where exactly where to adjust it within the code (if that makes sense). I want it to just move slowly at a constant pace like the one in your youtube video . I also am using 5 sensors instead of 3. Here what it looks like

You can adjust the "threshold" variable. You may need to create a separate threshold variable for each sensor. You can also adjust the averaging speed. Another thing that will help is moving the sensors farther apart. You don't want the shadow to hit more than one sensor at a time.

So if i increase the threshold hold it should help?

artaex (author)2014-05-25

This is a cheap solution, but if you want highly accurate positioning you could use a Kinect sensor.

novianwf (author)2014-03-15

Hi, I try made this project using Arduino promini and LDR. It reach at goal point 1, but it cannot back to goal point (or reset point) and cannot reach the other goal point.
Can you help me please?

You may need to adjust the sensitivity of the light sensors in the code. Or you may need to change the values of the resistors.

novianwf (author)2014-03-15

Hi, I try made this project using Arduino promini and LDR. It reach at goal point 1, but it cannot back to goal point (or reset point) and cannot reach the other goal point.
Can you help me please?

ray74 (author)2013-11-27

Awesome.

johnhr (author)2013-10-26

Hi, I can't get the code to run! It says, error: expected constructor, destructor, or type conversion before 'int'
In function 'void loop()';
error: 'PinOneCurrent' was not declared in this scope
Can you help please, thanks

I don't know, I just compiled it and it ran fine.

Hi, Thanks for your reply, got it sorted now, you were right, it didn't copy and paste properly.
Sorry for the trouble
Johnhr

sithdeath (author)johnhr2013-10-27

Something must not have copied properly. Its no biggie, just make sure the following is declared before void setup() {
int PinOneCurrent;

And after void loop() {
PinOneCurrent= analogRead(1);

Good luck :-)

David Bronstetter (author)2013-10-17

My Wife love's projects & with Halloween coming up she'll love this stuff. I'm glad I stumbled across this page.,love it .

markmcg (author)2013-10-13

Great instructable! I tried this today and the servo just makes small motions back / forth (maybe 1/8") it doesn't seem to respond to covering up the CDS photosensors, any ideas?

Start by changing around the photoresistors to see if that does anything. Then try changing some of the values in the code like the averaging speed.

DragonDon (author)2013-10-06

Creepy! Love it!

slipstream (author)2013-09-27

Very cool and simple. I Have been wanting to do something like this for a while. I want to place outside (for day and night use) and I'm thinking that the photoresistors will not work (tell me if I'm wrong). So I was wondering if a Parallax PIR Sensor would be a better option.

Photoresistors will not work at night without an external light source. PIR can work, but that is a little more expensive.

Thanks for this cool project as I have been trying to figure out how to get this done for a couple of weeks now :-(. I have tried to use 3 Parallax PIR's, and since I have to use delay(), the servo will not turn in real time as yours does. I tried to modify your code to work with the PIR's, but when I tested the output of the sensor using a multimeter, when the sensor turns off, for a moment the voltage jumps to 7V, and I don't want to fry my Uno :-p. Any suggestions would be great. Thanks

The trouble with a PIR is that the output is HIGH when there is motion or LOW when there is not motion. It doesn't give values relative to how much motion. The best that you can do is have the skull turn to face the sensor that most recently detected motion. Another option is to use just two sensors and have the center position be the default that it will turn to when the sides don't detect motion.

Thank you for the quick response. I will give that a shot tomorrow as I currently tried using 3 PIR sensors... I will also try to see if I can get it working with 2 or 3 Ping sensors, since I have the ones which have both an echo and a trigger output, and let u know...

sithdeath (author)sithdeath2013-09-30

ok, so maybe when I have more time to mess with the PIR's, I will... In the meantime, I modified your code to include 2 Led's that will go on when the light sensors are triggered...

// Here is the Arduino code that I used.
// Open up the Arduino environment. Then copy and paste it into a new sketch.
// Then upload the code to the Arduino board.
// Based upon code from the following. Thank you
// https://www.instructables.com/id/Halloween-Props-That-Turn-to-Look-at-You-as-you-Wa/
// The only addition is that 2 LED's will now turn on when the light sensors are triggered, and go off after.

#include
Servo myservo; //create servo object to control a servo

#define led1 9
#define led2 10

int ResetTimer=0; //sets delay to reset position
int GoalPosition=3; //stores the goal postion (1-5) where the person is standing
int GoalPositionDegrees; //stores the goal position in degrees (30-150)
int CurrentPositionDegrees=90; //stores the current position in degrees (30-150)
int AveragingSpeed=100; //sets how quickly the average values adjust (a lower value changes average value quickly) //quickly. A value of 100 changes the average value slowly
// his effectively sets the speed at which the sensors recalibrate themselves to changing light conditions
int PinOneCurrent; //stores current value of pins 1-5
int PinTwoCurrent;
int PinThreeCurrent;
int PinFourCurrent;
int PinFiveCurrent;

float PinOneAverage; //stores the average value of pins 1-5
float PinTwoAverage;
float PinThreeAverage;
float PinFourAverage;
float PinFiveAverage;

float RatioPinOne=0.00; //stores the ratio of current pin value to average pin value
float RatioPinTwo=0.00;
float RatioPinThree=0.00;
float RatioPinFour=0.00;
float RatioPinFive=0.00;

float Threshold=0.95; //sets minimum threshold for sensors

void setup()
{
myservo.attach(13); //attaches servo to digital pin 13

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);

PinOneAverage = analogRead(1); //reads from sensors to set initial average pin value
PinTwoAverage = analogRead(2);
PinThreeAverage = analogRead(3);
PinFourAverage = analogRead(4);
PinFiveAverage = analogRead(5);

}

void loop()
{
//read analog pins 1-5 and set the result as current value
PinOneCurrent= analogRead(1);
PinTwoCurrent= analogRead(2);
PinThreeCurrent= analogRead(3);
PinFourCurrent= analogRead(4);
PinFiveCurrent= analogRead(5);
//adjust average pin values
PinOneAverage=PinOneAverage+(PinOneCurrent-PinOneAverage)/AveragingSpeed;
PinTwoAverage=PinTwoAverage+(PinTwoCurrent-PinTwoAverage)/AveragingSpeed;
PinThreeAverage=PinThreeAverage+(PinThreeCurrent-PinThreeAverage)/AveragingSpeed;
PinFourAverage=PinFourAverage+(PinFourCurrent-PinFourAverage)/AveragingSpeed;
PinFiveAverage=PinFiveAverage+(PinFiveCurrent-PinFiveAverage)/AveragingSpeed;

//calculates ratio of current pin value to average pin value
RatioPinOne=(float)PinOneCurrent/PinOneAverage;
RatioPinTwo=(float)PinTwoCurrent/PinTwoAverage;
RatioPinThree=(float)PinThreeCurrent/PinThreeAverage;
RatioPinFour=(float)PinFourCurrent/PinFourAverage;
RatioPinFive=(float)PinFiveCurrent/PinFiveAverage;


//determine which ratio is the largest and sets the goal position
//set goal position

if (RatioPinThree < Threshold && RatioPinThree < RatioPinOne && RatioPinThree < RatioPinTwo && RatioPinThree < RatioPinFour && RatioPinThree < RatioPinFive)
{ GoalPosition=3;
LedOn();
ResetTimer=0; }
else if (RatioPinOne < Threshold && RatioPinOne < RatioPinTwo && RatioPinOne < RatioPinThree && RatioPinOne < RatioPinFour && RatioPinOne < RatioPinFive)
{ GoalPosition=1;
LedOn();
ResetTimer=0; }
else if (RatioPinTwo < Threshold && RatioPinTwo < RatioPinOne && RatioPinTwo < RatioPinThree && RatioPinTwo < RatioPinFour && RatioPinTwo < RatioPinFive)
{ GoalPosition=2;
LedOn();
ResetTimer=0; }
else if (RatioPinFour < Threshold && RatioPinFour < RatioPinOne && RatioPinFour < RatioPinTwo && RatioPinFour < RatioPinThree && RatioPinFour < RatioPinFive)
{ GoalPosition=4;
LedOn();
ResetTimer=0; }
else if (RatioPinFive < Threshold && RatioPinFive < RatioPinOne && RatioPinFive < RatioPinTwo && RatioPinFive < RatioPinThree && RatioPinFive < RatioPinFour)
{ GoalPosition=5;
LedOn();
ResetTimer=0; }
else if (ResetTimer > 100) //after delay resets to position 3
{ GoalPosition=3;
LedOn();
ResetTimer=0; }
else
{ ResetTimer=ResetTimer+1;
digitalWrite(led1,LOW);
digitalWrite(led2,LOW);
}


GoalPositionDegrees=GoalPosition*25+15; //converts the goal position to degrees

myservo.write(GoalPositionDegrees); //sets the servo position according to the scaled value

delay(30); //sets how quckly the servo turns (lower numbers turn more quickly)


}

void LedOn() {
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
}

bryan3141 (author)2013-09-29

Hmmm...I like this, but I'm thinking that it's time to revisit the old plastic skull model that you assemble and go with either red LEDs or eyeballs and make them face the person instead. should be able to fit most of the mechanicals inside the skull kit.

poofrabbit (author)2013-09-26

This is cool nicely done!

About This Instructable

45,953views

378favorites

License:

Bio: My name is Jason Poel Smith I am a Community Manager here at Instructables. In my free time, I am an Inventor, Maker, Hacker, Tinker ... More »
More by DIY Hacks and How Tos:36 Things to Cook in a Coffee MakerHow to Make a Festivus PoleAdd Wings to an Infant's Halloween Costume
Add instructable to: