Laser Train Detection
Revised 11-26-14   1-4-17

The objective of this project is to design and construct a system that uses inexpensive lasers to detect the passage of a model train.  Several different versions will be made. 

The simplest will use a single laser to activate a relay whenever the laser beam is broken.  The circuit will require only a few parts:  the laser, a phototransistor, two transistors, a relay and a few resistors.

The other versions will include a PIC, PICAXE or Arduino microcontroller that will allow more sophisticated detection and operation.

It is also important to stress that, even though this article deals specifically with model railroads, there are many, many applications for the detection systems described here in other areas. 



I have used a number of train detection methods on both my garden railroad and my HO modular layout.  All have advantages and disadvantages many of which are spelled out in great detail in articles on my web page (see "Sensors" at: ). 

Up until now my favorite way of detecting a train as it passes a point on my layout has been to use pulsed infrared sensors.  These sensors use an infrared LED that is pulsed on and off at 38 KHz and an infrared detector that only reacts to pulses at that frequency.  The emitter and detector are placed across the track from one another so that the beam of light is broken when a train passes.  They are reliable and almost completely immune from interference from sunlight and other sources of light in the environment surrounding a garden railroad.  Their primary disadvantages are

  1. circuit complexity
  2. the need for a microcontroller or 555 timer to generate the pulses
  3. difficulty in aiming an invisible IR beam
  4. relatively short range.

Recently I began experimenting with lasers and found that the circuitry needed to use them can be very simple and that their range can be quite impressive.  Since their light is visible aiming & alignment are much easier.  Up until now their main disadvantage was that you had to disassemble a laser pointer to acquire a small laser.  Once you got the laser out of the laser pointer you still had to deal with the fact that most of these laser modules aren't designed for operation at 5 volts and that they frequently failed when put into continuous duty service.

The need to cannibalize laser pointers disappeared when I found a vendor in China (  ) that could supply me with very small laser modules that are ideal for model railroad use.  They contain a voltage regulator that allows them to function over a range of voltages from 3.5 to about 5 volts.  More importantly, they are designed to run continuously, not just while someone pushes a button on a laser pointer.

The units are about 9mm (23/64") in diameter and 20mm (3/4") long.  This makes them easy to hide on a layout.

The distance that can separate the laser module from the sensor also allows for detecting a train while it occupies a large section of track rather than just when it crosses a point on the layout.  This really simplifies how the sensors can be used and it really took care of a major sensing problem I was having with my modular HO layout.

My module (see photo and ) is 8 feet long and has a mining train that crosses the main line as it works its way up a mountain using switchbacks.  When a main line train enters the module my mining locomotive needs to stop so that the two don't collide at the crossing! 

Before examining the diagrams below you may want to view a YouTube video of the module in operation:


The troublesome crossing is circled in red in the drawing below.  The main line is in yellow.

Here the same crossing is circled in a photo of the module.  The computer controlled mining train goes up and down the mountain on a series of switchbacks while the main line (seen coming onto the module at the top) takes the low road.

My first detection system used two laser sensors (shown as red lines in the drawing below), one at either end of the module.  If one beam was broken the mining train would not enter the crossing until the beam at the other end was broken and then left unbroken for a number of seconds.  This worked very well except for the times when two trains were close together on the main line or when the main line train hit one of the sensors and reversed its direction of travel before hitting the second sensor.  If it went around the layout backwards and hit the sensor at the other end of the module the circuitry on the module thought the train had just passed and the mining train happily (and tragically!) entered the crossing in front of  the on-coming train.  This might have been A-OK with Gomez from the Munsters but others in the modular group were none too happy! (see:

Since we were using DCC (Digital Command Control - a computer-based method of operating trains that always has voltage on the track) I next considered using current detectors that sensed when a locomotive was on the track and drawing power.  That might have worked were it not for the very long trains that we frequently run on the module.  We had one running on the layout that had a locomotive, 50 coal cars and a caboose!  Since the current detectors only detect cars (or locomotives) that are using power I would have had to modify many of the coal cars and the caboose so that a current would have been drawn when they were on the track.

I had to find a better way as I didn't want to modify other railroader's trains to solve my problem.  I settled on a laser detector that projected its beam across most of the main line track.  Any time any train or part of a train broke the laser beam the mining train would be held back from the crossing.  In the diagram below the long red line shows the path of the laser beam.  It parallels the main line before and after the crossing and reliably detects a train approaching the crossing.

Advantages & Disadvantages of this System


  • Detection over a great distance.  Lasers can easily project their beam for hundreds of feet
  • Visible light for alignment.  Since the laser beam is red it is clearly visible when the system is being aligned
  • Circuit simplicity.  The laser does not need to be pulsed and the sensor is a simple phototransistor.


  • The laser beam is visible.  While the beam is difficult to detect under many circumstances it will be clearly visible as it shines on the train it is detecting when the beam is broken.  (note: see the section on microcontroller managed lasers for a way around this)
  • Alignment is critical.  The laser beam is highly focused and must be accurately aimed and securely mounted so that it falls directly onto the lens of the phototransistor.

Two Different Ways to Use the Lasers
I have been experimenting with using the lasers in two different ways.  The simplest utilizes a phototransistor and a one transistor circuit to activate a relay.  This is a simple way to test out the capabilities of the laser sensors and is more than adequate for many applications.

The second implementation makes use of a microcontroller, a PIC 16F684, a PICAXE 14M2 or an Arduino, to activate the laser and detect if its beam has been broken.  As you can imagine the use of the microcontroller allows a good bit more flexibility in setting up and using the laser.  And, I was pleasantly surprised to discover, can control the laser's beam in such a way that it becomes virtually undetectable.

The Basic Laser Sensor

If you take a moment to look over the next schematic you will see that there isn't much to this design.  The laser operates from the same 12 volt power supply as the rest of the circuit.  The 220 ohm resistor, R5, in series with the laser's positive lead limits the amount of current that is available to the laser.

The phototransistor, Q1, detects the presence of the laser light and, through transistor Q2, activates relay RLY1 and test LED, D3, which gives a visual indication of the laser being detected.


The second schematic is almost identical except for the addition of another transistor that reverses the behavior of the relay.  In the first circuit the relay pulls in when light is detected.  In the second the relay pulls in when no laser light is detected and releases when the laser light is seen.  The second circuit may be a better choice if you are running from batteries or some other low power source as it does not activate the relay's coil when the laser beam is unbroken, only on those less frequent occasions when a train passes.


The prototype for this circuit was put together on a small piece of project board.  The relay is at the top and the two transistor circuitry is to its left.  The phototransistor is in the lower left.  It has a small piece of heat shrink tubing over the lens to shield it from ambient light.

When connecting the phototransistor the emitter is closest to the tab.  The middle lead, the base, is not used and can be clipped off.

Parts list for basic circuit
Microcontroller Managed Lasers

A microcontroller such as a Microchip PIC 16F684 can be used to make a much more sophisticated laser sensor than what was described above.  Such a circuit will allow you to, for example, have the relay always stay on for a minimum of 5 seconds each time it is activated or only latch on after the laser beam has been broken for a set number of seconds or after a set number of beam-breaks.

As you can see from the PIC schematic the microcontroller not only connects to the phototransistor, Q1, but it also controls the laser, D2, so that it can be turned on or off.  The relay is triggered by pin 6 on the PIC through transistor Q2.  LED D3 is an indicator and the switch connected to pin 3 is used for setting up the sensor.

R5, shown as a 10K resistor, pulls the emitter of the photo transistor low and can be adjusted to make the circuit more or less sensitive.  I have used a 22K resistor to make it much more sensitive to the pulsed laser beam.


Test Software
Everything up to the first DEBUG statement sets up the microcontroller and its pins.  The DEBUG function was used for testing.  It connected to the computer's serial port so that test information could be seen in real time with HyperTerminal or a similar terminal program.

This program simply turns on the laser and activates the relay and test LED if the beam is seen and turns them off if it is not.

DEFINE DEBUG_BIT 0                'pin 13
DEFINE DEBUG_MODE 1     	  'Set DEBUG mode: 0 = true, 1 = inverted
ansel=0               		  'use pins as digital rather than analog
CMCON0= 7              		  'Disable comparator - makes portc LEDs work properly
DEFINE OSC 8            	  'use 8 mhz oscillator
OSCCON = $70            	  'set clock speed 
INTCON = %00001100      	  '00xx11xx to be CCP1 mode
option_reg.7     =0   		  'turn on Weak Pull Ups on PortA
wpu              = %00010000	  'Weak Pull Ups -  a.4 for ModeSwitch
SerialOut        VAR porta.0      'pin 13 for testing
PhotoTran        VAR portc.0      'pin 10 to Phototransistor
Laser            VAR portc.1      'pin 9 controls laser on/off
LED1             VAR porta.2      'pin 11 indicator LED
Relay            VAR portc.4      'pin 6 activate relay
trisa            = %00010000   'all outputs but a.4, pushbutton switch  
trisc            = %00000001   'all outputs but c.0, phototransistor

DEBUG 10,13,"Laser Test v2.0 ",10,13
DEBUG "(c) d. bodnar 05-21-10",10,13

HIGH Laser
IF PhotoTran=1 THEN
    HIGH LED1:HIGH Relay
    DEBUG "Hit",10,13
    LOW LED1:LOW Relay



Parts list for PIC version

An Interesting Discovery
Once I got the test software working and as my experiments with it progressed a very interesting capability came to light, no pun intended. I set up a simple test to determine if the microcontroller could detect the laser beam hitting the phototransistor using the software above. The test worked very well and got me wondering how long a pulse of laser light needed to be for the phototransistor to detect it.  This was of interest to me because, if the pulse were short enough, I might be able to make the laser light less visible to visitors observing the modular layout.  I reasoned that I could generate a short pulse of light, say 1/10 second long, every 1/2 second, that might be harder to see.

I modified the software so that the laser would be turned on and left on for 0.1 seconds using a PAUSE 100 command.  Then the program looks at the phototransistor, activates the relay and LED if it sees the laser and then turns the laser off for 0.4 seconds.  This has the system check the laser twice each second with the laser only being on for two 1/10 second periods each second. 

The program worked well and the laser light pulses were less obvious as I had hoped but they were still clearly detectable.  I wondered just how short a pulse the phototransistor and PIC could detect.  I kept reducing the PAUSE statement until I got to PAUSE 1 (a pause of 1/1000 second) and everything still worked perfectly!  Now each pulse only lasted one thousandth of a second and the laser beam was all but undetectable.

Since I still had not yet found the "bottom" of the unit's sensitivity I switched from using the PAUSE statement, which works in 1/1000 of a second increments, to the PAUSEUS statement that works in 1/1000000 of a second steps.  I was completely amazed when I started decreasing the PAUSEUS statement over and over testing every shorter pulses until I got to PAUSEUS 1 and it still worked!  A bit of reading through the PICBASIC PRO manual told me that the pauses are really more like 10 or 20us because of the 16F684's clock speed.  Nonetheless the pulses were so brief that even placing a piece of white paper directly in front of the laser in a darkened room barely made the beam detectable.

To check the actual length of time that the laser was on I hooked the circuit up to my logic analyzer.  This clip from the logic analyzer's screen confirms that one pulse lasts 20 us. 

Pulsed Laser Software
DEFINE DEBUG_BIT 0         ' PIN 8 on 16f88
DEFINE DEBUG_MODE 1     ' Set 'DEBUG mode: 0 = true, 1 = inverted
ansel=0                 'use pins as digital rather than analog
CMCON0= 7               'Disable comparator - makes portc LEDs work properly
DEFINE OSC 8            'use 8 mhz oscillator
OSCCON = $70            'set clock speed
INTCON = %00001100       '00xx11xx to be CCP1 mode
option_reg.7     =0   'turn on wpu PortA
wpu              = %00010000  'just a.4 for ModeSwitch
SerialOut        VAR porta.0      'pin 13
NotUseda1        VAR porta.1      'pin 12
PhotoTran        VAR portc.0      'pin 10
Laser            VAR portc.1      'pin 9
NotUseda3        VAR porta.3      'pin 4
FullBright       VAR porta.4      'pin 3 - switch to brighten laser for alignment
LED1             VAR porta.2      'pin 11
NotUseda5        VAR porta.5      'pin 2
'Laser            var portc.2      'pin 8  ' from pin that drove LED transistor
NotUsedc3        VAR portc.3      'pin 7  ' from pin on board to LED driver base
Relay            VAR portc.4      'pin 6  ' to meter on circuit board (R 21)
NotUsedc5        VAR portc.5      'pin 5  ' output to 16 ohm speaker through cap
Temp             VAR WORD
Hit              VAR BIT
trisa            = %00010000    
trisc            = %00000001   

DEBUG 10,13,"Laser Test v2.0 "
DEBUG "(c) d. bodnar 07-14-10",10,13

'this routine gives 20 us pulses / 10 per second
HIGH Laser
IF PhotoTran=1 THEN
    HIGH LED1:HIGH Relay
    LOW LED1:LOW Relay
Laser=FullBright   'set laser to value of pushbutton switch  / on or off
PAUSE 100 'check every 1/10 second - increase this pause to make it even dimmer


An "Aiming" Switch
The brief pulses made the laser beam so dim that it was no longer possible to reliably see the beam to aim it at the phototransistor.  Fortunately the addition of a switch and a minor change to the software took care of the problem.  When the switch is open the laser light is on just for a brief period of time.  If the switch is closed the laser light never dims making it quite visible and very easy to aim.
' 04-23-10  
 ' turns laser on for 5 us then tests phototransistor to see if it "sees" laser
 ' demonstrates that a very fast pulse of the laser is enough to detect
 ' effectively dims the laser 
 ' Tests several hundred times / second
DEFINE DEBUG_BIT 0         ' PIN 8 on 16f88
DEFINE DEBUG_MODE 1     ' Set 'DEBUG mode: 0 = true, 1 = inverted
ansel=0                 'use pins as digital rather than analog
CMCON0= 7               'Disable comparator - makes portc LEDs work properly
DEFINE OSC 8            'use 8 mhz oscillator
OSCCON = $70            'set clock speed 
INTCON = %00001100       '00xx11xx to be CCP1 mode
option_reg.7     =0   'turn on wpu PortA
wpu              = %00010000  'just a.4 for ModeSwitch
SerialOut        VAR porta.0      'pin 13
NotUseda1        VAR porta.1      'pin 12
PhotoTran        VAR portc.0      'pin 10 
Laser            VAR portc.1      'pin 9
NotUseda3        VAR porta.3      'pin 4
FullBright       VAR porta.4      'pin 3 - switch to brighten laser for alignment
LED1             VAR porta.2      'pin 11
NotUseda5        VAR porta.5      'pin 2
'Laser            var portc.2      'pin 8  ' from pin that drove LED transistor
NotUsedc3        VAR portc.3      'pin 7  ' from pin on board to LED driver base
Relay            VAR portc.4      'pin 6  ' to meter on circuit board (R 21)
NotUsedc5        VAR portc.5      'pin 5  ' output to 16 ohm speaker through cap 
Temp             VAR WORD
Hit              VAR BIT
trisa            = %00010000     
trisc            = %00000001    

DEBUG 10,13,"Laser Test v1.2 "',#seed.byte0," ",#seed.byte1,10,13
DEBUG "(c) d. bodnar 04-23-10",10,13

HIGH Laser
IF PhotoTran=1 THEN
    HIGH LED1:HIGH Relay
    LOW LED1:LOW Relay

IF FullBright=1 THEN LOW Laser 'if switch off dim Laser else leave on full
DEBUG #Hit," "
Variable Brightness
Next I added a potentiometer to the circuit that gives variable brightness control over the laser.  This makes it even easier to use the laser detector over longer distances where the really fast pulses are just too fast and too dim to be reliably detected.  The modified software is here:



'7-29-14 revision underway for revised laser train detector using pot for brightness selection

' 04-23-10
' turns laser on for 5 us then tests phototransistor to see if it "sees" laser
' demonstrates that a very fast pulse of the laser is enough to detect
' effectively dims the laser
' Tests several hundred times / second
DEFINE DEBUG_BIT 0 ' PIN 8 on 16f88
DEFINE DEBUG_MODE 1 ' Set 'DEBUG mode: 0 = true, 1 = inverted
''ansel=0 'use pins as digital rather than analog
CMCON0= 7 'Disable comparator - makes portc LEDs work properly
DEFINE OSC 8 'use 8 mhz oscillator
OSCCON = $70 'set clock speed
INTCON = %00001100 '00xx11xx to be CCP1 mode
option_reg.7 =0 'turn on wpu PortA
wpu = %00010000 'just a.4 for ModeSwitch
ANSEL = 0 ' Analog select set to digital, pg 69 data
ADCON0 = 0 ' A/D turned OFF, pg 68 of data
Define ADC_BITS 8 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 500 ' Set sampling time in uS
ADCON0 = %100001000 ' Set PORTA analog and right justify result
Pot1 VAR portc.3 'pin 7
SerialOut var porta.0 'pin 13
NotUseda1 var porta.1 'pin 12
PhotoTran var portc.0 'pin 10
Laser var portc.1 'pin 9
NotUseda3 var porta.3 'pin 4
FullBright VAR porta.2 'pin 11 - switch to brighten laser for alignment
LED1 var portc.2 'pin 8
NotUseda5 var porta.5 'pin 2
'Laser var portc.2 'pin 8 ' from pin that drove LED transistor
'''NotUsedc3 var portc.3 'pin 7 ' from pin on board to LED driver base
Relay var portc.4 'pin 6 ' to meter on circuit board (R 21)
NotUsedc5 var portc.5 'pin 5 ' output to 16 ohm speaker through cap
Temp var word
Hit var bit
PotValue var word
trisa = %00010100
trisc = %00001001

dEBUG 10,13,"Laser Test v3.0 "',#seed.byte0," ",#seed.byte1,10,13
DEBUG "Using new Timer Board (dated 09-25-2013)",10,13
DEBUG "(c) d. bodnar 07-30-14",10,13
goto top:

if phototran = 1 then
high laser
high led1
low laser
low led1

debug "PT= ",#PhotoTran," FullBright= ",#fullbright, 10,13
goto testing:

adcin 7,potvalue
debug "Report = ",#PotValue,10,13
if potvalue > 250 or potvalue < 5 then
high relay
low relay
goto Testing:

adcin 7,potvalue
potvalue = potvalue * 10
'high led1:pause 500:low led1:pause 500:goto top
high laser
pauseus potvalue
if phototran=1 then
high led1:high relay
low led1:low relay

if fullbright=1 then low laser 'if switch off dim Laser else leave on full
debug #hit," "
pause 10
goto top

Laser Placement & Use of Mirrors
If you prefer to have the laser and the phototransistor on the same side of the track this can be accomplished by placing a small mirror on the other side of the track.  Just bounce the laser beam off of the mirror and back onto the phototransistor.

It takes a bit more work to align the beam, mirror and sensor but works very well once this is done.

PICAXE Program
The PIC microcontroller that I used for initial experiments works very well but requires a special programmer and programming software.  Many hobbyists use PICAXE microcontrollers as they use an inexpensive programmer and the software is free.  The program for the PICAXE is below.  It works in the same way as the software for the PIC.  Functionally it is almost the same, but the slower speed of the PICAXE limits the shortest period of time that the laser can be on.

'd. bodnar 8-1-14
'14M2 laser detector based on PIC version
'working but no where near as dim as
' on the PIC due to clock speed
' and PICAXE overhead

'update - better by using bit variable to
' store phototran value

#NO_DATA 'don't download data - speeds up programming
#PICAXE 14M2 'identify the
SETFREQ m32 'speed it up to 32 MHz
SYMBOL PhotoTran =pinb.3 'physical pin 10
SYMBOL FullBright =pinb.2 'pin 11 - switch to brighten laser for alignment
SYMBOL LED1 =b.5 'pin 8
SYMBOL Laser =b.4 'physical pin 9 on 14m (for PWM only!)
SYMBOL Relay =c.1 'physical pin 13 or 7 on 08m
SYMBOL Temp = w1
SYMBOL POTT =c.0 'physical pin 3
SYMBOL PV = bit1
symbol PotValue = w3

readadc POTT,potvalue
potvalue = potvalue * 10
if potvalue < 20 then
high laser
pauseus potvalue
low laser
if pv=1 then
high led1:high relay
low led1:low relay

if fullbright=1 then
low laser 'if switch off dim Laser else leave on full
high laser
sertxd("PV ", #PotValue," ")
'pause 10
goto topPIC

PICAXE Schematic

Parts for PICAXE version
Schematic - Arduino
The Mini is shown here but any version of the Arduino (Uno, Nano, etc) should work equally well.

Arduino Program
This software should work without modification on the Uno, Mini and Nano.

Laser Train Detector using Arduino UNO v5
int Relay = 3;
int Laser = 2;
int LaserBright = 5;
int sensorPin = 0; // Analog Pin 0 (not pin 0!)
int LaserBrightValue = 0;
int PhotoTransistor = 4;
int potValue = 0; // variable to store the value coming from the Pot
int PTState;
// the setup routine runs once when you press reset:
void setup() {
pinMode(Relay, OUTPUT);
pinMode(Laser, OUTPUT);
pinMode(PhotoTransistor, INPUT);
pinMode(LaserBright, INPUT_PULLUP);

void loop() {
potValue = analogRead(sensorPin);
digitalWrite(Laser, HIGH);
PTState = digitalRead(PhotoTransistor); // wait for a second
LaserBrightValue = digitalRead(LaserBright);
if(LaserBrightValue >0 ) {
digitalWrite(Laser, LOW);

if (PTState == 1)
digitalWrite(Relay, HIGH);
digitalWrite(Relay, LOW);
LaserBrightValue = digitalRead(LaserBright);
Serial.print(" ");



Parts for Arduino version
  • Arduino Uno (or other Arduino) - Amazon or eBay
  • other parts from PIC version except for voltage regulator and capacitors
I have successfully used the circuits described here in a number of model railroading applications. The same idea could be used to make a sensor that would beam across your driveway to announce visitors or to trigger animations on a Halloween display.

I am sure that you have ideas for how this can be used and will find it a simple and reliable system.  Please let me know if I can help ( )