Simple infrared light curtain detector


Needed to make a sensor that could tell if something, like trash, was thrown in a bin. Sounds simple but I tried various ultrasonic and optical sensors and nothing seemed to work right. Either they would pick up spurious signals or be too fiddly to adjust or would simply miss small objects completely. I also wanted to be able to scale the sensor system to accommodate different hole sizes.

It turns out that detecting if something small passes through a relatively large opening is surprisingly difficult.

I deeded to try something like a infrared light curtain where many tightly spaced beams of light was used to cover a large area.

Infrared receivers and LEDs

Infrared remote control receivers are available in may forms:

Most of them works very similar and can be used for the application explained later. The chips/modules are only sensitive to light modulated with a specific carrier frequency. This is done to make them insensitive to ambient light. Your typical remote uses  37kHz, 38kHz or 40kHz modulation with 38kHz being the most common. Furthermore the receivers only reacts if the modulated signal is it self on/off modulated with some kind of data with a bitrate in the 0.5 to 2kBit range. The carrier frequency is specified by the manufacturer but 38kHz usually works for all specially if the transmitter and receiver is close to each other.

IR LEDs typically looks like regular LEDs except that they often appear black. They emit light in the 940nm range which is completely invisible.  They are often super bright though and only require a small amount of signal to drive.

Many beams of infrared light

I ended up using an array of infrared LEDs and remote control sensors placed on either side of the bin in such a way that every LED would mostly illuminate one receiver on the opposite side of the bin:

To make sure each LED predominately shine on one sensor I make a sandwich of 4mm. HDF boards that when stacked would create a series of narrow baffles to block light i all but one direction:

LEDs and IR receivers could be pressed into the channels and secured with a bit of glue.

I made several prototypes of different sizes for different size holes:

Reading many sensors

One would think that with many sensors a lot of electronics would be needed to real all of them simultaneously but there is a simpler way.

To detect if any of the light paths was blocked I used this circuit:

All the infrared LEDs are connected in parallel each with a series resistor Ra. A resistor Rb can be used to set the overall brightness of the LEDs to control the relative sensitivity of the detector.

How the detector works

In this application the LED’s are modulated by connecting the Anode(positive) end of the LEDs to a constant 38kHz signal(C) and the other to a 1 kHz signal(B).  While 1kHz signal is LOW the LEDs will blink every time the 38kHz signal is HIGH. When the 1kHz signal is HIGH the LEDs are experiencing reverse voltage and are constantly off.

Put simply the LEDs are transmitting bursts of 38kHz modulated IR signal at 1kHz. In this case the 1kHz signal is the “data” that is transmitted:

The IR receivers picks up the modulated light signal and outputs the 1kHz “data” signal on their output. Most receivers will output a LOW signal when a burst of IR is received.

In the circuit above all receivers will output a LOW signal when a burst of light is received. If at least one of the receivers fail to detect the pulse it will output a HIGH during the duration of the light pulses. Diodes (d) will pull a resistor (Rb) HIGH if ANY of the detectors is not receiving light.

To generate the waveforms and check for the missing pulses I used a Arduino UNO but other microcontrollers can obviously be used as well:

Example code

Here is some simple test code:

#define BUILTIN_LED 13
void setup() {
  //Set up frequency generator for 38kHz:
  TCCR1A = 0b10110010;      
  TCCR1B = 0b00011001;      
  ICR1 = 420;         //16MHz/420 ~ 38kHz                
  OCR1A = 210;        //Half that for 50% duty cycle        
  TCCR1B |= 0x01;          
  pinMode(9, OUTPUT); //-Signal generator pin
  pinMode(8,OUTPUT);  //-"data" pin      

void loop() {
  digitalWrite(8,LOW);  //-LEDs sending
    //-Light blocked
    //-Light clear
  digitalWrite(8,HIGH);  //-LEDs off

In the ‘setup’ function the Arduino is instructed to output a constant 38kHz signal on pin 9. This pin is determined by the hardware inside the Arduino and can not be changed. Pin 9 and 8 is also configured as outputs.

The “data” signal is generated in the ‘loop’ function by simply setting pin 8 HIGH, waiting for 1/2 milisecond, setting pin 8 LOW, waiting 1/2 millisecond and repeating for ever.

A check is made of pin 7 when pin 8 is high. If this pin is HIGH at this time an obstacle is present in one of the beams. A built in LED (connected to pin 13) will light up when an obstacle is present in any of the light paths.

The repetition rate is not very critical so if whatever goes into the if-statement takes a little time it’s usually fine.


I have now used this kind of detector for many applications and I find that it works reliably under many different conditions. The hardware is really simple and it only require 3 I/O pins on whatever microcontroller is used and I have tried with as many as 20 individual LED/receiver pair without any problems.

Sensor used for industrial application

Sometimes the brightness of the LEDs can be adjusted to increase reliability. I often find that lowering the brightness to almost failure and then up a bit gives the best results. The IR detectors are made to be extremely sensitive so when pointing the transmitters directly at them it is easy to over saturate the sensors.


Leave a Reply