determining velocity using a PIRSensor

Hey all, I joined this forum to try and get help with a project I am working on. I want to use a PIRSensor to detect the motion of an object, start a timer, then pass the same PIRSensor (do not have two sensors yet) and stop the timer. After the second pass on the motion sensor I would like the time to be remembered and then used in order to calculate the speed of the object over an arbitrary specified distance. After the speed is calculated, I would like to take that value of speed and have it light a set of corresponding LEDs (I am using 5). The slowest speed will light 1 LED, the next fastest will light 2 LEDs, the next fastest range will light 3 LEDs, and so on and so forth. I have researched Google, this forum for two days now, and cannot find particular topics or help with this setup. I am not particularly good with coding, have only done a little during my labs at school. So any advice or direction to another thread would be fantastic. Thanks for any help.

Here is the code I have so far.

int led1 =  13;      // LED1
int led2 =  12;      // LED2
int led3 =  11;      // LED3
int led4 =  9;       // LED4
int led5 =  8;       // LED5
int distance= 10;   // distance for speed is 10 meters
int n = 0;              // intial time step
int spd = 0;        //initial value for speed
int motionPin = 2;     // motion detector input pin 
byte senseMotion = 0;   // variable to hold current state of motion detector

void setup() {
  // set the digital pin directions
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(motionPin, INPUT);
}

void loop()
{
   senseMotion = digitalRead(motionPin);
   if (senseMotion == HIGH); {
    n=n+.01;  //starts the time counter
    delay(10);  //delay for counter
    }
    
     if (senseMotion == HIGH); {
    n=n; //after second pass of motion sensor holds the last value for time
    spd = n/distance;   //calculates the new value for speed
    }

     if (spd > 1); {  //if statement to light LED 

      digitalWrite(led1, HIGH);
      
    }
    if (spd > 5); {   //if statement to light 2 LEDs 
     digitalWrite(led2, HIGH);

    }
    if (spd > 10); {   //if statement to light 3 LEDs
     digitalWrite(led3, HIGH);

    }
    if (spd > 15); {   //if statement to light 4 LEDs
     digitalWrite(led4, HIGH);
    }
    if (spd > 20); {   //if statement to light all 5 LEDs
     digitalWrite(led5, HIGH);
    }
    delay(3000); //delay for 3 seconds and then shut off all LEDs
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, LOW);
    digitalWrite(led5, LOW);
}

Use the millis() timer to measure time like the blink without delay. Look for edges to trigger the timer not levels. That is if the sensor showed high now but low last time round the loop make a note of the start time. Forget the LEDs bit and use serial print for the output until you get this going.

Use the millis() timer to measure time like the blink without delay. Look for edges to trigger the timer not levels. That is if the sensor showed high now but low last time round the loop make a note of the start time. Forget the LEDs bit and use serial print for the output until you get this going.

Like I said, I am rather new to this coding language and am not sure what you are exactly referring too. The coding I have in OP is bits and pieces found from basic programs others have written strung together the best I could. Perhaps lead me towards an example of what you are talking about?

Perhaps lead me towards an example of what you are talking about?

Grumpy_Mike:
Use the millis() timer to measure time like the blink without delay.

This is an example in the IDE you down loaded.
Look at other examples under the examples menu for button input to see about edges.

I have examined your suggestions and implemented them the best I thought. Do not know if this is correct or not. If you could please tell if this was what you were describing or if I am completely off track.

int led1 =  13;    	// LED1
int led2 =  12;    	// LED2
int led3 =  11;    	// LED3
int led4 =  9;     	// LED4
int led5 =  8;     	// LED5
long previousMillis = 0; //store last time motion sense was triggered
const int distance= 10; 	// distance for speed is 10 meters
int n = 0;              // intial time step
int spd = 0; 		//initial value for speed
int motionPin = 2;   	// motion detector input pin 
byte senseMotion = 0;   // variable to hold current state of motion detector

void setup() {
  // set the digital pin directions
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(motionPin, INPUT);
}

void loop()
{
   senseMotion = digitalRead(motionPin);
   if (senseMotion == HIGH); {
	unsigned long currentMillis = millis();
	if (currentMillis - previousMillis > 1)
	 previousMillis = currentMillis;	//counter after first motion trigger
    
     	if (senseMotion == HIGH)		//second trigger of motion sensor to stop counter
	 currentMillis = currentMillis; //stores elapsed time between motion triggers
	 spd = currentMillis / distnace ; //calculates speed 
	 Serial.print("Speed: ");
    
		
     if (spd > 1);   //if statement to light LED 
		 
      digitalWrite(led1, HIGH);
      
    
	if (spd > 5)   //if statement to light 2 LEDs 
	 digitalWrite(led2, HIGH);
	 
    
	if (spd > 10)    //if statement to light 3 LEDs
	 digitalWrite(led3, HIGH);
	
    
	if (spd > 15)    //if statement to light 4 LEDs
	 digitalWrite(led4, HIGH);
    
	if (spd > 20)    //if statement to light all 5 LEDs
	 digitalWrite(led5, HIGH);
    
	delay(3000); //delay for 3 seconds and then shut off all LEDs
	digitalWrite(led1, LOW);
	digitalWrite(led2, LOW);
	digitalWrite(led3, LOW);
	digitalWrite(led4, LOW);
	digitalWrite(led5, LOW);
}

What part of:-

Grumpy_Mike: Forget the LEDs bit and use serial print for the output until you get this going.

Did you not understand?

or if I am completely off track.

Yep.

That code is not correct at all, it sort of nudges it but is wrong. 1) Do not declare your variables inside the meat of the code make currentMillis global like previousMillis 2) if (currentMillis - previousMillis > 1 ) is wrong if ( (currentMillis - previousMillis) > myDelayTime ) is more like what you want. 3) You are still not looking at edges if (senseMotion == HIGH ) - and DON'T put a colon on the end or you screw it up - should be something like if (senseMotion == HIGH && lastSenseMotion == LOW ) will look at an edge, update the value of lastSenseMotion from senseMotion as the last thing in the loop() function.

I'm sorry, I am not good at coding what so ever. Thank you for the help you are giving me and the patience. It is very much appreciated. Perhaps this is better?

int led1 =  13;      // LED1
int led2 =  12;      // LED2
int led3 =  11;      // LED3
int led4 =  9;       // LED4
int led5 =  8;       // LED5
long previousMillis = 0; //store last time motion sense was triggered
unsigned long currentMillis = millis();
int myDelayTime = 0;
int lastSenseMotion = LOW;
const int distance= 10;     // distance for speed is 10 meters
int n = 0;              // intial time step
int spd = 0;        //initial value for speed
int motionPin = 2;     // motion detector input pin 
byte senseMotion = 0;   // variable to hold current state of motion detector

void setup() {
  // set the digital pin directions
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(motionPin, INPUT);
}

void loop()
{
   senseMotion = digitalRead(motionPin);
   if (senseMotion == HIGH && lastSenseMotion == LOW) {

    if (currentMillis - previousMillis > myDelayTime)
     previousMillis = currentMillis;    //counter after first motion trigger
    
      if (senseMotion == HIGH)    //second trigger of motion sensor to stop counter
     currentMillis = currentMillis; //stores elapsed time between motion triggers
     spd = currentMillis / distnace ; //calculates speed 
     Serial.print("Speed: ");
     lastSenseMotion = senseMotion; 
    }
}

Ok, so after some research I found this tutorial http://playground.arduino.cc/Code/PIRsense . Which measures time between high and low states. I attempted to modify this code to keep time between high and high states using the edges you mentioned earlier. If this will work, I might be able to then continue the code to spit out the velocity given an arbitrary specified distance using the time calculated between high and high states.

//the 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 time;         

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

//set last state of motion sensor to low
in lastsenseMotion = LOW; 

boolean lockLow = true;
boolean takeHighTime;  

int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;



void setup(){
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }


void loop(){

     senseMotion = digitalRead(pirPin);
     if(senseMotion == HIGH && lastsenseMotion == LOW) {
                   
         Serial.println("---");
         Serial.print("motion detected at "); //time motion sense went from low to high
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         
         }         
         takeHighTime = true;
       }

     if(senseMotion == HIGH && lastsenseMotion == LOW){    
      

       if(takeHighTime){
        time = millis();          //save the time between triggers of high and high
        takeHighTime = false;       //make sure this is only done at the start of a High phase
       }
       

	 lastsenseMotion = senseMotion;
       }
  }

Those two if statements test for exactly the same condition.

lastSenseMotion = senseMotion Should be the last thing in your loop. As you have it it is only executed if that second if statement executes.