Introduction: Motion Activated Servo

Picture of Motion Activated Servo
This is a basic motion activated servo that can be used in a wide variety of projects, and it is very simple and easy to make. If you use it creatively, you can do a lot of things with it. For example, I used mine to create a motion activated nerf gun.

Step 1: Materials

Picture of Materials

In order to make this, you will need:

An Arduino.
A PIR motion sensor.
A servo.
Wire.

Step 2: Wiring

Picture of Wiring

The wiring in this Instructable is very simple. The ground pin (GND) on the PIR sensor should be plugged into the Arduino's ground pin, the 5 volt pin (VCC) should be plugged into the Arduino's digital pin 13, and the data pin (OUT) should be plugged into the Arduino's digital pin 12.

The servo's red wire should be plugged into the Arduino's 5 volt pin, the black wire should be plugged into the Arduino's Ground pin, and the signal wire (it was white on my servo) should be plugged into the Arduino's digital pin 4.

The wiring is complete! If you are confused, look at the pictures or ask in the comments.

Step 3: Code

Picture of Code

This code should be uploaded to your Arduino. If you wish, you can open the Serial Moniter in the Arduino IDE in order to view what the Arduino is doing.

To write this code, I basically combined code I found for a PIR sensor (http://playground.arduino.cc/Code/PIRsense) and code for a servo  (http://arduino.cc/en/Tutorial/Sweep), and then made changes wherever I thought it would improve the code.

Code:

/* This code sweeps a servo from 0 degrees to 180 when the PIR sensor detects motion.
   Special thanks goes to the author of the PIR sensor code, whose code helped tremendously
   in the making of this code and Instructable.
   author of PIR sensor code: Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
**/

#include <Servo.h>

Servo myservo;  //creates a servo object
                         //a maximum of eight servo objects can be created

int pos = 0;        //variable to store servo position

//amount of time we give the sensor to calibrate(10-60 secs according to the datasheet)

int calibrationTime = 30;

//the time when the sensor outputs a low impulse
long unsigned int lowIn;        

//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int pause = 5000; 

boolean lockLow = true;
boolean takeLowTime; 

int pirPin = 12;            //digital pin connected to the PIR's output
int pirPos = 13;           //connects to the PIR's 5V pin

void setup(){
  myservo.attach(4);    //attaches servo to pin 4
  Serial.begin(9600);    //begins serial communication
  pinMode(pirPin, INPUT);
  pinMode(pirPos, OUTPUT);
  digitalWrite(pirPos, HIGH);

  //give the sensor time to calibrate
  Serial.println("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(calibrationTime - i);
    Serial.print("-");
    delay(1000);
  }
  Serial.println();
  Serial.println("done");
 
  //while making this Instructable, I had some issues with the PIR's output
  //going HIGH immediately after calibrating
  //this waits until the PIR's output is low before ending setup
  while (digitalRead(pirPin) == HIGH) {
    delay(500);
    Serial.print(".");     
  }
  Serial.print("SENSOR ACTIVE");
}

void loop(){

  if(digitalRead(pirPin) == HIGH){  //if the PIR output is HIGH, turn servo

    /*turns servo from 0 to 180 degrees and back
    it does this by increasing the variable "pos" by 1 every 5 milliseconds until it hits 180
    and setting the servo's position in degrees to "pos" every 5 milliseconds
    it then does it in reverse to have it go back
    to learn more about this, google "for loops"
    to change the amount of degrees the servo turns, change the number 180 to the number of degrees you want it to turn
    **/
    for(pos = 0; pos < 180; pos += 1)  //goes from 0 to 180 degrees
    {                                                 //in steps of one degree
      myservo.write(pos);                   //tells servo to go to position in variable "pos"
      delay(5);                                   //waits for the servo to reach the position
    }
    for(pos = 180; pos>=1; pos-=1)    //goes from 180 to 0 degrees
    {                               
      myservo.write(pos);                  //to make the servo go faster, decrease the time in delays for
      delay(5);                                  //to make it go slower, increase the number.
    }
   
    if(lockLow){ 
      //makes sure we wait for a transition to LOW before further output is made
      lockLow = false;           
      Serial.println("---");
      Serial.print("motion detected at ");
      Serial.print(millis()/1000);
      Serial.println(" sec");
      delay(50);
    }        
    takeLowTime = true;
  }

  if(digitalRead(pirPin) == LOW){      

    if(takeLowTime){
      lowIn = millis();             //save the time of the transition from HIGH to LOW
      takeLowTime = false;    //make sure this is only done at the start of a LOW phase
    }
   
    //if the sensor is low for more than the given pause,
    //we can assume the motion has stopped
    if(!lockLow && millis() - lowIn > pause){
      //makes sure this block of code is only executed again after
      //a new motion sequence has been detected
      lockLow = true;                       
      Serial.print("motion ended at "); //output
      Serial.print((millis() - pause)/1000);
      Serial.println(" sec");
      delay(50);
    }
  }
}

Step 4: Use It.

Once your motion activated servo is completed, you can use it to make a lot of different projects. Be creative here! There's a lot of things you can do with it. I used mine to create a motion activated nerf gun. Here's a couple videos of the motion activated nerf gun.

Comments

Vardhanbatavia007 (author)2017-03-26

Hello,
I want to use this servo for continuous rotation when motion is detected for 20 seconds. Do I need to make any change in the hardware or with the software. Please help where to make a change. I am a newcomer in this field. Please reply.........

giantpair (author)2016-08-25

I have had good luck with this setup using the HC-SR501 but found the HC-SR505 (the mini version) unreliable, either overactive or not working at all. I have tried multiple units and have not tried to modify the code/wiring. Someone PLEASE help me to use the mini!

Jacks how2s (author)giantpair2016-10-22

Just play around with the sensitivity and test the module to see if it is faulty. Also make sure you connect left to GND middle to OUT and right to VCC (look up a data sheet)
All the best,
Jacks How2s ( not author of this project!)

Jacks how2s (author)2016-10-22

I love it

MaheshS59 (author)2016-10-05

thank you so much, u rock

thelaneboy (author)2016-08-14

i need help to code 4 servo motor sweep motion activated by PIR. The 1st motor will sweep and return to its original position when PIR detects motion followed by 2nd motor (sweep motion) , 3rd (sweep motion) and the 4th (sweep motion).

hakim1 (author)2016-07-27

how to add LED and BUZZER. And what is the code and schematic diagram?

HELP.

Topgambling26 (author)2016-05-08

I would like to make a motion activated cat feeder...could this be used for this? We're my cat can paw at an area near feeder and 3-4 pixies of food drop out...

PrimaA (author)2016-02-18

Hi nice project..

Actually i have made similar project like this, but i used 2 PIR sensor. PIR1 i put at 0 degree and PIR2 put at 180 degree. so when movement detected, servo will move to source movement then SIM900A make call. i have done for it all and success for calling, but the problem is why my servo is vibrate and move by itself? if without SIM900A, servo and pir working normally. is it anything wrong? i used 9600 bps..

DorT1 (author)2016-02-08

Nice one,

You could use this free tool for quickly generate schematics and code snippets:

www.circuito.io

giantpair (author)2015-12-29

I have got it working, however only when plugged into the USB. How do I modify the circuit to get it working from a battery?

masonhockey17 (author)2015-12-28

when I try to compile the code for arduino it says there is a compiling error. How can I fix this.

ata123456789 (author)2015-12-05

Hi

I can not transfer the info from PIR cencor to servo. I appreciate any help.

Thank you!

skulpture made it! (author)2015-12-04

Thanks!

https://www.youtube.com/watch?v=NAY9ikZV6lo

https://www.youtube.com/watch?v=NAY9ikZV6lo

Nguyen-erT made it! (author)2015-07-04

I did everything dicribed but it seems to be not working?

Nguyen-erT (author)Nguyen-erT2015-07-04

Please help

Justith99 (author)2014-10-07

Hi!

What would you change in the code to make the servo only go 180 degrees and back once, when triggered by the sensor? I noticed it goes to 180 and back three times when triggered. Thanks!

jim.baker.9847 (author)Justith992015-03-15

Did you ever figure out why the servo loops three times? I'm having the same issue.

I'm experiencing this as well! If anyone could comment on this, it would be really helpful!

SamuelS11 (author)paperisthin2015-06-27

Found it. Edit delay in "//waits for the servo to reach the position" or use this simplified code :

#include <Servo.h>

Servo myservo; //creates a servo object

//a maximum of eight servo objects can be created

int pos = 0; //variable to store servo position

//amount of time we give the sensor to calibrate(10-60 secs according to the datasheet)

int calibrationTime = 30;

int pirPin = 12; //digital pin connected to the PIR's output

int pirPos = 13; //connects to the PIR's 5V pin

void setup(){

myservo.attach(4); //attaches servo to pin 4

Serial.begin(9600); //begins serial communication

pinMode(pirPin, INPUT);

pinMode(pirPos, OUTPUT);

digitalWrite(pirPos, HIGH);

//give the sensor time to calibrate

Serial.println("calibrating sensor ");

for(int i = 0; i < calibrationTime; i++){

Serial.print(calibrationTime - i);

Serial.print("-");

delay(1000);

}

Serial.println();

Serial.println("done");

while (digitalRead(pirPin) == HIGH) {

delay(500);

Serial.print(".");

}

Serial.print("SENSOR ACTIVE");

}

void loop(){

if(digitalRead(pirPin) == HIGH){ //if the PIR output is HIGH, turn servo

for(pos = 0; pos < 170; pos += 1) //goes from 0 to 180 degrees

{ //in steps of one degree

myservo.write(pos); //tells servo to go to position in variable "pos"

delay(50); //waits for the servo to reach the position

}

}

if(digitalRead(pirPin) == LOW){

}

}

nojo127 (author)2015-06-25

Very helpful.

JulioM5 (author)2015-06-13

HI Seraine,

I've follow your instructions and seem to be getting close to my desired intent. The problem I am running into is like in your video, the servo motor is constantly rotating and does not come to a complete stop before being triggered again by the motion sensor. Perhaps you can help me with this?

I am attempting to implement a kinetic skin system to my final architecture thesis project and would appreciate any help. Thanks!

Brezorojo (author)2015-05-12

Thanks so much for this, I couldn't work out how to combine the Servo code with the PIR code. All is now clear! I have made a useless object which moves kind of flower things when someone approaches.

MatthewS4 (author)2014-09-15

Thank you for posting this! I am having one problem with it and I hope you can help me understand what I'm doing wrong. Everything starts fine, the sensor triggers the servo as it's supposed to, but the servo never stops. I have isolated the sensor so the motion of the servo isn't setting it off. Any ideas? Thanks again!

swordst (author)2014-08-30

Made this for my Halloween owl amazing, I am trying to add led blinking program to it but keep running into problems says voids are wrong and loop is wrong. You are an amazing programmer can not wait to see what the future holds for you

seraine (author)swordst2014-08-30

How do you want the led to blink? Do you want it to blink when the servo is moving, or something else? Could I see your code?

swordst (author)seraine2014-08-30

Seraine
After playing with your program I added the lights
Thank you for the reply tho

Joekevdv (author)2014-06-03

Really nice tutorial. I have a problem because the PIR is too sensitive, do you have the same problem?

Oliverhall (author)2014-04-02

Nice tutorial!

You can get the hc-sr501 PIR motion sensor for cheap here: http://voltatek.com/en/sensors/69-motion-sensor-m...

Abhiman (author)2014-03-03

How to connect it with servo ?

seraine (author)Abhiman2014-03-03

Copy and pasted from step two:
The servo's red wire should be plugged into the Arduino's 5 volt pin, the black wire should be plugged into the Arduino's Ground pin, and the signal wire (it was white on my servo) should be plugged into the Arduino's digital pin 4.

us241098 (author)2013-07-05

cool bro !!! could you provide me a little i wanna light two bulbs on detecting motion could u plzz give me a code , i am a newbie

EET1982 (author)2013-04-17

Pretty cool man. Thanks for the 'ible.

cridds (author)2013-03-13

Looking for some help with a project I am thinking of undertaking. I want to attempt this with a couple of mods - https://www.instructables.com/id/Squirt/step2/The-circuit/ (small pic only) but this one uses a 12v supply for the servo. Most servos I have seen are 5v. Am I correct in thinking I could move the servo power wire from the 12v as shown to the 5v on the board to power it and still maintain the functionality?

Any help would be appreciated.

seraine (author)cridds2013-03-13

Most servos should be able to be powered by the 5v pin on the Arduino, so you should be fine. That's how mine was powered. However, if you connect multiple devices that draw as much current as a servo to your Arduino or if your servo uses an unusually high amount of current, you could potentially fry the Arduino, so beware of that. Also, you can't power a servo through a digital pin on the Arduino by turning the pin HIGH, as the pin can't give enough current. Other than that, I can't think of any problems.

kambob13 (author)2013-03-04

Hi, how do I connect multiple servos, each triggered by individual sensors

seraine (author)kambob132013-03-05

I am assuming you want to have multiple servos, and each one controlled by its own individual sensor. I will address the electrical changes you need first, and then move onto programming.

The positive pins of all of the PIR sensors will need to be connected together, and the negative pins of all of the PIR sensors will need to be connected together. Then connect the positive pins to the Arduino's 5V pin, and the negative pins to the Arduino's GND pin. Finally, connect the signal pin from each individual sensor to its own Arduino pin. For example, the pin from your first sensor will be connected to Arduino pin 11, the pin from the second to pin 12, etc.

You will need to do something similar with the servos. However, you cannot connect the positive and negative pins to the Arduino's 5V and GND pins, because you will probably draw too much current and potentially fry the Arduino. Instead, you will need to connect the positive and negative pins to the positive and negative wires of a 5 volt power source (three AA batteries connected in series would probably work). Then connect the negative wire of the power source to the Arduino's GND pin. This is necessary because the electrical signal from the Arduino has to be able to return to the Arduino, and if they weren't connected, the signal wouldn't do anything.

As far as programming goes, you will need to start by attaching more pins for the new sensors and servo. For example, this

int pirPin = 12
Servo myServo;

void setup() {

myServo.attach(4);
pinMode(pirPin, INPUT);

}


would be become this

int pir1 = 11;
int pir2 = 12;

Servo servo1;
Servo servo2;

void setup() {

servo1.attach(4);
servo2.attach(5);

pinMode(pir1, INPUT);
pinMode(pir2, INPUT);

}

You will also need to change the if loops. For example, this

if(digitalRead(pirPin) == HIGH){
for(pos = 0; pos < 180; pos += 1)
{
myservo.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1)
{
myservo.write(pos);
delay(5);
}
if(lockLow){

lockLow = false;
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
delay(50);
}


Would have to become something like this

if(digitalRead(pir1) == HIGH){

boolean pirState1 = true;

if(lockLow){

lockLow = false;
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
delay(50);
}
takeLowTime1 = true;
}

if(digitalRead(pir2) == HIGH){

boolean pirState2 = true;

if(lockLow){

lockLow = false;
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
delay(50);
}
takeLowTime2 = true;
}

if (pirState1 == true) {
for(pos = 0; pos < 180; pos += 1) {
servo1.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1) {
servo1.write(pos);
delay(5);
}
}
if (pirState2 == true) {
for(pos = 0; pos < 180; pos += 1)
{
servo2.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1)
{
servo2.write(pos);
delay(5);
}
}

I hope this helps you with your design, but beware, you will probably need to modify the code to account for whatever I missed. If you need further help, feel free to ask.

seraine (author)seraine2013-03-05

I just realized that the loop code I wrote won't work very well. The problem with it is that it would sweep one servo, then sweep the next, etc. In order to have them all sweeping at the same time, it would have to look something like this.

boolean pirState1 = false;
boolean pirState2 = false;

if(digitalRead(pir1) == HIGH){

pirState1 = true;

if(lockLow){

lockLow = false;
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
delay(50);
}
takeLowTime1 = true;
}

if(digitalRead(pir2) == HIGH){

pirState2 = true;

if(lockLow){

lockLow = false;
Serial.println("---");
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
delay(50);
}
takeLowTime2 = true;
}

if (pirState1 == true && pirState2 == true) {
for(pos = 0; pos < 180; pos += 1) {
servo1.write(pos);
servo2.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1) {
servo1.write(pos);
servo2.write(pos);
delay(5);
} else if (pirState1 == true) {
for(pos = 0; pos < 180; pos += 1) {
servo1.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1) {
servo1.write(pos);
delay(5);
} else if (pirState2 == true) {

for(pos = 0; pos < 180; pos += 1) {
servo2.write(pos);
delay(5);
}
for(pos = 180; pos>=1; pos-=1) {

servo2.write(pos);
delay(5);

} else {
}


This code is probably very inefficient, but it gives the gist of what I am thinking of.

kambob13 (author)2013-03-05

thanks alot. I want to build an art installation that reacts when someone walks by, i'm thinking of using about 10 servos

danny59 (author)2013-02-22

This is nice and simple, yet effective. Your a very smart young man, and I wish I would have started my electronics hobby when I was your age. I didn't start until I turned 50, (now 53) and it amazes me at how smart some young inventors can be. Great job and keep up the good work, or should I say play :-)

seraine (author)danny592013-03-05

Thanks!

danny59 (author)seraine2013-03-05

You are welcome.

About This Instructable

62,706views

121favorites

License:

Bio: I am 14 years old, and I'm interested in many different things - electronics, chemistry, robotics, basketball, chess and much, much more.
More by seraine:Arduino Ticking Time BombMotion Activated ServoLow Voltage Electrical Igniters
Add instructable to: