Categories
algorithm Arduino electronics software

LDR or LED for Laser Detection?

While researching how to detect a laser beam configured as a tripwire I came across a number of ‘recommended’ ways to do this. I decided to test the two cheapest viable options – an LDR and LED – to see which would best suit my needs.

The sensor requirements for this application are relatively simple – detect a low power red laser beam interrupted by something passing through the it. The sensor needs to provide a reliable on/off signal within a few milliseconds of the event. It should also be inexpensive and implementable with a minimum of supporting passive components (ie, no op-amps, transistors, etc).

The two candidates that could suit this application are a

  • Light Dependent Resistor (LDR).
  • Light Emitting Diode (LED) used as a photodiode.

Light Dependent Resistor

A LDR (also known as photoresistor or photocell) is a passive component that decreases resistance when exposed to increased light intensity. The resistance range can span orders of magnitude when exposed to light – from as several megaohms to as low as a few hundred ohms.

Inexpensive cadmium sulfide (CdS) cells are readily available and can be found in many consumer items. Importantly for this application, LDRs are also commonly used in laser-based security systems to detect the laser beam is interrupted.

LDRs are usually configured as in voltage divider (see the circuit here) that provides a voltage proportional to the light intensity to a microporcessor’s analog input.

Light Emitting Diode

A Light Emitting Diode (LED) is a semiconductor light source that emits light when current flows through it. The color of the light is determined by the energy required for electrons to cross the band gap of the semiconductor and commonly enhanced by the color of the encapsulating plastic lens.

In addition to emitting light, a LED can be used as a photodiode light sensor/detector. When used this way, a LED is sensitive to wavelengths equal to or shorter than the predominant wavelength it emits. The current produce is very small (microamps).

The small current produced can be measured using high impedance inputs common in modern microprocessors. The LED is wired in a circuit ‘as normal’ with the microprocessor pin configured as an analog input measuring the voltage generated by the light detection, which should be about the same as the LED forward voltage.

Testing

The test hardware setup shown below is built up from my standardized prototyping mini-circuits (see this previous article) and the software used is found at the end of this article.

A small 5mW red laser is directly connected to an output pin and can be turned on/off using a tact switch connected to input pin.

The LDR/LED sensors are in turn connected to a third input pin and sampled by the software. The Arduino board’s bult-in LED is used to indicate the binary sensor output and the corresponding analog values are written to the serial monitor.

The LED had a few shortcomings in this application. The analog range was relatively small (260 to 140) making it tricky to find the on/off threshold. The sensor values read also jumped around quite a bit, so each reading was actually the average of multiple reads with senor recovery delays between each reading.

The LDR performed the best for this application. The sensor was 100% reliable, with the analog values reported between 1000 (exposed to the laser) and 100 (dark). This large range makes it easy to convert to an on/off signal. The sensor could also be read in one operation and requires minimal software additional hardware to use.


Test Code

// Test Laser Tripwire
//
// Test laser sensor types
// Switch off the built-in LED when the laser is blocked
//
// MD_UISwitch from https://github.com/MajicDesigns/MD_UISwitch or Arduino Library Manager


#include <MD_UISwitch.h>

#define TEST_LDR 1
#define TEST_LED 0

const uint8_t PIN_LASER = 12;
const uint8_t PIN_DETECT = A0;
const uint8_t PIN_SWITCH = 3;

MD_UISwitch_Digital sw(PIN_SWITCH); // laser toggle switch

void setup(void) 
{
  Serial.begin(57600);
  Serial.print(F("\n[Laser Test]"));
  pinMode(PIN_LASER, OUTPUT);
  pinMode(PIN_DETECT, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  sw.begin();
}

#if TEST_LDR
const uint16_t threshold = 200;

inline uint16_t readSensor(void)
{
  return(analogRead(PIN_DETECT));
}
#endif

#if TEST_LED
// LED is in circuit with anode in the PIN_DETECT and gnd to ground
const uint16_t threshold = 160;
const uint8_t samples = 20;
const uint16_t recovery = 2;

uint16_t readSensor(void)
{
  uint32_t sens = 0; 

  for (uint8_t i = 0; i < samples; i++) // remember the lowest value out of many readings
  {
    sens += analogRead(PIN_DETECT);
    delay(recovery);                 // the sensor needs a delay here to catch its breath
  }
  sens /= samples;

  return(sens);
}
#endif

void loop(void)
{
  // toggle laser on/off with momentary switch
  if (sw.read() == MD_UISwitch::KEY_PRESS)
    digitalWrite(PIN_LASER, digitalRead(PIN_LASER) == LOW ? HIGH : LOW);

  // display the value of the input detected
  uint16_t v = readSensor();
  
  digitalWrite(LED_BUILTIN, v < threshold ? HIGH : LOW);

  Serial.print(F("\n"));
  Serial.print(v < threshold);
  Serial.print(F("  "));
  Serial.print(v);
}

Leave a comment