Go Down

Topic: Using a PIR Sensor along with a Motor Shield (Read 5172 times) previous topic - next topic

jaredlee

Oct 14, 2013, 08:13 am Last Edit: Oct 14, 2013, 04:45 pm by jaredlee Reason: 1
Hi. I have been trying to correlate the movement of my robot based on a PIR Sensor. Specifically, I just want my robot to move randomly (forward, left and right) whilst stopping on a regular interval (say every 5 seconds) to activate the PIR Sensor to check if anything's moving. However, I can't seem to make anything move and even the PIR is not checking on anything on my code.

Here's a list of what I am using
* A standard Parallax PIR Sensor
* Generic Motor Shield that drives 2 DC Motors. Uses pins  8,9,10,11.
* Arduino Uno R3

Since I have yet to gather enough understanding on how to make time intervals on code, I am only trying at the moment to make the motors move once the PIR detects something. Here is my (non-working) code so far. (I only mixed and modified some tutorial codes I've found and added some of mine. Credits to their owners.)

Code: [Select]
int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int speed;

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);     
  pinMode(11, OUTPUT);

  Serial.begin(9600);
}

void loop(){
  val = digitalRead(inputPin); 
  if (val == HIGH) {           
    digitalWrite(ledPin, HIGH); 
    digitalWrite(8, LOW);
    digitalWrite(11, LOW);
    for (speed=0; speed<256; speed++){
      analogWrite(9, speed);   
      analogWrite(10, speed);   
      delay(10);     
    }   
    for (speed=255; speed>0; speed--){
      analogWrite(9, speed);   
      analogWrite(10, speed);   
      delay(10);           
    }     
    digitalWrite(8, HIGH);
    digitalWrite(11, HIGH);
    for (speed=0; speed<256; speed++){
      analogWrite(9, speed);   
      analogWrite(10, speed);   
      delay(10);         
    }   
    for (speed=255; speed>0; speed--){
      analogWrite(9, speed);   
      analogWrite(10, speed);   
      delay(10);           
    }   
    if (pirState == LOW) {
      Serial.println("Motion detected!");
      pirState = HIGH;
    }
  }
  else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH){
      Serial.println("Motion ended!");
      pirState = LOW;
    }
  }
}


If somebody could shed me some light on this I would be very much thankful!

EDIT: Okay so I tried the code and made some corrections and now it works. The car now runs for a short while whenever a motion is detected on the PIR sensor. That's basically how I programmed it to be for the meantime just to see if the shield and PIR Sensor work. However, how do I go into making the car to do these things:

1.  Run randomly for 5 seconds (forward, left and right)
2. Activate the PIR once the wheels have stopped. Then run another DC motor once motion is detected.
3. If no motion is detected on Step 2, Run step 1 again.

Thank you!

PaulS

Code: [Select]
     delay(10);      // wait for a second
Useless comments should at least be correct.

If you put your { on new lines, and used Tools + Auto Format, your code would be more readable. Posting it correctly would be even better.

Forget that you can put comments at the end of a line of code. They rarely belong there. You should put comments before blocks of code that explain what the code is supposed to do.

Quote
Here is my (non-working) code so far.

The code is doing something. You haven't explained what that is. You want it to do something. Presumably that is different from what it actually does. You haven't explained what it is, though.

jaredlee

Thank you for the suggestions. I have done some editing on the original post. Please tell me if there's still something wrong about my post.

Here's what I've added by the way:

Quote

EDIT: Okay so I tried the code and made some corrections and now it works. The car now runs for a short while whenever a motion is detected on the PIR sensor. That's basically how I programmed it to be for the meantime just to see if the shield and PIR Sensor work. However, how do I go into making the car to do these things:

1.  Run randomly for 5 seconds (forward, left and right)
2. Activate the PIR once the wheels have stopped. Then run another DC motor once motion is detected.
3. If no motion is detected on Step 2, Run step 1 again.


The code above is only meant for the Arduino and the Motor Shield to run 2 geared DC Motors whenever the PIR Sensor detects motion. I am still unsure of what I should do next to attain my objectives. Thank you!  :)


jaredlee

I have made steps in order to run the motors at a definite interval which is 5 seconds. However, I seem to ran into a problem where the motors indeed run every 5 seconds(ish) but only at a very short short time, as short as a pulse not even enough to see movement. How do I set the motor to run for 5 seconds and will do this every 5 seconds?

Code: [Select]
const int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int speed;

long previousMillis = 0;
long interval = 5000;

void setup() {
  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);     
  pinMode(11, OUTPUT);

}

void loop(){
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time the motor is ran
    previousMillis = currentMillis;

    val = digitalRead(inputPin);  // read input value
    if (val == LOW) {            // check if the input is HIGH
      digitalWrite(ledPin, LOW);  // turn LED ON
      for (speed=0; speed<256; speed++){
        digitalWrite(9, speed);   
        digitalWrite(10, speed);
        digitalWrite(8, speed);
        digitalWrite(11, speed);   
      }   
    }
    else
      digitalWrite(ledPin, HIGH); // turn LED OFF
    for (speed=255; speed>0; speed--){
      analogWrite(9, speed);   
      analogWrite(10, speed);
      analogWrite(8, speed);
      analogWrite(11, speed);   

    }
  }
}

wildbill

Add a boolean variable to tell you whether the motors are on or off. When the five second interval occurs, if the motors are on, spin them down, otherwise, spin them up.

Right now, when the interval occurs, you spin up the motors if the pir input is low and then unconditionally spin them down again.

Using PWM on all your motor pins seems wrong - I'd expect only one per motor needs it to control speed.

jaredlee

Yes my bad, pins 9 and 10 must only be either ON or OFF since they're only for brakes, my last code was so messed up.
Here's my cleaner code so far, but still no improvements regarding the duration and timing of motor spins.

Code: [Select]

int ledPin = 13;
int pirPin = 2;
int gunPin=12;
int val = 0;
int motorPin9=0;
int motorPin10=0;
int analogval9=0;
int analogval10=0;
int speed;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(pirPin, INPUT);
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);     
  pinMode(11, OUTPUT);

  Serial.begin(9600);
}

void loop()
{
  val = digitalRead(pirPin);
  analogval9 = analogRead(motorPin9);
  analogval9 = analogRead(motorPin9);

 
    digitalWrite(ledPin, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(11, LOW);
    for (speed=255; speed>0; speed--)
    {
      analogWrite(9, speed);
      analogWrite(10,speed);
      delay(10);
    }        ///////////////////// FORWARD
    if (analogval9==0 & analogval10 ==0)
    {
      if (val == HIGH)
      {
        digitalWrite(12,HIGH);
        delay(20);
      }
    }
}
 


I wish to have the car STOP when the PIR senses motion, but I believe it can't do so because it's busy processing "delay" commands.

Quote
Add a boolean variable to tell you whether the motors are on or off. When the five second interval occurs, if the motors are on, spin them down, otherwise, spin them up.


I tried to do this above but I still can't get the car to stop and make time for the PIR sensing.  Am I supposed to use analogRead in the first place? I used it to recognize if the values of PWM pins for motors are at 0.

wildbill

Quote
I wish to have the car STOP when the PIR senses motion,


Is that viable? I'd assume that once the car is moving, it will appear to the pid that there is movement - can you write a little sketch that tests it?

jaredlee

Ah yes my bad again. That is why I want the car to move only for 5 seconds and once it stops automatically, it signals the PIR to sense if something is moving, and if nothing moves, goes on to move for 5 seconds again. I just want to time these 2 events on the program. Thanks!  :)

tangotigger

Hi,
I had a similar problem - trying to control the duration of a motor code running, without getting into complex timing controls - which a kind forum member helped me with....http://forum.arduino.cc/index.php?topic=191649.msg1416279#msg1416279 I removed the PIR from my project, but was able to successfully control the timing of a section of the code within the void loop section of the programme, using the advice I was given. Don't know if this is exactly what you're looking for, but it worked for my application.
Good luck with finding a solution  :)

Go Up