Building the phototrap. Part 5: The long range infra-red beam sensor

All the phototraps that I’ve seen on the internet include some variation on the infra-red beam breaking sensor. The technique is simple to explain. You place an infra-red source directly in-line with an infra-red emitter and when an object comes between the two you trigger the camera, or a flash. Job done. Well, in theory at least. Here’s an account of the fun that I had.

The naive design

Initially while playing around I hooked up an IR LED, in this case an Osram SFH484 that has a nice tight half-angle and a 100mA max sustained current. I fitted the appropriate series resistor and on another board I hooked up a photodiode who’s datasheet indicated that it gave the strongest response in the same area of the spectrum as the IR LED. Confidence was running high at this point.

Sadly my expectations were quickly brought back down to earth when I realised that I could only get a few centimetres range in total darkness. Turn the lights on and it barely worked at all. There were two main problems that I quickly identified.

Firstly, 100mA isn’t nearly enough to get decent range. I was going to have to seriously crank up the juice if this was going to be a practical proposition.

Secondly, and most importantly, infra-red radiation is emitted by anything and everything that gives off light or heat and these ‘noise’ sources quickly drown out your ‘signal’.

Max power

A few hours of internet research and much studying of datasheets later and I discovered the solution to the power problem. Instead of running the LED on a continuous current you can get much MUCH higher output if you send short pulses of current to the LED interspersed by gaps designed to be of sufficient size to allow the device to cool before it burns itself out. Do this fast enough and the LED will appear to the human eye to be continuously on and very bright indeed.

The device I chose was the Vishay TSAL6200. The reason for this choice is because it pairs well with a Vishay sensor that we’ll come to later on, and also because it can be pulsed up to 1000mA given the right pulse design. Mouser has these for about 30 pence each.

The power versus current chart

The sensor

The answer to the interference problem is pulse modulation. What this means is that instead of emitting a continuous HIGH signal during your pulse on state, you modulate on and off at a known frequency. 38Khz appears to have been chosen as the industry standard for this purpose. You then use a device that will not respond to infra-red radiation unless it is being modulated at 38Khz.

Vishay produce a device that does exactly that, it’s the TSOP4038 and it couldn’t be simpler to use. There are only 3 pins: power, ground and output. When a 38Khz signal is received the output pin goes high and when there’s no signal it stays low.

Studying the datasheet shows that Vishay’s own test conditions for the TSOP4038 used a TSAL6200 emitter pulsed at 600mA with pulse widths and gaps of 600 microseconds.

The pulse characteristics and sensor response

I had an email exchange with a very helpful gentleman in tech support at Vishay who confirmed that such an arrangement should be good for 5 metres or so of range without any external optics and that the TSAL6200 made a good pair with the TSOP4038.

So that was that, I now had a specification. I was going to build a TSAL6200/TSOP4038 combination pulsing the LED at 600mA with a pulse size of 600 microseconds. The range quoted to me of 5 metres sounded like enough for the purposes of a phototrap but I wondered if I could beef that up a little with some custom modifications…

Emitter design

In my phototrap the sensors are wired to the control box and the emitters, if required, must be standalone. Therefore my design is a self-contained battery powered unit. The clever stuff to do the pulse timing and modulation is handled by an ATtiny85, a very cost-effective MCU from Atmel that comes with 8K flash and 512 bytes of SRAM. Not a lot, but more than enough for this application and the MCU costs less than £3.

Here’s the circuit diagram.

Click for larger

The device is powered by four AA rechargeable batteries, giving an input to the adjustable voltage regulator (the MIC29152BT) of 4.8V. The 680Ω and 470Ω resistors are used to program the MIC29152 to output 3.02V, about as near to my target of 3V as possible using standard value resistors. The goal was for a full charge to last at least 6 hours of continuous use – something I easily achieved.

The TSAL6200 datasheet shows that the forward voltage of the LED at 600mA is around 2.2V. That suggests I need a series resistor of 1.2Ω. I didn’t have any of those around so I decided to push the envelope a bit and use a 1Ω resistor which should yield close to 800mA. I’m confident that the LED will handle it because the modulation of the pulses means I’m only going to be driving the LED for a 25% duty cycle. In any case, I bought a few TSAL6200 just in case of burnouts during development!

The two 3.3K resistors form a voltage divider that I use to measure the voltage coming out of the battery. When it’s above 3.8V I periodically pulse the blue LED. When it’s between 3.8V and 3.3V I pulse the red LED. If it falls below 3.3V then the battery power is getting too low and the circuit is in danger of malfunctioning. If such a malfunction were to result in the ATtiny program emitting a constant HIGH level on pin 6 instead of the programmed pulse then the TSAL6200 would quickly burn out, therefore I shut down the program if the battery voltage falls below 3.3V. I can get away with a single current limiting resistor for both the power LEDs because the firmware ensures that only one is ever on at a time.

The modulating pulse is output from pin 6 of the ATtiny85 via a current limiting resistor to the gate of a BUZ72L power MOSFET. This device was chosen because its characteristics were a good match for the voltage used in this circuit.

The 100Ω resistor across the TSAL6200 is a shunt resistor. Without it the voltage in the circuit cannot fall fast enough to maintain a good waveform. Here is a picture of the waveform without the shunt resistor.

A poorly shaped waveform

As you can see the voltage does not fall to zero in the 38Khz LOW periods and only falls slowly away in the longer pulse OFF period.

Here is the same circuit with the addition of the shunt resistor.

A good shaped waveform

The resolution is different because I wanted to show some complete pulses but you can easily see how much more of a clean shape we’ve got, in fact it’s pretty much ideal.

Emitter firmware

As mentioned earlier the emitter firmware is embedded in an ATtiny85 with 8K of flash memory and 512 bytes of SRAM. This seemingly paltry amount of memory is more than enough because the entire C++ firmware compiles down to only 2878 bytes of machine code.

Eight pins are all you need – an ATtiny85

Out of the box the ATtiny85 is set to run at 1Mhz. Unfortunately that is too slow for it to generate the pulses I need and execute the additional functions in the gaps between the pulse changes so I reprogrammed the fuses to 8Mhz and that worked just fine. You can find an online calculator that will generate fuse values for you by clicking here.

I use a port of the Arduino library, basically to get access to the millis() and micros() timing functions. I don’t use any of the other facilities of the library and I’ve moved the timer that millis() and micros() uses from Timer0 to Timer1 so that I can get access to all the PWM wave generation features on Timer0. The ported library is included in the emitter firmware download in the ArduinoCore subdirectory.

One point to note is that the pin numbers used for digitalRead() and digitalWrite do not map to the same as the package pin numbers. Here is the mapping:

//                  +-/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//      	    GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

Setting up the 38Khz PWM output

The following code is used to program Timer0 to generate a 38Khz signal on pin 6.

void IREmitter::create38KHz()
// switch off


// COM0A = 00: disconnect OC0A
// COM0B = 00: disconnect OC0B; to send signal set
//              to 10: OC0B non-inverted
// WGM2 = 101: phase-correct PWM with OCRA as top
// CS2 = 000: no prescaling

  TCCR0B=_BV(WGM02) | _BV(CS00);

// the top value for the timer
// the modulation frequency will be SYSCLOCK / 2 / OCR0A

  OCR0B=OCR0A/2; 								// 50% duty cycle

The above calculations owe much to the work done by Ken Shirriff in his IR remote library. It would have taken me much longer to decipher the timer registers without his good work.

The main loop of the code basically looks like this

	// high

		TCCR0A|=_BV(COM0B1); 			// Enable pin 6 PWM output

	// check the power level


	// delay for the remaining time


	// low

	  TCCR0A&=~(_BV(COM0B1)); 	// Disable pin 6 PWM output


	 // output power level indicator to appropriate LED


	  // if we are switching from power ok then ensure that
    // the ok led is off


	  // pulse the low power led

	  // if we are switching from low power then ensure that
    // the low power led is off


	  // pulse the OK led


	 // get the time now


	 // delay for the remaining time


The logic in the infinite loop goes like this:

  1. Switch on the wave output
  2. Take a measurement of the voltage from the potential divider
  3. Do nothing for the remainder of the 600 microsecond pulse
  4. Switch off the wave output
  5. Shutdown if the power has been below a critical level for a predefined length of time
  6. Start or continue pulsing the red led if the power is low, or blue if OK.
  7. Delay for any remaining time in the pulse length.
  8. Go to step 1

With so few pins on the ATtiny I don’t have the luxury of a spare timer that I can use to generate a real PWM waveform just for the purposes of producing the nice ‘heartbeat’ LED fade in/out effect. To get around this I wrote an asynchronous LED heartbeat class that just needs me to call pulse() regularly while I want the effect to continue and stop() when I want it to switch off quickly.

Emitter Build

I decided to build the circuit on cheaply available stripboard rather than go to the extra effort and expense of having a PCB built. The stripboard layout is shown below. The two empty rows at the top and bottom are by design so I have some space to mount rubber feet in the corners.

Click to download a PDF

I mentioned earlier that I was going to power the emitter from a set of four AA batteries. With this in mind I decided to mount the circuit and batteries inside a 40mm square box section aluminium tube that I got on ebay for a few pounds, complete with a pair of very handy push-on end caps that could be modified to hold connectors and drilled to let out the IR beam.

The emitter enclosure drilled to accept the on/off switch and the two power leds

Assembling the board only takes an hour or so because the components are quite well spaced apart and stripboard is generally quite easy to work with. Here’s the assembled board with the ATtiny85 mounted in an IC socket. I programmed it externally then simply pressed it into place.

The MIC29152BT voltage regulator was a bit of a pain. Although it came in a standard TO-220 package it crammed five pins into a space where you would normally get three meaning that I had to do quite a lot of gratuitous outward bending with some needle-nose pliers to slot the pins comfortably into the 0.1″ stripboard grid.

The assembled board

Using optics to extend the range

I knew from my conversations with the Vishay engineer that I was going to be good for the planned five meter range but I got to thinking, why not try to get more? So let’s see what we can do with some external optics.

Unsurprisingly the answer came on ebay where I picked up one of these magnifying loupes from a seller in China for a few pounds.

Cheapo loupe

The optical quality of the loupe is terrible! No attempt seems to be made to correct for field curvature so you can have the center in focus, or the edges but not both at the same time. Nice! Anyway, none of this is in the slightest bit important for our purposes. We just need it to magnify, and that it does very well.

Firstly we unscrew the cover and discard it, then we determine the working distance of the lens from the LED like this:

Calculating the working distance

What I’ve done here is to place the loupe in front of the board, which has a power supply connected. Now I move the loupe backwards and forwards until the point where the image of the LED fills the entire surface of the magnifying glass. Then I stop and measure the distance from the lens to the LED and that’s the working distance.

But hang on a second, isn’t this infra-red? How can I see it? The trick is to view the scene through either a camera-phone or any point and shoot camera with an LCD viewfinder on the back, i.e. nearly all of them. These camera’s have sensors that are sensitive to IR and the LED will show up as purple on the LCD.

Don’t be tempted to rig up any old visible LED just to work out this distance. Unless you get the half-angle matched directly with the IR LED then the working distance will be different.

All hooked up

Here’s what it looks like ready to go into the enclosure. The loupe and the board are superglued on to a strip of perspex that I cut from some packaging that was otherwise heading for landfill. The board itself is additionally mounted on four square ‘feet’ cut from an eraser and superglued into place.

Delicate mounting procedure

Mounting the board in the case needed a bit of forward planning. Wires had to be attached to the switches and LEDs before threading them out through the end of the case and then soldering them to the board. Before slotting the board back into the case and gluing it to the bottom.

The painted emitter

Here’s the finished item after painting and sealing with a lacquer. The front end-cap has a hole drilled to allow the IR LED to shine through and the rear cap pops off to expose the AA battery pack which slides out for easy access.

Receiver Design

Very simple circuit

Thanks in no small part to the high level of integration offered by the Vishay TSOP4038 we can use the application circuit given by Vishay in the datasheet for the device. Just one resistor and one capacitor are required as external components. I supply 5V and ground from the Arduino and the output goes back to an input pin on the Arduino.

The stripboard layout

The stripboard layout reflects the simplicity of the circuit. As with the emitter I have left a little extra space at the corners to mount the rubber ‘feet’ that I cut from a pencil eraser.

The receiver stripboard build with two of the three leads connected

The receiver software

The receiver software is a little more complex than the simple emitter. I designed it to cater for varying strengths of signals, to be resistant to false positives and to operate in two different modes.

Beam break mode

The first mode is beam-break triggering. In this mode the beam is normally detected by the receiver and is interrupted by an object that passes in front of it. This is the mode that can operate at the longest range. The disadvantage is that for photographic purposes you normally need two beams designed to cross at a point where you are focussed otherwise your camera could trigger when the object is out of focus. This might not matter if you have a large memory card and don’t care about getting false triggers.

Beam make mode

The second mode is beam-make triggering. In this mode the beam is normally directed off into space and is interrupted by an object passing through it. The infra-red reflectivity of the object causes a trigger because the beam is bounced back into the receiver.

Software design

The basic steps taken by the software are:

  • Sample the receiver in as tight a loop as we can, remembering a count of highs and a count of lows
  • When a configurable multiple of the beam pulse period (1200µs) has passed, calculate the percentage high’s versus lows that we have received.
  • A perfect unbroken beam would be 50% low, 50% high. We say the beam is broken if the calculated percentage falls outside a configurable percentage range.

A snippet from the class definition that declares the receiver is here:

class IRBeamSensorImpl

	int _acceptRangeLowPercent;
	int _acceptRangeHighPercent;
	int _samples;
	uint32_t _periodMicros;
	Sensor::BeamTriggerActionType _beamTriggerActionType;

	uint32_t _lastSampleWindowStart;
	uint32_t _sampleWindowMicros;
	uint32_t _counter[2];

	bool hasTriggered();

The user configurable variables (lines 5 to 9) are configured using my management user interface, the code for which is not shown here – it’s far too involved and is way beyond the scope of this article. Here’s a few photographs of the the part of the interface that configures these variables:

Screen one of the configuration interface

The period looks a bit dull in the photograph because it’s blinking during the exposure!

Screen two of the configuration interface

The ‘Trigger: single’ setting is a general configuration option for all my phototrap sensors and is not related directly to this IR sensor. What it does is configure the unit to either fire once when the sensor is activated or continually fire until the sensor is no longer activated.

The state variables are set up thus:


The method that manipulates these state variables to determine whether the unit has triggered is shown here. The original code has some extra calculations to convert how far away a percentage is from being triggered and convert that to a ‘signal strength’ meter that is continually displayed by the unit.

bool IRBeamSensorImpl::hasTriggered()
	uint32_t now;
	int 		 percent;
	bool		 outOfRange;


		_lastSampleWindowStart=0;      // must have wrapped, start again

// starting again?


		_counter[!!digitalRead(_receiverPin)]++;		// take a sample
	// calc the percent high


	// we're done ready for next time


	// check if percentage is outside range

		outOfRange=percent<_acceptRangeLowPercent || 

				return true;       // triggered
				return true;
	return false;


Test results

I tested the range of the emitter/receiver combination outside on a summer’s evening with the setting sun pointing directly at the receiver. I ran out of patio space at 15 metres and at that distance the signal was still full strength. Distances of 20 metres or more should be easily achieved by this design.

Article series index

Use the following links to navigate through this series of articles.

Part 1: Design
Part 2: The control unit electronics
Part 3: Control unit assembly
Part 4: The operating system Coming soon!
Part 5: The infra-red beam sensor You are here.
Part 6: The X-band radar sensor Coming soon!
Part 7: The PIR infra-red sensor Coming soon!
Part 8: The lightning trigger Coming soon!
Part 9: The ultrasonic trigger Coming soon!
Part 10: The sonic trigger Coming soon!
Part 11: The laser trigger Coming soon!
  • ron mayes

    Andy – thanks for this enlightening description of your work. I am just coming out of the naive stage and beginning to look at the work others gave done, I own a Phototrap and it works fine, however, cannot resist building my own, I am a science (Chem major) person by education, received my degree in the pre-computer days, so your comments on code are above my level of understanding. Nevertheless, I understand the logic of what you are doing and it has been a great help.

    In an effort to make sure I am understanding the bigger picture, I do have a question. When i look at the pulse size of 600 microseconds in your Phototrap type device, the on time for 38,000 successive pulses is about 22 seconds (38,000 cycles/second x .0006 second). In my way of thinking, the total on time of 38,000 successive pulses would have to be less than 1 second, as there is off time between the pulses. I think the math would work (at least the way I think about it) if the pulse size was 6 microseconds, as the duty cycle would be about 25 % (actually between 22 – 23 %) as 38,000 pulses at 6 microseconds per pulse is about .228 seconds, or about 25% of 1 second.

    If you could comment I would appreciate.

    Also, for reasons of simplicity and lack of programming knowledge, I may need to use at 555 timer or a Picaxe 08M microprocessor rather than the ATiny (playing within my game so to speak). Any suggestions here?

    Also, I found a IR emitter that might have an edge in terms of power (relative to the TSAL6200) and want to give myself every advantage. Could you comment on this one (Vishay TSTS7100)

    Thanks for the information already provided. It has been a big help. Any additional comments would be greatly appreciated.


    • Simon

      Hi Ron,
      Let me help you by describing the behaviour of the detector a bit more. The TSOP4038 is a very sensitive receiver. Think of it much like a radio receiver. A radio receiver is able to receive signals that are about to sink into the background noise. At the same time a radio receiver can receive a local station too. It uses an adaptable amplification for this. And so does the TSOP4038. It “listens” to the optical signals and adjusts the amplification so that it just does not receive anything given the ambient light conditions. So there is no noise coming fron the TSOP4038 as is with a normal radio. You can imagine that an optical receiver may look into the black of night, or be put in a artificially lit room of the sun may flood the room. Very different light conditions. Still the TSOP4038 adjusts the amplification and is able to detect the 38kHz signal.
      For this to work the TSOP4038 has to see “no signal” for most of the time. That is why you should send short bursts of the 38kHz signal. So that the amplifier can adjust when there is no signal. Actually, if you are sending a 38kHz signal 100% of the time you would see that the TSOP4038 will give you a signal for a few milliseconds, maybe a second, after enabling the transmitter and then it switches off. That is because the amplifier is adjusted so that the continues light level does not give an output signal. Even when it is a 38kHz signal.
      So what is done in the above project is that 38000 x 0.0006 = 23 pulses are generated, and then there is a pause. The TSOP4038 will give a signal for each burst of 38kHz signal it sees. So you will see 0,6ms pulses on the output of the TSOP4038, not the 38kHz signal.
      Now you say I am not into programming. One answer is maybe; it would be fun; you can make wonderful things for no money. Using the processor, just an 8-pin dip, we are able to make any signal at the correct frequency, with exactly 23 full pulses and wait an exact time between the bursts. The processor has an internal oscillator and the signals will be pretty accurate. The TSOP4038 likes this as it is most sensitive for 38,0kHz signals, and less sensitive for 37kHz of 39kHz.
      Well if you stick to hardware I would suggest you use CD4060 and with some diodes (to make an OR) you should be good to make a reasonable 38kHz signal and a synchronous burst/pause signal. You will get it to work but either when it gets cold (next winter) or when it gets old (next year) it will fail as the frequency will wander off. Not so with the processor and eventually you could even use a crystal but with a processor you will not need a strange frequency as you have N-dividers at your disposal.
      I hope this helps (you to a new hobby).

      • Hi Simon, brilliant explanation, better than I ever could have done. Thanks!

      • ron mayes

        Thanks Simon for reading my question and for your well informed/concise response. That cleared things up. Thank You!

  • Peter

    i am curious to know why the addition of the 100 Ohm resistor in parallel with the emitter improves the switching characteristics.

    • Grumpy_Mike

      The simple answer is it doesn’t. It is an artifact of the measurement. Also the LED is only rated for 200mA peak forward current on a continuous cycle so the actual light output of the circuit will be shot by giving it a 1R resistor. The surge current which the author thinks is some sort of rating you can run the LED at is a one off pulse not part of a PWM cycle.

  • Samir Suneja

    I am new to the arduino world , but want to have a trip beam for photography , little confused where to start .. have ordered the arduino and Attiny , but what exactly to programe in the attiny and how ot use the libraries is confusing me

  • Samir Suneja

    HI Andy , me too trying my hand at building a personal Photo trap and by large yours is the most feasible approach as the infra red noise can really be handled by your approach .
    I have just been able to program a Attiny with a fuse of 8 Mhz and get a Arduino ISP going , but now am stuck as have no prior experience with these chips ..please help with a step by step guide if possible in how to put the emitter code in the attiny.
    Your guidance is appreciated …

    • Hi Samir, I’ve just started a forum topic on this subject. I’ve posted the .hex firmware file ready for flashing to the ATtiny.

  • I just played a lazer game and was curious about the tech inside, of course I was not allowed to dismount the rifles but I watched them carefully and noticed they had two shots mode, one “grenade” with large field but short range (10-15m) with 4 IR LED grouped in a square and one long range with a big loupe two or three times the diameter of yours I think, with up to 150m range long !!!

    3 IR receivers spread around the helmet that handle 360° shots hit.

    All communication between helmets, rifles and the server is done using some RF emitters/receivers

    Look at this here :

  • Luciano Bono

    Hi Andy, awesome job! I’m working on something like this, but for a security system . When attempting to download the firmware link transmitter fallen meeting , not meeting the receiver , is it some other posible download link ? Regards

  • Carpenter Family

    Love it !!!

  • Rodrigo Forrequi

    What program do you use for schematic draw? Really sweet.