Repeated Beam Sensor Inputs interfering with Loop

I have what I think is a pretty basic question that I couldn't find an answer to in the Forum. I have a Beam sensor that once tripped triggers two motions on an actuator. If the sensor is triggered multiple time while the actuator is still performing it's function the actuator locks up. I can't seem to find the best way to prevent the reading of additional inputs until the actuator is finished. Code Below.

int pirPin = 12;
int motionStatus = 0;
int pirState = 0;
int ENApin = 6;
int IN1pin = 7;
int IN2pin = 8;


void setup() {

Serial.begin (9600);
pinMode (pirPin,INPUT);
pinMode (ENApin, OUTPUT);
pinMode (IN1pin, OUTPUT);
pinMode (IN2pin, OUTPUT);
delay (60000);                                  

}

void loop() {
 
motionStatus = digitalRead(pirPin);

if (motionStatus == HIGH) {

	if (pirState == LOW) {
	 	
    Serial.println ("Motion Detected");
		pirState = HIGH;

digitalWrite (IN1pin, HIGH);
digitalWrite (IN2pin, LOW);
analogWrite (ENApin, 255);
delay (3000);

  digitalWrite (IN1pin, LOW);
  digitalWrite (IN2pin, LOW);
  delay(3000);

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, HIGH);
analogWrite (ENApin, 255);
delay (4000);

 digitalWrite (IN1pin, LOW);
 digitalWrite (IN2pin, LOW);
 
	}
}

else {

	if (pirState == HIGH) {
	Serial.println ("Motion Ended");
	pirState = LOW;

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, LOW);

	}
	}

}

Given you use delay() to perform the actuator's motion, you don't read the sensor at all during the movement.

Regarding your code structure, you might benefit from studying state machines. Here is a small introduction to the topic: Yet another Finite State Machine introduction

if you want blocking code, you could probably do something as simple as this (typed here, fully untested)

const byte pirPin = 12;
const byte ENApin = 6;
const byte IN1pin = 7;
const byte IN2pin = 8;

void goCW() {
  digitalWrite (IN2pin, LOW);
  digitalWrite (IN1pin, HIGH);
  digitalWrite (ENApin, HIGH);
}

void goCCW() {
  digitalWrite (IN1pin, LOW);
  digitalWrite (IN2pin, HIGH);
  digitalWrite (ENApin, HIGH);
}


void stop() {
  digitalWrite (ENApin, LOW);
  digitalWrite (IN1pin, LOW);
  digitalWrite (IN2pin, LOW);
}

void setup() {
  pinMode (pirPin, INPUT);
  pinMode (ENApin, OUTPUT);
  pinMode (IN1pin, OUTPUT);
  pinMode (IN2pin, OUTPUT);
  delay (60000);
}

void loop() {
  if (digitalRead(pirPin) == HIGH) {
    goCW(); delay (3000);
    stop(); delay(3000);
    goCCW(); delay (4000);
    stop();
  }

  // wait until PIR rests before triggering a new motion
  while (digitalRead(pirPin) == HIGH) ;
}

Thank you for the input.
I'll study up on state machines.

J-M-L,

To follow up I tried something this morning. I changed the pinMode from INPUT to OUTPUT at the beginning of the movement and then switched it back at the end of the movement. This seems to work well. I don't know why because as you pointed out the delay should be preventing inputs during the motion but it did seem to work. I'll keep learning about State machines. Thanks.

int pirPin = 12;
int motionStatus = 0;
int pirState = 0;
int ENApin = 6;
int IN1pin = 7;
int IN2pin = 8;

void setup() {

Serial.begin (9600);
pinMode (pirPin,INPUT);
pinMode (ENApin, OUTPUT);
pinMode (IN1pin, OUTPUT);
pinMode (IN2pin, OUTPUT);
delay (60000);

}

void loop() {

motionStatus = digitalRead(pirPin);

if (motionStatus == HIGH) {

if (pirState == LOW) {

Serial.println ("Motion Detected");
pirState = HIGH;

pinMode (pirPin, OUTPUT);
digitalWrite (IN1pin, HIGH);
digitalWrite (IN2pin, LOW);
analogWrite (ENApin, 255);
delay (3000);

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, LOW);
delay(3000);

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, HIGH);
analogWrite (ENApin, 255);
delay (4000);

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, LOW);
pinMode (pirPin, INPUT);
}
}

else {

if (pirState == HIGH) {
Serial.println ("Motion Ended");
pirState = LOW;

digitalWrite (IN1pin, LOW);
digitalWrite (IN2pin, LOW);

}
}

}

there should be no implication whatsoever as you don't read that pin anyway...

Did this get resolved? I'm curious so am trying to run the sketch in post #4. With few details of your circuit, (sensor?, outputs?) I've connected your ENA, IN1 and IN2 pins to amber, red and green LEDs respectively. Resultant behaviour not making much sense. So - assuming you're still interested - can you please tell us:

  1. What should happen?
  2. What sensor are you using? Mine is a PIR, with its HIGH period set to the minimum, about 6 s, and is running in non-retriggerable mode.
  3. Any further details that would help us help you.

This is hooked up to a Beam sensor.
When the beam sensor trips it turns on an actuator that extends for a set period of time, stops for a set period of time, and then lowers for a set period of time. The actuator is lifting another motor that spins a shaft when its down and lets the shaft freespin when it's up. So far, the coding works out just fine. What I found is that if I don't Turn the sensor input OFF once it triggers and keep it OFF until the sequence is complete, any additional sensor triggers tend to mess up the sequence and either cause it to freeze up or to start over again during the middle of the sequence. I can't really explain that but that seems to be what happens.

When you see sensor activity, set a flag that says two things. One it means you are working on the process that should invoke, and second that any input should be ignored.

The other part of the loop sees it should do the response, and when it finishes, clears the flag resetting the mechanism.

 if not busy and sensor input
    set busy

  if busy
    do a step of the response
    if done clear busy

Both sections meant to be run without blocking.

HTH

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.