Help with one out of 2 laser inputs have an object detected for 1 second before switching pin 5 HIGH

Hello folks, new to writing code. I'm using an Arduino UNO R3 to control a UR5 robot, vibrating bowl, and a feeder. This is the code I have come up with to have laser 1 detect if a part is in the tool head prior to moving to the next location and depositing the part.

Laser 2 is for the feeder. Parts will go past this laser and I don't want the relay to shut off as soon as a part blocks the sensor. I want to turn the relay on pin 5 LOW only when a part is stuck for 1 second as the feeder is full. THIS IS WHERE I NEED HELP, PUTTING IN CODE FOR THE 1 SECOND DETECTION

Analog Input is to control the relay for the vibrating bowl and is based upon the UR5 beginning and end of that program.

// Define pins
int laserPin2 = 2;
int laserPin3 = 3;
int analogPin = 0;
int outputPin4 = 4;
int outputPin5 = 5;
int outputPin6 = 6;

void setup() {
// Set pin modes
pinMode(laserPin2, INPUT);
pinMode(laserPin3, INPUT);
pinMode(analogPin, INPUT);
pinMode(outputPin4, OUTPUT);
pinMode(outputPin5, OUTPUT);
pinMode(outputPin6, OUTPUT);
pinMode (10, OUTPUT); //Output for Laser
pinMode (11, OUTPUT); //Output for Laser
}

void loop () {
// Read laser inputs and analog input
int laser2 = digitalRead(laserPin2);
int laser3 = digitalRead(laserPin3);
int voltage = analogRead(analogPin);

{digitalWrite(10, HIGH), digitalWrite(11, HIGH);}

// Check if object is detected at laser 2
if (laser2 == HIGH) {
  digitalWrite(outputPin4, HIGH); // Set output pin 4 to HIGH
} else {
  digitalWrite(outputPin4, LOW); // Set output pin 4 to LOW
}

// Check if object is detected at laser 3
if (laser3 == HIGH) {
  digitalWrite(outputPin5, HIGH); // Set output pin 5 to HIGH
} else {
  digitalWrite(outputPin5, LOW); // Set output pin 5 to LOW
}

// Check voltage at analog input
if (voltage == 1023) {
  digitalWrite(outputPin6, HIGH); // Set output pin 6 to LOW
} else {
  digitalWrite(outputPin6, LOW); // Set output pin 6 to HIGH
}}

You introduce five devices (LASER, a part, tool head, movement, locations), but what do all of them do? Describe how you intend this project to work. Provide a wiring diagram.

Bare with me with the wiring diagrams as I'm new to this and they don't have the laser eye receiver and they don't have the UR5, vibrating bowl, or motor for the relay outputs.

So laser 1 is simple code where relay turns on or off if there is something detected.

Laser 2 is where I want the laser to be blocked for 1 second before activating the relay.

What detects the "somethig?"

What event starts this blocked period?

Is this close? "Something" is rolling along and is detected by (?device? LASER1?) which activates the stopping of LASER2 from operating for one second, while LASER1 continues to work (whatever it does.. is LASER1 a detector?).

Big picture: Pick and place machine for lip balm tubes. Laser 1 says yes there is a lip balm tube present so I can place the part in the tray. Laser 2 determines if there is a backup with the supply.

Laser 1 and Laser 2 are both on all the time and the receiver is what provides the inputs to the Arduino to activate the relays.

Right now the code works with the components and functions. Instead of relay 2 clicking on and off the entire time a part is moving, I want it to stay deenergized until laser 2 receiver is blocked for 1 second indicating a backup has occurred.

Some comments before continuing...

Yes, I know "0" means A0/DIO14 in this case, but it can be read by a human as "Arduino Pin 0, hardware serial RX"

This is... odd... even though it compiles...

  {
    digitalWrite(10, HIGH), digitalWrite(11, HIGH);
  }

I would write it without the braces ( { } ) or the comma(,)

    digitalWrite(10, HIGH);
    digitalWrite(11, HIGH);

... but why the "10" when something more descriptive should be there (for future code readers)?

    digitalWrite(outputPin10, HIGH);
    digitalWrite(outputPin11, HIGH);

We will keep these two always ON and set a timeout to allow or disallow reading the receiver when LASER2 is blocked for one second.

What is the value of "LASER 2 receiver blocked"? HIGH or LOW?

oops I do not see a "LASER1" anywhere... I see laser3...

We need to be straight on the terms... do not write "laser 1"... use the terms from your code. Would you explain, again (sorry), your code using the terms from your code?

Do you understand how to code a 1 second timer using "millis" and make it NONBLOCKING?

Ok, so I am new and just going through and the int analogPin = 0 is for my association on what I'm using for the input.

digitalWrite for 10 and 11 worked to turn the lasers on on the signal wire. This line can be deleted because I'm just powering it off the mini breadboard and power supply now.

Learning from trying to operate 2 stepper motors in opposite directions at the same time off one input the

{
digitalWrite(10, HIGH), digitalWrite(11, HIGH);
} runs the code as one line at once.

So laser 2 and laser 3 ( based upon pin assignment) will work independently of each other as each input controls a different relay for a different system.

Laser2 code is perfect for the operation I'm trying to do with it.

Laser3 desired operation is to start with pin 5 high and then start monitoring. when laser3 is is then high for 1 second, turn pip 5 high.

I have tried to add millis() but get an error and can't get it to compile. I tried delay but it added delay to laser2 and analog.

Just verifying I understand:

"if laser2 receiver "detects" an object, stop reading laser3 receiver for one second."

Negative. Lasers will read independently of each other.

// Check if object is detected at laser 3
if (laser3 == HIGH) {
  digitalWrite(outputPin5, HIGH); // Set output pin 5 to HIGH
} else {
  digitalWrite(outputPin5, LOW); // Set output pin 5 to LOW
}

That is the only thing I'm trying to modify here.

Ideally pin 5 is high automatically once Arduino is powered up. Parts will start to move past laser3. This will cause the "strobe" effect switching pin 5 high and low. A part will get stuck this way.

I want to add the detect object for one second (laser3 = LOW) before it changes the state on pin 5. This indicates the feeder is full and no more parts can be pushed into it until gravity takes over and creates a laser3 HIGH input again.

Whenever laser3 is HIGH, set a variable to the current time.

If you ever see that time become more than five seconds in the past, it means that kaser3 has been high for more than five seconds.

// using a timing variable, here global (up top, not inside any { braces }

unsigned long laser3Timer;



// Then anywhere in the loop() check it and reset the timer to now 

  if (laser3) laser3Timer = millis();



// And anywhere in the loop() see if it has exceeded the time

  unsigned long elapsedTime = millis() - laser3Timer;
  if (elapsedTime > 5000) {
    Serial.println("laser3 false for > 5 seconds");
// and anything else  wanna do because goes here

  }

HTH

a7

Then you put that code in setup()

Another thing to consider is using variable names than mean something vs. laserPin2. It helps the code be much more self explanatory. A couple of other notes - you can do a digitalRead() on an analog pin. It appears you are using it as a digital value (1023). You can also reduce your if/else statements since your are writing the state of your relays to match the state of your inputs. Just write the value directly.

// Define pins
const int headDetectLaserPin = 2; //int laserPin2 = 2;
const int feederLaserPin = 3;     //int laserPin3 = 3;
const int UR5inputPin = A0;       //int analogPin = 0;
const int headDetectRelayPin = 4; //int outputPin4 = 4;
const int feederRelayPin = 5;     //int outputPin5 = 5;
const int outputPin6 = 6;

unsigned long feederTimer;
const unsigned long maxFeederTime = 1000;

void setup() {
  // Set pin modes
  pinMode(headDetectLaserPin, INPUT);
  pinMode(feederLaserPin, INPUT);
  pinMode(UR5inputPin, INPUT);
  pinMode(headDetectRelayPin, OUTPUT);
  pinMode(feederRelayPin, OUTPUT);
  pinMode(outputPin6, OUTPUT);

  digitalWrite(feederRelayPin, HIGH); // Set feeder relay HIGH

}

void loop () {
  // Read laser inputs and analog input
  int headDetectState = digitalRead(headDetectLaserPin);
  int feederState = digitalRead(feederLaserPin);
  int voltage = digitalRead(UR5inputPin);   // you can digitally read an analog pin

  // Check if object is detected at tool head
  digitalWrite(headDetectRelayPin, headDetectState); // Set output to match input

  // Check if object is detected at laser 3
  if (feederState == HIGH) {
    // not blocked, enable relay and reset timer
    digitalWrite(feederRelayPin, HIGH); // turn on bowl feeder
    feederTimer = millis();
  } else {
    // blocked, if blocked long enough, turn off relay
    if ( millis() - feederTimer >= maxFeederTime ) {
      digitalWrite(feederRelayPin, LOW); // turn off bowl feeder
    }
  }

  // Check voltage at analog input
  digitalWrite(outputPin6, voltage); // Set output to match input
}

Thank you everyone for the input and I'm learning so much. Nice to have support and guidance! blh64 thank you for the break down

In @blh64's sketch you see the pattern I wrote out in #11

  int feederState = digitalRead(feederLaserPin);

//...

  // Check if object is detected at laser 3
  if (feederState == HIGH) {
    // not blocked, enable relay and reset timer
    digitalWrite(feederRelayPin, HIGH); // turn on bowl feeder
    feederTimer = millis();
  } else {
    // blocked, if blocked long enough, turn off relay
    if ( millis() - feederTimer >= maxFeederTime ) {
      digitalWrite(feederRelayPin, LOW); // turn off bowl feeder
    }
  }

Mine was two if statements, the else doesn't change the logic but it does mean the loop will execute a bit faster. But the essential parts are in there. Set a timer whenever you see the signal, check the timer to see if the signal has been absent for some period:

        // Check if object is detected at laser 3
==>        if (feederState == HIGH) {
          // not blocked, enable relay and reset timer
          digitalWrite(feederRelayPin, HIGH); // turn on bowl feeder
==>          feederTimer = millis();
        } else {
          // blocked, if blocked long enough, turn off relay
==>          if ( millis() - feederTimer >= maxFeederTime ) {
            digitalWrite(feederRelayPin, LOW); // turn off bowl feeder
          }
        }

One change or habit I suggest is to use boolean variables for digitalRead(). And manifest constants for the meaning.

Write

// up top maifest constant
# define BLOCKED HIGH


//... and

bool feederBlocked = digitalRead(feederLaserPin) == BLOCKED;

So feederBlocked is true when the beam is blocked. Or maybe you meant the opposite, just change the definition of BLOCKED.

Then the if test is just

  if (feederBlocked) { // whatever

It's another way to improve readability. As well as gaining compliance with the API for digitalRead(). Add a few more manifest constants and you can lose commentary, viz:

  bool feederIsBlocked = digitalRead(feederLaserPin);

//...

  if (feederIsBlocked) {
    digitalWrite(feederRelayPin, ON); 
    feederTimer = millis();
  }

  if (millis() - feederTimer >= maxFeederTime) {
    digitalWrite(feederRelayPin, OFF); 
  }

The combination of manifest constants and familiarity with the basic pattern for timing stuff means the code can end up telling its own story.

a7