Multiple LDR sensor laser trip wire question

I’m working on a laser tripwire project for a Christmas light display that uses 5 laser modules shining into 5 light-dependent resistors connected to five different analog pins which will “trip” one of five 120 VAC relays that are each hooked to their own digital pin.

The laser modules as well as the relays are powered via 5v USB power brick, because I wasn’t sure if I the arduino could handle the load on the 5v pin. The LDR’s are also fed +5v from the USB power brick.

The laser and LDR are housed in a wooden block. The laser shines across a hallway and reflects back to the LDR via reflective tape mounted on the other side of a hallway. When the laser beam is interrupted, it will activate the relay.

I’ve drawn up the circuit diagram and have indicated which pins will be connected on the arduino(see attachment). I’m currently prototyping using an Uno, but would like to move the final version to a smaller board.

While testing this out, after an hour or so of being up and running, I started to notice some strange behavior, where some of the relay modules were activating without the laser being “tripped”. I wasn’t sure if this is due to overloading of the arduino or what?

Here’s the sketch. I’m using the timemark library which uses millis() to avoid using the delay function.

#include <Timemark.h>

const uint32_t TURN_OFF_TIMEOUT = 2000;
const int CONTROL_MAX = 5;
Timemark turnOff[CONTROL_MAX];
const int sensorPin[CONTROL_MAX] = {A0,A1,A2,A3,A4};
const int relayPin[CONTROL_MAX] = {8,9,10,11,12};

void setup()
{
  Serial.begin(9600);
  for (int i = 0; i < CONTROL_MAX; i++) {
    turnOff[i].limitMillis(TURN_OFF_TIMEOUT);
    pinMode(relayPin[i], OUTPUT);
   digitalWrite(relayPin[i], HIGH);
  }
}

void loop()
{   
  for (int i = 0; i < CONTROL_MAX; i++) {
    if (analogRead(sensorPin[i])> 0 && analogRead(sensorPin[i]) < 100) {
      //Serial.println(analogRead(sensorPin[i]));
      digitalWrite(relayPin[i], LOW);
      turnOff[i].start();
    }
    else if (turnOff[i].expired()) {
      digitalWrite(relayPin[i], HIGH);
    }
   
  }
}

That diagram looks wrong: I don't think the laser is connected via the 10k resistor. So I'll assume you did the actual connections correct.

Start by printing out the analog readings; see what you really get. Mind that the LDR is very sensitive to ambient light, switching on/off lights in that hallway can totally mess up your contraption. That's why normally modulated IR is used in break beam sensors: this makes them much less sensitive to ambient light as the modulation is looked for rather than the actual level.

wvmarle:
That diagram looks wrong: I don't think the laser is connected via the 10k resistor. So I'll assume you did the actual connections correct.

Start by printing out the analog readings; see what you really get. Mind that the LDR is very sensitive to ambient light, switching on/off lights in that hallway can totally mess up your contraption. That's why normally modulated IR is used in break beam sensors: this makes them much less sensitive to ambient light as the modulation is looked for rather than the actual level.

You are correct. I had the diagram wrong. I've corrected it and attached in the original post.

The LDR's are recessed 1" into the wooden block with the inside of the hole painted flat black to reduce reflections. I'm also in an office environment where the lights are on all the time so there's really no ambient light fluctuations. With the blocks mounted, the analog reading (for one LDR) was pretty stable when I first hooked it up. With the laser reflection hitting the LDR, I was getting analog readings between 350 - 400. When I interrupt the laser beam, the readings drop to 60-75. Keep in mind this was when I only had one Laser block and relay hooked up. The strange behavior started happening on the first one I hooked up but only after the other 4 had been hooked up for an hour or more. This all happened last wednesday, but I had to unhook everything due to some other work that was being done. I'm just trying to get some preemptive bugs worked out before I hook everything back up.

What's the best way to get a reading of all of the analog inputs and still be able to identify which reading came from which LDR? Using serial monitor, the output fills the window so quickly as the scroll bar gets smaller and smaller each passing second.

Just add a delay(500) in loop() when testing. Then you get only two prints a second. Or even a delay(1000) for a print every second. That should do just fine.

Remember to remove the delay() calls from your final code.

You can of course also print all the numbers on one line, and add sensor identification to it:

Serial.print(i);
Serial.print(": ");
Serial.print(analogRead(sensorPin[i]));
Serial.print(",  ");

and then just past the for loop do a Serial.println() to get a new line.

So I changed a few things in my code. The first thing was to declare a constant string array that would be used for identifying (via serial output) which laser was tripped.

I also check the state of the “tripped” relay pin to determine if I should print the sensor value. This keeps from filling the serial monitor window. I found that one of my LDR’s had distinctively different readings than the others and my threshold value for comparing if the laser was tripped was too high. I lowered my threshold value and that solved my random “tripping” issue.

I also discovered the Serial Plotter. The plotter works by plotting values that are passed to Serial.print(). You can get multiple plot lines by printing a space between sensor readings. This works great for my project as I can tell when a laser is tripped because the plot line will drop (to zero in my case). Each color line represents a different laser. The key is found at the top and is the order in which the values are printed. (see attachment)

Here’s how my code looks currently:

#include <Timemark.h>

const uint32_t TURN_OFF_TIMEOUT = 2000;
const int CONTROL_MAX = 5;
const int THRESHOLD = 50;
Timemark turnOff[CONTROL_MAX];
const int sensorPin[CONTROL_MAX] = {0,1,2,3,4};
const int relayPin[CONTROL_MAX] = {8,9,10,11,12};
const String pos[CONTROL_MAX] = {"Laser1 ","Laser2 ", "Laser 3 ", "Laser 4 ", "Laser 5 "};
int tripValue[CONTROL_MAX];

void setup()
{
  Serial.begin(9600);
  for (int i = 0; i < CONTROL_MAX; i++) {
    turnOff[i].limitMillis(TURN_OFF_TIMEOUT);
    pinMode(relayPin[i], OUTPUT);
   digitalWrite(relayPin[i], HIGH);
  }
 
//  Serial.print(400); //Used to set upper limit for serial plotter
//  Serial.print(" ");
//  Serial.print(0); //Used to set lower limit for serial plotter
//  Serial.print(" ");
}

void loop()
{       
  for (int i = 0; i < CONTROL_MAX; i++) {
    tripValue[i] = analogRead(sensorPin[i]);

    //UNCOMMENT section if using serial plotter to monitor all sensors
    Serial.print(analogRead(sensorPin[i]));
    if( i < CONTROL_MAX - 1){ 
      Serial.print(" ");
    } else  {
      Serial.println(" ");
    }
    
    if ( tripValue[i] < THRESHOLD) {
     //UNCOMMENT section if using serial monitor to print sensor reading once when laser tripped
//        if (digitalRead(relayPin[i]) == HIGH){ //relay is off
//        Serial.print(pos[i]);
//        Serial.print(" : ");      
//    }
      
      digitalWrite(relayPin[i], LOW);
      turnOff[i].start(); //async timer 
    }
    else if (turnOff[i].expired()) {
      digitalWrite(relayPin[i], HIGH);
    }    
  }
}

laser_trip_plotter.png