Motion Tracking Head Using 4 PIRs, Servo and Arduino Uno
Updated: Mar 31,2014 - modified program to use PIR only once per HIGH state.
I wanted to make a motion tracker originally using sound sensors but that was too much work and I thought using PIRs would be just like programming on and off switches, simpler. This works pretty fair considering it's utter simplicity, not rocket science. I used 4 PIRs (actually 5 but one wiring harness shorted and I was too lazy to fix it), a servo to turn the head (bird), and an arduino uno to do the heavy number crunching (45 lines of code, see below).
I hate to program, too frustrating but I finally broke down and got an Arduino, man what a cinch. The last chip I played with I had to download Java, and Keil Uvision, and a bunch of other stuff and it took me two or three days just to set up the environment. The Arduino I had everything installed and running the Blink program in minutes. Where was Arduino when I was young?
The tracker works well if you are walking normally past the PIR sensors, if you move slowly it gets a little confused sometimes between two adjacent sensors but ends up shaking its head quickly which is definitely bird like. My algorithm couldn't be simpler, cycle through the PIRs and place the servo where a PIR has just gone HIGH. Suppose it could be made more complex, but what for? NOTE: modified on Mar 31,2014 to address this problem by allowing PIR to be used only once after it goes HIGH so that it doesnt jump back and forth between adjacent positions. Works quite nicely now even with 2.5 second response time.
The PIRs have an on cycle time of about 2.5 seconds at its fastest so if one found some quicker PIRs or wanted to play with the hardware then the tracker would have quicker response time but its pretty good as is. Don't use any slower PIRs or it will just sit there longer before responding. Ideally if the PIR would go HIGH at movement and then immediately go LOW even if there was continued movement then response time would be quicker too, I think, not sure how it would behave frankly.
Used 9mm EPP to hold the PIRs, a tea container to support the servo.
After I had begun building I did see a video where someone did something similar (nothing new under the sun) but his algorithm sounded too complex and frankly I feel mine works better.
Here is a closeup of the Uno board. I just wired all the PIRs in parallel and ran them off the 5v from the Uno, plugged the PIR out wires into 3,4,5,6,7 sockets and servo into 9.
Close up shot of the board:
Here is the code:
#include <Servo.h>
// author: jim demello feb 2014 //
// modified: Mar 31,2014 - added array to allow PIR to be used only once per HIGH state so it doesnt jump back
// and forth between adjacent PIR servo positions.
boolean pirStatus;
Servo servo1;
int servangle = 0; // servo angle variable
int pirNo[] = {3,4,5,6,7}; // pir pin numbers
int pirPrevLow[] = {1,1,1,1,1}; // previously low flag set to true
int pirPrevUsed[] = {0,0,0,0,0}; // track if PIR has been used after going HIGH
int pirPos[] = {10,60,100,140,170}; // positions for servo (0-180)
int curPosPir = 0;
int pirPin = 3;
int ledPin = 13;
void setup(){
Serial.begin(9600);
servo1.attach(9);
for(int i=0;i<4;i++){
pinMode(pirNo[i], INPUT);
}
pinMode(ledPin, OUTPUT);
delay(10000); // calibrate for about 10 seconds
}
////////////////////////////
//Main LOOP
//////////////////
void loop(){
for(int j=0;j<4;j++){ // for each PIR
pirPin=pirNo[j];
pirStatus = digitalRead(pirPin);
if (pirStatus == HIGH) {
digitalWrite(ledPin, HIGH); // turn on led for kicks and to show PIRs are HIGH
if(pirPrevLow[j]) {
if (curPosPir != pirPin && pirPrevUsed[j] == 0) { // if high PIR is different than current position PIR then move to new position
servo1.write(pirPos[j]);
curPosPir = pirPin; // keep current PIR
pirPrevUsed[j] == 1;
}
pirPrevLow[j] = 0; // pir is now not low
}
}
else {
digitalWrite(ledPin, LOW); // turn off the led
pirPrevLow[j] = 1; // pir is now low
pirPrevUsed[j] == 0;
}
} // end j number of pirs loop
}// end infinite loop
Suppose I will post this over at the doilie makers website (instructables.com) too.
Head follows movement based on 4 PIR sensors
- Actuators / output devices: single servo
- Control method: PIR controlled servo via Arduino
- CPU: arduino uno
- Power source: 11.1 3S lipo
- Programming language: Arduinos C
- Sensors / input devices: PIR sensor
- Target environment: maybe Halloween