Introduction: Motion Activated Servo
Step 1: Materials
In order to make this, you will need:
An Arduino.
A PIR motion sensor.
A servo.
Wire.
Step 2: 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
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);
}
}
}
48 Comments
Question 1 year ago
How to give a pause for few sec after it has reached 180 degree
9 years ago on Introduction
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!
Reply 4 years ago
Put a buffer between (cardboard) or tell it to stop pir read while performing action and give a little extra time.
Reply 3 years ago
Im having the same problem and im new at coding, do you mind going through the code and changing it? i would highly apreciate it
4 years ago on Step 3
Hi, I’m trying the code above, but some error message shows up I cannot sort out. Can you help please ?! Thanks
4 years ago on Step 3
Hi, I tried, but the code keeps coming up with error messages, no matter how I try to correct it, it doesn’t seem to work. And if it would I would like to connect 4 servos fir 1 sensor. Please help! It’s urgent!!!
10 years ago on Introduction
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
Reply 4 years ago
Read the code for blink in the library. This should give you the tools need to adjust.
7 years ago
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..
Reply 4 years ago
I have had power issues cause this if your using the large servo try useing a dedicated power source not the board.
6 years ago
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.........
Reply 4 years ago
You want continuous sweeps or rotation.
Sweeping you adjust your coding for an "until"
So It won't stop until a button is pressed.
Rotation you would need a modified servo or switch to an electric motor.
Question 4 years ago
Hi good day.
Im using pir + servo(SG90) as a automated door, like in the mall but a mini and cheaper version. I just want to ask for your help in coding.
The scenario is, when the PIR SENSOR detects motion, the door opens BUT it closes after 5 seconds(5 seconds was based on the adjusted trimmer of the PIR).
Now, the condition is, when the PIR detects someone and he/she is staying at the opening of the door, the door should remain open.
Can you please help me figure out the logic behind that automated door? where as long as im staying in the front of the door, the servo/door SHOULD still remain open and it only CLOSES when i walk pass the door or no any other motion is detected.
Please :(
This is my code and i know im missing some logic in this.
#include <Servo.h> // Library for Servo
Servo myservo; // Name of my Servo
int led = 13;
int sensor = 2; // Sensor is connected to D2
int state = LOW; // Initial value for variable state is low
int val = 0; // Initial value for variable val is 0
void setup() {
pinMode(led, OUTPUT);
myservo.attach(9); // Servo is connected to D9
pinMode(sensor, INPUT); // D2 is set as a Input
Serial.begin(9600); // Start for Serial Communication
}
void loop() {
val = digitalRead(sensor);
if(val==HIGH){
digitalWrite(led, HIGH);
myservo.write(60);
if (state == LOW){
Serial.println("Motion Detected");
state = HIGH;
}
}
else {
digitalWrite(led, LOW);
myservo.write(180);
if(state == HIGH){
Serial.println("Motion Stopped");
state = LOW;
}
}
delay(10);
}
Answer 4 years ago
In a normal door you use a photo laser to keep a door open a pir only reads motion then resets to the new perimeters if you stay still a photo cell takes a recorded image and won't reset tell the image is returned to normal
7 years ago
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!
Reply 7 years ago
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!)
7 years ago
I love it
7 years ago
thank you so much, u rock
7 years ago
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).
7 years ago
how to add LED and BUZZER. And what is the code and schematic diagram?
HELP.