Go Down

Topic: Turret design from Portal - PIR triggered PING reading with servo motion (Read 422 times) previous topic - next topic


Reference: https://www.youtube.com/watch?v=7Z0CRfBR7MY

Motion triggers a PIR sensor, which in turn triggers a PING sensor to look for an obstacle within 2 feet.

If no object is found, the servo will start rotating and do continuous sweep until the PING sensor finds an object within the predetermined frame of distance. The turret then locks on and does other functions (LED turns on, audio plays).

In my design, I have an HC-SR04 ultrasonic sensor instead of a PING sensor. Also, two servos operate in pan-tilt fashion. Instead of 2 feet, i set a distance of 10 units.

My problem is that the ultrasonic sensor will only do continuous reading if the max allowed distance read is smaller than 10 units (servos stop due to target lock on).

Above 10 units of distance, the servos rotate, looking for a target, but only 1 reading is done by the ultrasonic sensor. Just as one itch of movement triggers the PIR sensor.

How is it possible to have repeated ultrasonic reading while the servos rotate? Unless the target is within 10 units at the time of activation, the turret is not able to find a target.

#include <Servo.h>

Servo myservoy;  //creates a servo object
Servo myservox;
                         //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 = 10;

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

// defines pin numbers for ultrasensor
const int trigPin = 11;
const int echoPin = 10;

// defines variables
long duration;
int distance;

void setup(){
  Serial.begin(9600);    //begins serial communication
  pinMode(pirPin, INPUT);
  pinMode(pirPos, OUTPUT);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  digitalWrite(pirPos, HIGH);

  //give the sensor time to calibrate
  Serial.println("calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(calibrationTime - i);
  //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) {
  Serial.print("SENSOR ACTIVE");

void loop(){

  while(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


    // Clears the trigPin
    digitalWrite(trigPin, LOW);
    // Sets the trigPin on HIGH state for 10 micro seconds
    digitalWrite(trigPin, HIGH);
    digitalWrite(trigPin, LOW);
    // Reads the echoPin, returns the sound wave travel time in microseconds
    duration = pulseIn(echoPin, HIGH);
    // Calculating the distance
    distance= duration*0.034/2;
    // Prints the distance on the Serial Monitor
    Serial.print("Distance: ");

    if(distance > 10){
      for(pos = 90; pos < 180; pos += 1)  //goes from 0 to 180 degrees
      {                                                 //in steps of one degree
        myservoy.write(pos);                   //tells servo to go to position in variable "pos"
        delay(20);                                   //waits for the servo to reach the position
      for(pos = 180; pos>=1; pos-= 1)    //goes from 180 to 0 degrees
        myservoy.write(pos);                  //to make the servo go faster, decrease the time in delays for
        delay(20);                                  //to make it go slower, increase the number.
      for(pos = 0; pos < 180; pos += 1)  //goes from 0 to 180 degrees
      {                                                 //in steps of one degree
        myservoy.write(pos);                   //tells servo to go to position in variable "pos"
        delay(20);                                   //waits for the servo to reach the position
      for(pos = 180; pos > 90; pos -= 1)

    if(distance <= 10){
      //makes sure we wait for a transition to LOW before further output is made
      lockLow = false;           
      Serial.print("motion detected at ");
      Serial.println(" sec");
    takeLowTime = true;

  if(digitalRead(pirPin) == LOW){     

      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");


Motion triggers an IR sensor
No, it doesn't. An IR sensor detects IR emissions. They can be present when there is no motion, or not present when there is motion.

A PIR sensor is a different device, and does detect motion, but only of warm bodies.

Instead of 2 feet, i set a distance of 10 units.
Quarts? Fathoms? Light years? 10 units is a useless statement.

THINK about what you want to do. You want to move one servo a little bit. You want to take a distance reading. Then you move the servo again, and take another reading. And again, and again, until something makes the process stop.

You do NOT take one reading and then wave the servos around like a mad-man, which is what your code is doing now.
The art of getting good answers lies in asking good questions.



Made the correction in my post. Thanks!
Don't do that.  Oh, if there is a typo or grammatical error, go correct it in the earlier post.
But if you change the content of the earlier post based on later conversation, nobody can understand who said what, when.
Instead, make a new reply with the new information.  That keeps the chain of the conversation intact.

OH!  There IS another thing you should change in earlier posts.  The use of code tags.  Go edit your earlier post and put code tags around your code.  This makes it easier to export to the IDE or other text editor.

Many forum members refuse to help new members who fail to read the 'how to use this forum - please read' post at the top of the forum.  Te use of code tags is covered there.

Go Up