Introduction: Sensor for Railway Layout Automation

Picture of Sensor for Railway Layout Automation

Over time, I will add steps in this post, gradually complicating the project. The first three steps explain the choice of sensors, their installation and working example. I use Arduino, but you can use whatever electronic devices.

In this part, an simple example of signaling of a interlocking. The train turns on the red signal when passing the traffic light, and returns the green signal as leaving the block section.

The same principle can be applied to the railway crossing for the movement of the gates and all that.

Step 1: Hall Effect Magnetic Sensor Module

Picture of Hall Effect Magnetic Sensor Module

I used Hall sensors as train detector triggers on the line, known Arduino devices and URB block, but you can use breadboard. There are many types of Hall Effect sensors. For applications where the speed of detection is not crucial, ordinary Hall Effect sensors like 44E can be used.

I apply cylinder neodymium magnets because it's convenient. You can fasten them anywhere metal part of the train, both at the beginning and at the end. Also you can put magnets on both the first and the last cars, then the logic of switching signals will become even more interesting.

Step 2: Schematics

Picture of Schematics

This is a very simple example and it works when the locomotive moves in any direction. You can add to it your logic of signaling behavior, for example parity or counter. Also you can install more sensors and so on.

Step 3: Code

Picture of Code
// arduinorailwaycontrol.com
// SimpleHall.ino
// 19.10.2017 // Author: Steve Massikker //// GPIO PINS //// #define HALL_1 2 #define HALL_2 3 #define RED_SIGNAL 10 #define GREEN_SIGNAL 11 //// VARIABLES //// boolean interlocking_state; void setup() { // Initialize GPIO pinMode(HALL_1, INPUT); pinMode(HALL_2, INPUT); pinMode(RED_SIGNAL, OUTPUT); pinMode(GREEN_SIGNAL, OUTPUT); // On start or reset interlocking_state = true; // Line free digitalWrite(RED_SIGNAL, LOW); digitalWrite(GREEN_SIGNAL, HIGH); } void loop() { if (digitalRead(HALL_1) == LOW || digitalRead(HALL_2) == LOW) { interlocking_state = !interlocking_state; delay(200); } if (interlocking_state) { //true digitalWrite(RED_SIGNAL, LOW); digitalWrite(GREEN_SIGNAL, HIGH); } else { digitalWrite(RED_SIGNAL, HIGH); digitalWrite(GREEN_SIGNAL, LOW); } }

Step 4: Interlocking

Picture of Interlocking

Let's complicate our scheme. Now we divide the line into two sections. At the entrance of the each section we'll put the signal and let's go the train in a circle. There is one problem: if the train stops right above the sensor, then our previous sketch will get chaos.

The problem can be solved in many ways, but the most obvious and simple (at the same time get rid of "delay (200);" in the sketch) to put two sensors, instead of one. These modules are very cheap.

Let's change the scheme (see the code of the sketch):

// arduinorailwaycontrol.com
// SimpleInterlocking.ino
// 16.09.2017
// Author: Steve Massikker

//// GPIO PINS ////

#define HALL_1 2 
#define HALL_2 3
#define HALL_3 4 
#define HALL_4 5
#define HALL_5 6 
#define HALL_6 7
#define RED_SIGNAL_1 8
#define GREEN_SIGNAL_1 9
#define RED_SIGNAL_2 10
#define GREEN_SIGNAL_2 11

//// VARIABLES ////
boolean latch_hall_1 = false, latch_hall_2 = false; 
boolean latch_hall_3 = false, latch_hall_4 = false;
boolean latch_hall_5 = false, latch_hall_6 = false;
boolean point_1, point_2, point_3;

void setup() {

// Initialize GPIO
  pinMode(HALL_1, INPUT); 
  pinMode(HALL_2, INPUT); 
  pinMode(HALL_3, INPUT); 
  pinMode(HALL_4, INPUT);   
  pinMode(HALL_5, INPUT); 
  pinMode(HALL_6, INPUT); 
  pinMode(RED_SIGNAL_1, OUTPUT); 
  pinMode(GREEN_SIGNAL_1, OUTPUT); 
  pinMode(RED_SIGNAL_2, OUTPUT); 
  pinMode(GREEN_SIGNAL_2, OUTPUT);     

// On start or reset
  digitalWrite(RED_SIGNAL_1, LOW);
  digitalWrite(GREEN_SIGNAL_1, HIGH); 
  digitalWrite(RED_SIGNAL_2, LOW);
  digitalWrite(GREEN_SIGNAL_2, HIGH);   
  
}

void loop() {

// HALL //
  if (digitalRead(HALL_1) == LOW) {
    latch_hall_1 = true;
  }
  if (digitalRead(HALL_2) == LOW) {
    latch_hall_2 = true;
  } 
  if (digitalRead(HALL_3) == LOW) {
    latch_hall_3 = true;
  }
  if (digitalRead(HALL_4) == LOW) {
    latch_hall_4 = true;
  }
  if (digitalRead(HALL_5) == LOW) {
    latch_hall_5 = true;
  }
  if (digitalRead(HALL_6) == LOW) {
    latch_hall_6 = true;
  }

// POINT //
  if (latch_hall_1 && latch_hall_2) {
    latch_hall_1 = false;
    latch_hall_2 = false;
    point_1 = false;
  }
  if (latch_hall_2 && latch_hall_3) {
    latch_hall_3 = false;
    latch_hall_4 = false;
    point_2 = false;
  }
  if (latch_hall_4 && latch_hall_5) {
    latch_hall_4 = false;
    latch_hall_5 = false;
    point_3 = false;
  }
  
// LOGIC // 

  if (!point_1) {
    digitalWrite(RED_SIGNAL_1, HIGH); // red
    digitalWrite(GREEN_SIGNAL_1, LOW);     	
  }
  if (!point_2) {
    digitalWrite(RED_SIGNAL_1, LOW); // green
    digitalWrite(GREEN_SIGNAL_1, HIGH);  
    digitalWrite(RED_SIGNAL_2, HIGH); // red
    digitalWrite(GREEN_SIGNAL_2, LOW);
    point_1 = true;         	
  }
  if (!point_3) {
    digitalWrite(RED_SIGNAL_2, LOW); // green
    digitalWrite(GREEN_SIGNAL_2, HIGH);
    point_2 = true;  
    point_3 = true; 
  }
}  

Coming soon next step "Stop train at signal"!

And the gift video - how to make a two-wire signal.

Step 5: Bidirectional Line

Picture of Bidirectional Line

Before I bring the sketch from my real layout, in this post I will give a general solution. It is quite workable and you can apply it in your designs.

In this example, I use a variable of byte type to write the state of the rail blocks. As a result, we are able to transmit this number via bus I2C or serial port. It also makes it possible to perform mathematical operations with data (see the end of the sketch). The principle of recording data in the pictures.

Step 6: Sketch for Bidirectional Railway Line

Picture of Sketch for Bidirectional Railway Line
// arduinorailwaycontrol.com
// TEST_Bidirectional_6_HALLs.ino
// EXAMPLE 5a | 05-05-2016
// Author: Steve Massikker

//// GPIO PINS////

#define HALL_0 2
#define HALL_1 3
#define HALL_2 4
#define HALL_3 5
#define HALL_4 6
#define HALL_5 7

#define LED_0 8
#define LED_1 9
#define LED_2 10
#define LED_3 11
#define LED_4 12

//// VARIABLES////
unsigned long delayMillis;
boolean hall_0, hall_1, hall_2, hall_3, hall_4, hall_5;
byte x;

void setup() {

// Initialize serial
  Serial.begin(9600);

// Initialize GPIO
  pinMode(HALL_0, INPUT);
  pinMode(HALL_1, INPUT);
  pinMode(HALL_2, INPUT);
  pinMode(HALL_3, INPUT);
  pinMode(HALL_4, INPUT);
  pinMode(HALL_5, INPUT);
  pinMode(LED_0, OUTPUT);
  pinMode(LED_1, OUTPUT);
  pinMode(LED_2, OUTPUT);
  pinMode(LED_3, OUTPUT);
  pinMode(LED_4, OUTPUT);

// At start or reset
  bitSet(x, 7); // reserved | not used
  Serial.println(" ");
  Serial.println("Start sketch");
  Serial.println("----------");
  Serial.println("0B76543210");
  Serial.println("----------");

}

void loop() {

// HALLS STATES
  if (digitalRead(HALL_0) == LOW) {
    hall_0 = true;
    bitSet(x, 0);
    delayMillis = millis();
  }
  else hall_0 = false;

  // -------------->
  if (digitalRead(HALL_1) == LOW) { hall_1 = true; bitSet(x, 1); }
  else hall_1 = false;

  if (digitalRead(HALL_2) == LOW) { hall_2 = true; bitSet(x, 2); }
  else hall_2 = false;

  if (digitalRead(HALL_3) == LOW) { hall_3 = true; bitSet(x, 3); }
  else hall_3 = false;

  if (digitalRead(HALL_4) == LOW) { hall_4 = true; bitSet(x, 4); }
  else hall_4 = false;
  // <--------------

  if (digitalRead(HALL_5) == LOW) {
    hall_5 = true;
    bitSet(x, 5);
    delayMillis = millis();
  }
  else hall_5 = false;

  // DIRECTION | bit(6)
  // LR
  if (bitRead(x, 0) == 1) {
    if (hall_1) { bitSet(x, 6); bitClear(x, 0); }
  }
  // RL
  if (bitRead(x, 5) == 1) {
    if (hall_4) { bitClear(x, 6); bitClear(x, 5); }
  }

  // TRANSFER
  if (bitRead(x, 6) == 1) {
    // LR
    if (bitRead(x, 1) == 1) {
      if (hall_2) bitClear(x, 1);
    }

    if (bitRead(x, 2) == 1) {
      if (hall_3) bitClear(x, 2);
    }

    if (bitRead(x, 3) == 1) {
      if (hall_4) bitClear(x, 3);
    }

    if (bitRead(x, 4) == 1) {
      if (hall_5) bitClear(x, 4);
    }
  }
  else {
    // RL
    if (bitRead(x, 4) == 1) {
      if (hall_3) bitClear(x, 4);
    }

    if (bitRead(x, 3) == 1) {
      if (hall_2) bitClear(x, 3);
    }

    if (bitRead(x, 2) == 1) {
      if (hall_1) bitClear(x, 2);
    }

    if (bitRead(x, 1) == 1) {
      if (hall_0) bitClear(x, 1);
    }
  }

// SIGNAL

  if (bitRead(x, 0) == 1) digitalWrite(LED_0, HIGH);
  else digitalWrite(LED_0, LOW);

  if (bitRead(x, 1) == 1) digitalWrite(LED_1, HIGH);
  else digitalWrite(LED_1, LOW);

  if (bitRead(x, 2) == 1) digitalWrite(LED_2, HIGH);
  else digitalWrite(LED_2, LOW);

  if (bitRead(x, 3) == 1) digitalWrite(LED_3, HIGH);
  else digitalWrite(LED_3, LOW);

  if (bitRead(x, 4) == 1) digitalWrite(LED_4, HIGH);
  else digitalWrite(LED_4, LOW);

  if (millis() > (delayMillis + 1000)) { 
    bitClear(x, 0);
    bitClear(x, 5);
  }

// OPTIONAL
  // int number_of_trains_on_distance =
  //   bitRead(x, 1) + bitRead(x, 2) + bitRead(x, 3) + bitRead(x, 4);
  // byte check_free_distance = x << 2;
  //   if (check_free_distance == 0) Serial.print("free");
  //   else Serial.print("trains");

  Serial.print("->");
  Serial.println(x,BIN);

}

Comments

peabody1929 (author)2017-09-15

I am building a Lionel Fastrack Modular railroad. Your signaling scheme looks interesting for it. Would you explain more about the magnets? For example, what type, what size, how thick, how do they attach to the car, what is the distance from the bottom of the magnets to the top of the hall effect sensor, etc. A couple of pictures of the underside of a car with magnets would be great.

Oh! My Mistake... The most common cylinder neodymium magnets. There are so many shapes and sizes, choose any. I bought 50 pieces "N52 Magnets 3x1 mm Neodymium Disc small Cylinder round Rare Earth" for only $ 2. Hall sensors favorite toy of Arduiners and there are a lot of video about them. Distance for operation 1-5 mm.

tomatoskins (author)2017-09-15

Such a cool idea! Thank for sharing and welcome to instructables!

Thank you! I will try!

About This Instructable

1,371views

15favorites

License:

Bio: Hello. Main name is Steve. I'm designer and former engineer from Moscow.
More by Steve Massikker:Let's Add a Few New Parts to the Diagram Model Train Control on ArduinoSensor for Railway Layout AutomationModel Train Control on Arduino
Add instructable to: