Two-trains-interaction with photosensors

Now that we can control 1 train with arduino, it’s time to add a second one.
We made a track where the two trains share a part of the track, but also each have an individual part of the track. In this case we can let a train wait on his own track, while the other train uses the shared part of the track.
How do we know when the other train can start? We will be using photosensors for this.

On this track we placed two photosensors. What we want is when a train goes over a photosensor, it has to be stopped and the other train has to be started.


Our arduino circuit now looks a bit more complicated than in our previous post:


The IR-LED stays the same, connect it to an arduino port (we use port 13) and use a resistor to connect it to ground so it doesn’t burn out (see our previous post).
New in this schematic are the two photoresistors (LDR) which we connect to 5V and, the other leg of the sensor, to an analog port to read the value. They are analog inputs and the value we will get back will be between 0 and 1024. In this example we use the analog ports A0 and A1 on the arduino. Also connect another resistor after the photoresistor (they will be in series). This will create a voltage divider: more information here.

The code looks like this:

#include <legopowerfunctions.h>

LEGOPowerFunctions lego(13);
int sensorInnerTrack = A0;
int sensorOuterTrack = A1;

int threshold = 500;
boolean wasInnerTrackTrainOnSensor = false;
boolean wasOuterTrackTrainOnSensor = false;

What does this do so far?
We import the LegoPF library and define that our IR-LED is connected to port 13.
We also define our two photoresistors which are connected to analog input ports A0 and A1.
We also need some kind of threshold value. We expect the photoresistors to give this value or lower when a train is going over the photoresistor.
The booleans wasXTrackTrainOnSensor are necessary to know the previous state of the train. We don’t want to keep stopping the train when it’s still on the photoresistor, and if the two trains are “parked” on the photoresistors we need to know which one was driving before so we can start the other one.

Next up is the setup method:

void setup(){

Serial.begin(9600) is for ‘debugging’ purposes. You need to write this in the setup method if you want some output in the Serial Monitor later.

We start one of the trains, it doesn’t really matter which one. We do this by calling an extra method we defined next to the loop and setup method. We will also need methods to start the other train and two methods to stop the trains:

void startOuterTrackTrain(){
   lego.SingleOutput(0, PWM_FWD4, BLUE, CH2);
void startInnerTrackTrain(){
   lego.SingleOutput(0, PWM_FWD4, BLUE, CH1);
void stopOuterTrackTrain(){
   lego.SingleOutput(0, PWM_FLT, BLUE, CH2);
void stopInnerTrackTrain(){
   lego.SingleOutput(0, PWM_FLT, BLUE, CH1);

The PWM_FLT and PWM_FWD4 are the speeds of the train (stop and speed 4), and the other parameters tell us on which channels the signal will be sent. Our inner track train drives on the channel BLUE CH1 and the outer track train is on BLUE CH2.

The loop method will go like this:

void loop(){

   boolean isInnerTrackTrainOnSensor = analogRead(sensorInnerTrack) < threshold;
   boolean isOuterTrackTrainOnSensor = analogRead(sensorOuterTrack) < threshold;

   if(isInnerTrackTrainOnSensor && !wasInnerTrackTrainOnSensor){
   } else if(isOuterTrackTrainOnSensor && !wasOuterTrackTrainOnSensor){

   wasInnerTrackTrainOnSensor = isInnerTrackTrainOnSensor;
   wasOuterTrackTrainOnSensor = isOuterTrackTrainOnSensor;

The Serial.print-methods in the beginning are our ‘debug’ lines. It will print things to the Serial Monitor which you can find in the Arduino IDE under Tools > Serial Monitor.

We have to read the sensor values by using analogRead(). We immediately check if this is higher or lower than our predefined threshold value. This way we know if the train is standing above one of the sensors or not.
After that we need to stop and start the trains. If a train is standing over a sensor and wasn’t previously there, we need to stop that train and start the other one.
And last but not least, store the value of the sensor in the ‘previous’ value state so we know in the next loop if the train was standing over the sensor or not.

After Thoughts:

  • This way of working is fine, maybe even better suited if you work with 9V trains because your sensor will allow you to stop and start any train on that specific track.
  • With our Power Functions experiment, however, we run into complications as this setup needs to be fixed. Fixed in the way that you need to know which train is where at all times, because we need to send the signals to the trains on specific channels, we can’t just let any random train stop at the sensor.
  • If we were would drag this project further out, we would need to have the trains running on a fixed parcours at all times.
  • To make it more dynamic we’d need a way to indentify the trains at certain key points in the track. For this we’re looking at RFID but at the time of writing our hardware hasn’t arrived yet so we don’t know how succesful this solution can be.

14 thoughts on “Two-trains-interaction with photosensors

  1. Hi,

    Is this still a ongoing project or you’ve parked it?

    Really interested in this as I’m just starting to source all the bits and bobs to put my trains and arduino to good use….

    Cheers for what you’ve shared so far. It’s going to help me a lot I’m sure.

    • We have been testing some rfid-readers, some obstacle sensors (to use instead of the photo resistors) and some train track switching. At the moment, we haven’t got any setup/code that’s stable enough to make a blog post out of it.

      • Yeah, I’m thinking rfid to do some track switching, but using obstacle sensors instead of photoresistors would involve some sort of wireless communication, right? I’m thinking zigbee, x10,etc. Might has well just replace IR with that as well, and go full wireless (with a pc controlling the entire thing, knowing exactly who is who, and where they are)… I know, I know…. Too much hassle… Thinking too ahead! When I start I’ll share my project to show what I’ve accomplished. Cheers

      • Its been a while, but currently I’m using reed contacts and a little magnet on the front of the train. This works really well, except it isn’t wireless, but seems really stable. Just a couple of cents from me again πŸ˜‰

    • The Lego trains can be set on 4 channels on BLUE or RED, which means you can control 8 trains. When you put the train together, you have to choose this. On the motor of the train you have a red connection and a blue one, together with some sort of slider (I think it’s orange) which is the channel. The channel on which you’re train is set is the channel you have to use in your arduino program.

  2. Hey, epic cool project you got going there! I can’t wait till I get my own hardware and setup a similar situation. I think it should be possible to mimick a real situation. What the actual railway does is setup the track in blocks of a certain length (in real life somewhere between 1km and 2km). The trick is to keep track of the train, but if you have a reference point where Train A enters block A you know exactly where all your trains are. After that it should also be fairly simple to automate the whole proces using signals, switches etc.

    So basically, you need an Entrance Point and an Exit Point, keep track of that and you are on the right track (they call it NX-platform in the Dutch Railways, maybe you can use that to find some more info).

  3. gololo says:

    I was wondering if you can share something about the RFiD’s you’ve tested.
    LIke models, results, problems and so on. I’m very much interested =)

  4. JoJo says:

    The train/track is 8 wide. Would it be possible to use some kind of binary code underneath the train? With lightsensors detecting the presence of bit? A 1×8(left to right), with 8 1×1 positions at the bottom. Bit 1 up to eight. First bit is to detect presence of “barcode-strip”. Minus de track, cause of the passing wheels. Makes 5 bits/positions. 5×5 makes 25 options.

    Cause 8 trains is the have a way to detect the end of a train.

    In your example you’re using a track divided in 3 parts. Every part of the track needs a sensor at the start end end. Divide long tracks in parts and let trains share track.

    Just some midnights thoughts….

    • zwiep666 says:

      This is something we considered for a while and even tested very roughly. the photo sensors we were using at that time were barely able to get a decent read off the “bar codes”. We know there’s people who replaced the sensors with small optical camera’s (like those used in computer mice) but we eventually opted to try identifying trains with RFID.
      Also with what Bastiaan suggested a few comments earlier, it is possible to know the whereabouts of each train with only a few identifying points, thus eliminating the need for RFID sensors all over the tracks, using the cheaper optical sensors to detect whether or not a train has passed.
      These are things that are on the TO DO list but lately we haven’t had a lot of time to work on this project, we hope to make a new blog post soon with some new things.

      • Jojo says:

        Would it be an idea to post some details of your attempts? What didn’t work? What did you use in your tests?
        I’m diving into this stuff right now. Some other people on this site as well. Maybe we can learn from your attempts and try something different.

        No need to post this on the site by the way.

        If I’m obtrusive, sorry for that πŸ˜‰

  5. At the moment I’m considering using simple reed contacts on the train or track with some strong rare earth magnets. You can possibly use those at both ends of the train so you can even figure out if the train is bigger than the currently occupied block. Just a little insight I got recently πŸ™‚

    • That is so awesome! It looks like it’s running very well. Currently I’m building sort of “decoders” from Arduino microprocessors. The result, with an awesome app named Blynk, has lead to this:

      I’ve ordered some color-meters to see if they can provide any assistance in determining which train is where as to get an accurate reading of the blocks.

      I’d love to get some details of your motorized switches!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s