Activate Stepper Motor with PIR sensor

Hello guys,

I am working on a project which will allow a user to open a fridge door using a voice-recognition module.
I am using different components to make this work; linear solenoid, stepper motor, PIR sensor, EasyVR Shield).

I have programmed most of it but I am now stock on something.

I am trying to activate the stepper motor 500 steps if no motion is detected...using a PIR sensor.

So my question is: what would the code look like to move my stepper motor 500 steps once no motion is detected?
If motion is detected, I want the stepper motor to hold its position. I only want the stepper motor to move 500 steps only after no motion is detected.
I've been trying to use a while loop but can't seem to be working properly, what would be the best way to accomplish this?

Any help will be greatly appreciated!

Thanks

Your code would help.

Well, you have some logical condition when motion is detected.

And when you stop detecting the motion, you remember what time that is, and you start counting the time.
And if you detect motion, you go back to the logical condition when motion is detected.

And if 5 seconds go by, and you still don't detect motion any more, then you start driving your stepper motor.

So your system has four different states.

State 1: currently detecting motion
State 2: not detecting motion, but had motion in the last 5 seconds
State 3: running the stepper motor sequence
State 4: finished running the stepper motor sequence.

And then you implement the logical steps which cause transitions between those 4 logical states.

Hi,

Thanks for the feedback.
Here is the code I made so far. Still having trouble...

Any comments?

Thanks

//PIR sensor with Stepper motor

#include <Stepper.h>

#define motorSteps 200     // change this depending on the number of steps
                           // per revolution of your motor
#define motorPin1 8
#define motorPin2 9
#define motorPin3 10
#define motorPin4 11
#define ledPin 13

//int solenoidPin = 9;
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0; 

// initialize of the Stepper library:
Stepper myStepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4); 

void setup() {
  myStepper.setSpeed(30);       // set the motor speed at 30 RPMS:
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);
}
 
void loop(){
  val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }     
} else {
    if (pirState == HIGH){
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
      myStepper.step(-500)
      }
  }

Still having trouble...

Any comments?

Sure. I suggest you tell us what the trouble is.

Ok, I was trying to make it easier and only write the code for the stepper motor and PIR sensor. So here is my entire code...that entails recognizing my voice (key work and password), if EasyVR Shield recognizes the pattern then, a solenoid powers on breaking the seal of the fridge door. Then, the stepper motor takes over the motor and turns 500 steps.
So far so good, the code works.

This is the part where I am stuck.
I want the stepper motor to do -500 steps once the PIR sensor doesn't detect any motion.
My problem is the PIR sensor. The stepper motor does not do -500 steps once no motion is detected.

as for the code, you might want to ignore it until you see //Activate the stepper motor...that's where I am having trouble.

Thanks

/**
 EasyVR access control demo.
 
  Simple demo showing how to use the EasyVR Shield with Arduino
  to implement an access control system based on voice passwords.
 
  EasyVR wait for user names in group 1 and, if any name 
  is recognized, the system asks for the related password. 
  If the password is recognized the access is granted and 
  a stepper motor is actuated, if not the access is denied.
 
  User names and passwords are trained with the EasyVR Commander.
  Transfer the voice recordings into the EasyVR sound table, then 
  enter and train user names in group 1 and related passwords in group 16.
  Use long names and passwords to increase recognition performance.
  Moreover, for better security set the recognition level to HARDER using the 
  setLevel function.
  
  With EasyVR Shield, the green LED is ON while the module
  is listening (using pin IO1 of EasyVR).
  Details are displayed on the serial monitor window.

**
  Example code for the EasyVR library v1.0
  Written in 2011 by RoboTech srl for VeeaR <http:://www.veear.eu> 

  To the extent possible under law, the author(s) have dedicated all
  copyright and related and neighboring rights to this software to the 
  public domain worldwide. This software is distributed without any warranty.

  You should have received a copy of the CC0 Public Domain Dedication
  along with this software.
  If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/

//EasyVR Shield
#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
  #include "SoftwareSerial.h"
  SoftwareSerial port(12,13);
#else // Arduino 0022 - use modified NewSoftSerial
  #include "WProgram.h"
  #include "NewSoftSerial.h"
  NewSoftSerial port(12,13);
#endif

//Stepper Motor - define and declare variables
#include "EasyVR.h"
#include <Stepper.h> 
#define motorSteps 200 
#define motorPin1 8
#define motorPin2 9
#define motorPin3 10
#define motorPin4 11
#define ledPin 13
Stepper myStepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);

//Solenoid - declare variable
int solenoidPin = 7;

//PIR Sensor
//int ledPin = 13;
int inputPin = 2;
int pirState = LOW;
int val = 0;

//Sound Commands - not used in this example but still there for reference
#define SND_Access_denied            1
#define SND_Access_granted           2
#define SND_Hello                    3
#define SND_Please_repeat            4
#define SND_Please_say_your_password 5
#define SND_Please_talk_louder       6

//Bridge the EasyVR Shield with the Arduino
EasyVR easyvr(port);
EasyVRBridge bridge;

//EasyVR Shield declare variables
uint32_t mask = 0;
int8_t group = 0;
uint8_t train = 0;
char name[32];

void setup()
{
  // bridge mode?
  if (bridge.check())
  {
    cli();
    bridge.loop(0, 1, 12, 13);
  }

  Serial.begin(9600);
  port.begin(9600);
  
  // set the Stepper motor speed at 30 RPMS:
  myStepper.setSpeed(30);
  
  // initialize the Solenoid digital pin as an output.
  pinMode(solenoidPin, OUTPUT);     
  //myservo.attach(9);
  //myservo.write(90);  
  
  if (!easyvr.detect())
  {
    Serial.println("EasyVR not detected!");
    for (;;);
  }
  
  easyvr.setPinOutput(EasyVR::IO1, LOW);
  Serial.println("EasyVR detected!");
  easyvr.setTimeout(15);
  easyvr.setLanguage(EasyVR::ITALIAN);
  
  int16_t count = 0;
  
  
  if (easyvr.getGroupMask(mask)) // get trained user names and passwords
  {
    uint32_t msk = mask;  
    for (group = 0; group <= EasyVR::PASSWORD; ++group, msk >>= 1)
    {
      if (!(msk & 1)) continue;
      if (group == EasyVR::TRIGGER)
        Serial.print("Trigger: ");
      else if (group == EasyVR::PASSWORD)
        Serial.print("Password: ");
      else
      {
        Serial.print("Group ");
        Serial.print(group);
        Serial.print(": ");
      }
      count = easyvr.getCommandCount(group);
      Serial.println(count);
      for (int8_t idx = 0; idx < count; ++idx)
      {
        if (easyvr.dumpCommand(group, idx, name, train))
        {
          Serial.print(idx);
          Serial.print(" = ");
          Serial.print(name);
          Serial.print(", Trained ");
          Serial.print(train, DEC);
          if (!easyvr.isConflict())
            Serial.println(" times, OK");
          else
          {
            int8_t confl = easyvr.getWord();
            if (confl >= 0)
              Serial.print(" times, Similar to Word ");
            else
            {
              confl = easyvr.getCommand();
              Serial.print(" times, Similar to Command ");
            }
            Serial.println(confl);
          }
        }
      }
    }
  }
  easyvr.setLevel(EasyVR::HARDER);
  easyvr.playSound(SND_Hello, EasyVR::VOL_FULL);
}

void loop()
{
  int idx_cmd;	
  int idx_pwd;
  
  easyvr.setPinOutput(EasyVR::IO1, HIGH); // LED on (listening)
  
  Serial.println("Say a name in Group 1");  
  easyvr.recognizeCommand(1); // recognise command in group 1 
  while (!easyvr.hasFinished()); // wait for user name
  
  easyvr.setPinOutput(EasyVR::IO1, LOW); // LED off
 
  idx_cmd = easyvr.getCommand(); // get recognised user name

  if (idx_cmd >= 0) 
  {    
    Serial.print("Name: ");    
    if (easyvr.dumpCommand(1, idx_cmd, name, train))
      Serial.println(name);
    else
      Serial.println();    
    
    easyvr.playSound(SND_Please_say_your_password , EasyVR::VOL_FULL);  // ask for password
    
    easyvr.setPinOutput(EasyVR::IO1, HIGH); // LED on (listening)  
    
    Serial.println("Say the password");    
    easyvr.recognizeCommand(EasyVR::PASSWORD); // set group 16
    while (!easyvr.hasFinished()); // wait for password
  
    easyvr.setPinOutput(EasyVR::IO1, LOW); // LED off    
    
    idx_pwd = easyvr.getCommand(); // get recognised password
    
    if (idx_pwd >= 0)
    {
      Serial.print("Password: ");     
      
      if (easyvr.dumpCommand(EasyVR::PASSWORD, idx_pwd, name, train))
      {
        Serial.print(" = ");
        Serial.println(name);
      }
      else
        Serial.println();      
      
      if ( idx_pwd == idx_cmd) // index of username and password are the same, access granted
      {

        Serial.println("Access granted");
        easyvr.playSound(SND_Access_granted , EasyVR::VOL_FULL);    
        
        //Activate the Solenoid
        digitalWrite(solenoidPin, HIGH);   
        delay(500);
        digitalWrite(solenoidPin, LOW);
        
        //Activate the Stepper motor
        myStepper.step(500);
        delay(500);
        //myStepper.step(-500);
        //delay(500);
        
        val = digitalRead(inputPin);  // read input value (PIR)
        if (val == HIGH) {            // check if the input is HIGH
            Serial.println("Motion detected!");
            // We only want to print on the output change, not state
            pirState = HIGH;
          }     
      } else {
          if (pirState == HIGH){
            Serial.println("Motion ended!");
            // We only want to print on the output change, not state
            pirState = LOW;
            myStepper.step(-500);
            }
      }  
    }
      
      else // index of username and password differ, access is denied
      {
        Serial.println("Access denied");
        easyvr.playSound(SND_Access_denied , EasyVR::VOL_FULL);    
      }
      
    }    
    
    int16_t err = easyvr.getError();
    
    if (easyvr.isTimeout() || (err >= 0)) // password timeout, access is denied
    {
      
      Serial.println("Error, try again...");
      easyvr.playSound(SND_Access_denied , EasyVR::VOL_FULL); 
      
    }
  
  
  else
  {
    if (easyvr.isTimeout()) 
        Serial.println("Timed out, try again...");
      
    int16_t err = easyvr.getError();
    if (err >= 0)
    {
      Serial.print("Error ");
      Serial.println(err, HEX);          
    }
  }
}

Look at WHERE you put the code to read the PIR sensor. List all the things that have to happen ON THAT ITERATION OF LOOP() in order for that code to be executed.

Is it likely that all that stuff will happen, in that order, on a single pass through loop()?

You need a state machine (and a lot of changes to that code).

Make a list of states. Name unknown. Name known. Password wrong. Password right. Door open. Door closed. Motion detected. No motion detected. Plus maybe others. Put each of these in circles.

Draw arrows between states where transitions are logical (name unknown to name known is logical; name unknown to door open is not).

Along each arrow, write what needs to happen to trigger that state change, and what happens when the state changes. For instance, from door closed to door open, the door needs to be opened.

Then, write the code to implement each of the transitions (that make sense) when in the appropriate state.

I don't see why I need to change a lot in my code...it works perfectly fine.
Again, the only issue I have is the PIR sensor. I am having trouble making the stepper motor respond to the PIR sensor not detecting any motion.
Here what my code does as is:

  1. I say:"open" (I hear a beep saying it understood), then "fridge" (I hear another beep saying it understood).
  2. Linear Solenoid activates
  3. Stepper motor starts turning 500 steps
  4. Now this is what I need: as soon as the PIR sensor doesn't detect motion, stepper motor turns -500 steps
    Keep in mind the PIR sensor is turned on throughout this whole process (detecting motion or not)

You are thinking linearly. Step 2 follows step 1. Step 3 follows step 2.

The Arduino does not.

The Arduino could block when the door has been opened, and do nothing else until there is no motion and it can close the door. But, is that what you really want? It would not listen for new voice commands.

If you want to wait for the PIR sensor to go LOW, you'll need a

while(digitalRead(inputPin) == HIGH)
{
   // Do nothing
}

block, right after you run the stepper to open the door. Right after this block, you can close the door.

I tried this loop and it works exactly as I wanted it to work
Thank you!!!!!

I added the fucntion in the loop you provided me as follow, to keep the stepper motor at rest.

while(digitalRead(inputPin) == HIGH)
{
myStepper.step(0);
}
myStepper.step(-500);

Thank you again for your help PaulS!!!!!