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




My name is Jason Poel Smith. In my free time, I am an Inventor, Maker, Hacker, Tinker, and all ar...

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.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: 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

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

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

//  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

                                                                                    //calculates ratio of current pin value to average pin value

                                                                                 //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;   }
    {    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

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

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

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

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

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

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

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. 

Halloween Decorations Contest

Second Prize in the
Halloween Decorations Contest

Microcontroller Contest

Participated in the
Microcontroller Contest



    • Indoor Lighting Contest

      Indoor Lighting Contest
    • Stone Concrete and Cement Contest

      Stone Concrete and Cement Contest
    • DIY Summer Camp Contest

      DIY Summer Camp Contest

    38 Discussions


    Question 10 months ago

    I just tried to make this. I’m having no luck. Nothing is working but the lights on the Arduino. Servo does not move. I might have not installed the photoresistors properly?

    4 answers
    xonohDIY Hacks and How Tos

    Reply 9 months ago

    Hi there, I'm not the OP but I just encountered the same problem. I believe I have everything set up correctly, and my code uploaded to the board alright, but no luck. Here is a link to images of my setup, any help would be greatly appreciated!

    DIY Hacks and How Tosxonoh

    Reply 9 months ago

    It looks like you have everything hooked up correctly. Have you checked that your fixed resistor is close to the value of the photo resistor in the lighting that you will have it in?

    xonohDIY Hacks and How Tos

    Reply 9 months ago

    I'm a complete novice here so forgive my stupid questions -- when you say "close to the value of the photo resistor in the lighting that you will have it in" do you mean physically move the resistor or adjust the code?


    2 years ago

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

    1 reply
    DIY Hacks and How Tosengdar

    Reply 2 years ago

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


    4 years ago

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

    1 reply

    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.


    5 years ago on Introduction

    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!


    2 replies

    5 years ago on Introduction

    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

    2 replies

    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.


    5 years ago on Introduction

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


    5 years ago on Introduction

    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?

    1 reply