Tuesday, March 16, 2010

Detecting an IR Beam Break with the Arduino IR Library

One reader asked how to use my Arduino Infrared Library to detect breakage of an IR beam. The answer was too long for the comments section, so I've extended into a blog post. One straightforward way is to use the library to modulate an IR LED at 38kHz, and use a standard IR detector module to detect the signal. The output from the module can be simply read as a digital input.

Here is a simple sketch to do that. The IR LED is connected to pin 3 through a 100 ohm resistor, the detector is connected to pin 2, and a status LED is connected to pin 13 (if your Arduino board doesn't have it already.) To create the modulated output, simply call irsend.enableIROut(38); to set the PWM to 38kHz, and then irsend.mark(0) to send a mark (i.e. turn the output on). The loop simply reads the input from the detector, inverts it (since the detector is active-low), and writes it to the status LED.

#include <IRremote.h>

#define PIN_IR 3
#define PIN_DETECT 2
#define PIN_STATUS 13

IRsend irsend;
void setup()
{
  pinMode(PIN_DETECT, INPUT);
  pinMode(PIN_STATUS, OUTPUT);
  irsend.enableIROut(38);
  irsend.mark(0);
}

void loop() {
  digitalWrite(PIN_STATUS, !digitalRead(PIN_DETECT));
}
You should see the pin 13 LED light up when the IR receiver detects an infrared signal, and go dark when the receiver does not detect an infrared signal. The circuit is basically trivial, but there's a schematic at my original article if you need one. The following picture shows the detector setup. Note the illuminated status LED.
IR detector circuit
If the circuit doesn't work, first use a cell phone camera to verify that the infrared LED is lit. If the LED is not lit, try reversing it. Here's my cellphone's view of the illuminated LED:
illuminated infrared LED
Next, point a TV remote control at the detector and make sure the status LED flashes. If the status LED doesn't come on, make sure you wired the detector properly, and connected to input 2 of the Arduino. If the status LED won't turn off when you break the beam, you probably aren't blocking the IR signal well enough. The detector is very sensitive, and IR bounces off many things, so you may need to separate the LED and detector by several feet and make sure you're fully blocking the IR beam. Note that the library assumes you're using a ATmega168/328, so you're on your own if you have a different processor.

The tricky part of this is the optics - figuring out how to set up the LED and receiver so the beam gets interrupted when you want it to. Also, you'll probably want to modify the detection logic to do something more interesting than just set the status LED, but that's left as an exercise for the reader :-)

12 comments:

Ioan said...

Thank you!
Best regards.

Anton said...

This technique can alsa be used for non-contact collision detection for robots. The Boe-Bot for example does just that, send out a 38kHz IR beam and check if it's reflected.

Ioan said...

Yesterday I received the 38kHz IR detectors from Digi-Key and I was able to test the IR Library. Worked perfect from the first try. Thank you!

lukethomastaylor said...

Is there any way to do this "PWM style" break beam with a simple IR detector (i.e. not one that automatically detects a 38kHz modulated IR signal, just a transistor)?

Sergio said...

Hi, This is a great library and circuit. Thanks for sharing.
I'm having a problem with my detector, as I could figure out, I'm using TSOP1838 with basically rejects continuos 38Khz frequency, see the datasheet at:
http://www.datasheetcatalog.org/datasheets/134/301155_DS.pdf

I'm wondering what sensor can I use that does not supress continuous frequencies.

Thank you.

Anonymous said...

I have built this circuit and during testing, I noticed that when I cut the beam, the light on my arduino board (L or pin 13).

In the write up it says the light should shine always, and shut off when the beam is interrupted.

Is this a typo, or is there something strange on my end?

Also, I noticed that if I bring the detector and emitter very close, the pin 13 light goes on, but nothing happens when I break the beam.

Any idea what I have gotten wrong?

Iain Smith said...

Great tutorial, works a treat!

Also that's a good tip (Anton) for the non-contact object detection, my guess is that this will use alot less power than something like the PING board (ultrasonic).

You can also use it for a really cool non-contact "switch" (for example to enable something)

regarding the comment from Anon did you remember the "!" to invert the status?

Marc said...

Here is a fix for the 838 and any others that reject a continuous beam.

void loop() {
irsend.space(0);
delay(1);
irsend.mark(0);
digitalWrite(PIN_STATUS, !digitalRead(PIN_DETECT));
delay(1);
}

Declan said...

I know this is an old post, but...

Is it possible to use two emitters and two detectors without them interfering?

Is it just a case of giving them a different frequency?

If so, do you think these will do?: http://www.sparkfun.com/products/241

Thanks in advance,

Declan

scottyjr said...

Thanks for the library. I'd like to change the pin assignment for the emitter. I tried by changing it in the code but had no success so I suspect it needs to be changed elsewhere also. How can I do this? Thanks

solaron99 said...

Hi Ken,

my sketch currently uses pin3, I attempted to change the variable declaration from your sketch:

#define PIN_IR 3 to #define PIN_IR 5

... it doesn't work,
I want to use my Arduino Uno's pin 5 for the IR emitter.

Do I have to modify some code in the library?
Any other PWM I declare does not work either except pin 3.

Please help!

Thx!

Abinand said...

thanks a ton!!!!!!!!!