Project showcase
Railway Interlocking System

Railway Interlocking System © Apache-2.0

Create massive train traffic on your own model railway!

  • 4,635 views
  • 10 comments
  • 18 respects

Components and supplies

Ard nano
Arduino Nano R3
×2
Generic Motor-driver L298
×2
Free URB unit
You need to send GERBER file to your PCB manufacturer and assemble the unit yourself
×2
Generic Arduino sensor modules (Hall or IR)
×7
Kingbright wp7113srd d image
5 mm LED: Red
or railway two-lenses signal
×6
Kingbright wp7113sgd
5 mm LED: Green
×4
Mfr 25fbf52 221r sml
Resistor 221 ohm
×5
Mfr 25frf52 10k sml
Resistor 10k ohm
×2

Apps and online services

About this project

I very often see sad videos on the Internet as the lonely train monotonous and boring move on a circle on an excellently making railway layout. You can change this trend, and it's really simple with an Arduino! I'm going to tell you how make a railway interlocking system. But first I'll show you how fun it is.

Interlocking add "live" train traffic scenarios as dynamic changes like dispatching of routes, complex maneuvers and more. At first glance, interlocking system is too difficult to understand. So please watch the next video, I hope that relays your very understandable fears.

In this example, a simple and clear system is built, but you can easily scale it to any size, making several systems between stations or adapt it to your railroad. There are no restrictions in the URB project, just re code Arduino sketches.

Code

COMM unit sketchArduino
// -------------------------------------------------- //
// WWW.ARDUINORAILWAYCONTROL.COM                      //
// comm_urb.ino                                       //
// V.2.0  11/24/2019                                  //
//                                                    //
// SMALL INTERLOCKING                                 //
// For URB unit V.2.FINAL                             //
// 122Hz Thrust contol                                //
// https://arduinorailwaycontrol.com/urb_unit.html    //
//                                                    //
// Author: Steve Massikker                            //
// -------------------------------------------------- //
void(* resetFunc) (void) = 0;

#include <Wire.h>
#include <SoftwareSerial.h>

// Bluetooth module
SoftwareSerial Bluetooth(12, 13); // D12 - RX | D13 - TX

// PWM (SPEED)
#define MD_1_ENA 10 // LINES A, B
#define MD_1_ENB 9  // BLOCK 1
#define MD_2_ENA 11 // BLOCK 3
#define MD_2_ENB 3  // BLOCK 2
// DIRECTION DRIVER A 
#define MD_1_IN1 4  
#define MD_1_IN2 2
// DIRECTION DRIVER B
#define MD_12_IN3_IN3_IN1 5 
#define MD_12_IN4_IN4_IN2 6
// SENSORS
#define SNS_1 17
#define SNS_2 14
#define SNS_3 15
#define SNS_4 7
#define SNS_5 8
#define SNS_6 16
#define SNS_7 A6

// Variables
int addressI2C;
byte dataToI2C;
bool stringComplete = false;
String inputString = "";

  // 24 speed
  byte speedArrayA [] = {30,40,50,60,80,110,140,160,180,200,220,255};
  byte speedTrainA = 0;

  // Interlocking
  unsigned long timerBlock1, timerBlock2, timerBlock3, timerStation;
  byte speedBlock1, speedBlock2, speedBlock3; 
  
  // Dispather AWS
  bool flag_interlocking = false;  
  bool flag_station_open = true;    

  // Sensors
  unsigned long timer_protected_sensor1, timer_protected_sensor3,
                timer_protected_sensor5, timer_protected_sensor7;
  bool protected_sensor1, protected_sensor3, 
       protected_sensor5, protected_sensor7;
  bool sensor_block1_IN, sensor_block2_IN, sensor_block3_IN, 
       sensor_block1_OUT, sensor_block2_OUT, sensor_block3_OUT, 
       sensor_OUT;
  bool latch_stop_block1, latch_stop_block2, latch_stop_block3;
  
  // Latches     
  bool open_block1 = true, open_block2 = true, open_block3 = true;

  // TURNOUTS & SET DEFAULT POSITIONS
  bool switch_A = true, switch_B = false;
      

void setup() {

  // Initializie Serials & I2C
  Serial.begin(9600);
  Bluetooth.begin(9600);
  inputString.reserve(4);
  Wire.begin(); // Set as Master

  // Initialize pins
  pinMode (MD_1_ENA, OUTPUT);
  pinMode (MD_1_ENB, OUTPUT);
  pinMode (MD_2_ENA, OUTPUT);
  pinMode (MD_2_ENB, OUTPUT);  
  pinMode (MD_1_IN1, OUTPUT);
  pinMode (MD_1_IN2, OUTPUT);
  pinMode (MD_12_IN3_IN3_IN1, OUTPUT);
  pinMode (MD_12_IN4_IN4_IN2, OUTPUT);  
  pinMode (SNS_1, INPUT);
  pinMode (SNS_2, INPUT);
  pinMode (SNS_3, INPUT);
  pinMode (SNS_4, INPUT);
  pinMode (SNS_5, INPUT);
  pinMode (SNS_6, INPUT);
  pinMode (SNS_7, INPUT);  

  // Set PWM frequency for D3, D9, D10, D11
  // Timer 1 divisor to 256 for PWM frequency of 122.55 Hz (9, 10)
  TCCR1B = TCCR1B & B11111000 | B00000100;  
  // Timer 2 divisor to 256 for PWM frequency of 122.55 Hz (3, 11)
  TCCR2B = TCCR2B & B11111000 | B00000100; 

  // Set default direction to FORWARD (POLARITY)  NON Interlocking
  digitalWrite(MD_1_IN1, LOW);
  digitalWrite(MD_1_IN2, HIGH); 
  digitalWrite(MD_12_IN3_IN3_IN1, LOW);
  digitalWrite(MD_12_IN4_IN4_IN2, HIGH); 
 
}

void loop() {

  // ----  START PARSING INCOMING APP COMMANDS
  if (stringComplete) {
    // RESET 
    if (inputString =="999z") {
      dataToI2C = 99;
      addressI2C = 2;      
      sendDataViaI2C();
      resetFunc();
    }

    // FUNCTIONS 
    if (inputString.charAt(0) =='a') {
        // Speed   
      if (inputString.charAt(1) =='0') {
        if (inputString.charAt(2) =='0') speedTrainA = 0;
        if (inputString.charAt(2) =='2') speedTrainA = speedArrayA[0];
        if (inputString.charAt(2) =='4') speedTrainA = speedArrayA[1];
        if (inputString.charAt(2) =='6') speedTrainA = speedArrayA[2];
        if (inputString.charAt(2) =='8') speedTrainA = speedArrayA[3]; 
      } 
      if (inputString.charAt(1) =='1') {
        if (inputString.charAt(2) =='0') speedTrainA = speedArrayA[4];
        if (inputString.charAt(2) =='2') speedTrainA = speedArrayA[5];
        if (inputString.charAt(2) =='4') speedTrainA = speedArrayA[6];
        if (inputString.charAt(2) =='6') speedTrainA = speedArrayA[7];
        if (inputString.charAt(2) =='8') speedTrainA = speedArrayA[8];
      }
      if (inputString.charAt(1) =='2') {
        if (inputString.charAt(2) =='0') speedTrainA = speedArrayA[9];
        if (inputString.charAt(2) =='2') speedTrainA = speedArrayA[10];
        if (inputString.charAt(2) =='4') speedTrainA = speedArrayA[11];         
      }

      // Direction and Stop
      if (inputString.charAt(1) =='d') {
        if (inputString.charAt(2) =='f') { // (f) Forward
          digitalWrite(MD_1_IN1, LOW);
          digitalWrite(MD_1_IN2, HIGH); 
          digitalWrite(MD_12_IN3_IN3_IN1, LOW);
          digitalWrite(MD_12_IN4_IN4_IN2, HIGH); 
        }
        if (inputString.charAt(2) =='b') { // (b) Backward - Interlocking
          digitalWrite(MD_1_IN1, HIGH);
          digitalWrite(MD_1_IN2, LOW); 
          digitalWrite(MD_12_IN3_IN3_IN1, HIGH); 
          digitalWrite(MD_12_IN4_IN4_IN2, LOW); 
        }
        if (inputString.charAt(2) =='s') { // (s) Stop button
          speedTrainA = 0;
        } 

        analogWrite(MD_1_ENA, speedTrainA); // Throttle Driver A
        
        if (!flag_interlocking) {
          analogWrite(MD_1_ENB, speedTrainA);
          analogWrite(MD_2_ENB, speedTrainA);
          if (flag_station_open) analogWrite(MD_2_ENA, speedTrainA); 
          else analogWrite(MD_2_ENA,0); 
        }    
      }
    }  

    if (inputString.charAt(0) =='j') {
      // Switch A
      if (inputString.charAt(1) =='a') { 
        if (inputString.charAt(2) =='0') { // Branch direction
          switch_A = false;
          Bluetooth.print("a0z"); // Feedback to App
          Serial.print("a0z");
          addressI2C = 2; dataToI2C = 30; sendDataViaI2C();
        }
        if (inputString.charAt(2) =='1') { // Throw direction
          switch_A = true;
          Bluetooth.print("a1z"); // Feedback to App
          Serial.print("a1z");      
          addressI2C = 2; dataToI2C = 31; sendDataViaI2C();
        } 
      }

      // Switch B
      if (inputString.charAt(1) =='b') { 
        if (inputString.charAt(2) =='0') {
          switch_B = false;
          Bluetooth.print("b0z"); 
          Serial.print("b0z");
          addressI2C = 2; dataToI2C = 32; sendDataViaI2C();
        }
        if (inputString.charAt(2) =='1') {
          switch_B = true;
          Bluetooth.print("b1z");
          Serial.print("b1z");      
          addressI2C = 2; dataToI2C = 33; sendDataViaI2C();
        } 
      }
    }
    
    // AUTOMATE ON | OFF
    if (inputString.charAt(0) =='f') {
      if (inputString.charAt(1) =='a') {

        if (inputString.charAt(2) =='0') {
          flag_interlocking = false;
          speedBlock1 = 0; speedBlock2 = 0; speedBlock3 = 0;
          addressI2C = 2; dataToI2C = 50; sendDataViaI2C(); // AUTOMATE OFF
        }
        if (inputString.charAt(2) =='1') {
          flag_interlocking = true;
          speedBlock1 = 180; speedBlock2 = 140; speedBlock3 = 160;
          digitalWrite(MD_1_IN1, HIGH);
          digitalWrite(MD_1_IN2, LOW); 
          digitalWrite(MD_12_IN3_IN3_IN1, HIGH); 
          digitalWrite(MD_12_IN4_IN4_IN2, LOW); 
          protected_sensor1 = false; protected_sensor3 = false;
          protected_sensor5 = false; protected_sensor7 = false;
          latch_stop_block1 = false; latch_stop_block2 = false; latch_stop_block3 = false;
          open_block1 = true; open_block2 = true; open_block3 = true;          
          addressI2C = 2; dataToI2C = 51; sendDataViaI2C(); // AUTOMATE ON
        }

        analogWrite(MD_1_ENB, speedBlock1);
        analogWrite(MD_2_ENB, speedBlock2);
        analogWrite(MD_2_ENA, speedBlock3); 
      }  
    }

    dataToI2C = 0;
    inputString = "";
    stringComplete = false;
  }

  // ----  MAIN BLOCK
  if (flag_interlocking) {

    // CHECK SENSORS STATES

    if (digitalRead(SNS_1) == LOW) { // BLOCK 1 | HALL
      sensor_block1_IN = true;
      open_block1 = false;
      //Serial.println("SENSOR 1");
    }
    else sensor_block1_IN = false; 
    if (digitalRead(SNS_2) == LOW) { // HALL
      sensor_block1_OUT = true;
      latch_stop_block1 = true;
      //Serial.println("SENSOR 2");    
    }
    else sensor_block1_OUT = false;
  
    if (digitalRead(SNS_3) == HIGH) { // BLOCK 2 | IR
      sensor_block2_IN = true;
      open_block2 = false;
      //Serial.println("SENSOR 3");    
    }
    else sensor_block2_IN = false; 
    if (digitalRead(SNS_4) == LOW) { // HALL
      sensor_block2_OUT = true;
      latch_stop_block2 = true;
      //Serial.println("SENSOR 4");    
    }
    else sensor_block2_OUT = false;  
    
    if (digitalRead(SNS_5) == HIGH) { // BLOCK 3 | IR
      sensor_block3_IN = true;
      open_block3 = false;
      //Serial.println("SENSOR 5");    
    }
    else sensor_block3_IN = false;
    if (digitalRead(SNS_6) == LOW) { // HALL
      sensor_block3_OUT = true;  
      latch_stop_block3 = true;
      //Serial.println("SENSOR 6");    
    }
    else sensor_block3_OUT = false;  
    
    // OUT
    if (analogRead(SNS_7) > 550) { // ANALOGUE HALL
      sensor_OUT = true;
      //Serial.println("SENSOR 7");
    }      
    else sensor_OUT = false;   
  
    // RESET BLOCK LATCHES
    if (sensor_block2_IN) open_block1 = true; 
    if (sensor_block3_IN) open_block2 = true;
    if (sensor_OUT) open_block3 = true;

    // RESET AUTOSTOP LATCHES
    if (sensor_block2_IN) latch_stop_block1 = false;
    if (sensor_block3_IN) latch_stop_block2 = false;        
    if (sensor_OUT) latch_stop_block3 = false;
    
    // ----  SIGNALS
    // SIGNAL 1
    if (sensor_block1_IN && !protected_sensor1) {
      timer_protected_sensor1 = millis();
      protected_sensor1 = true; 
      addressI2C = 2; dataToI2C = 101; sendDataViaI2C();
    }  
    // SIGNAL 2
    if (sensor_block2_IN && !protected_sensor3) {
      timer_protected_sensor3 = millis();
      protected_sensor3 = true;      
      addressI2C = 2; dataToI2C = 102; sendDataViaI2C();
    }    
    // SIGNAL 3
    if (sensor_block3_IN && !protected_sensor5) {
      timer_protected_sensor5 = millis();
      protected_sensor5 = true;       
      addressI2C = 2; dataToI2C = 103; sendDataViaI2C();
    } 
    // SIGNAL 4 
    if (sensor_OUT && !protected_sensor7) {
      timer_protected_sensor7 = millis();
      timerStation = millis();
      protected_sensor7 = true; 
      flag_station_open = false;      
      addressI2C = 2; dataToI2C = 104; sendDataViaI2C();
    } 

  // AUTOSTOP
    // BLOCK 1
    if (!open_block2) {
      if (latch_stop_block1) {
        if (millis() > (timerBlock1 + 100)) {
          timerBlock1 = millis();
          if (speedBlock1 > 40) speedBlock1 = speedBlock1 - 25;
          else speedBlock1 = 0;
        }
      }  
    }
    else speedBlock1 = 180;

    // BLOCK 2
    if (!open_block3) {
      if (latch_stop_block2) {
        if (millis() > (timerBlock2 + 100)) {
          timerBlock2 = millis();
          if (speedBlock2 > 60) speedBlock2 = speedBlock2 - 30;
          else speedBlock2 = 0;
        }
      }  
    }
    else speedBlock2 = 140;

    // BLOCK 3
    if (!flag_station_open) {
      if (latch_stop_block3) {
        if (millis() > (timerBlock3 + 100)) {
          timerBlock3 = millis();
          if (speedBlock3 > 40) speedBlock3 = speedBlock3 - 18;
          else speedBlock3 = 0;
        }
      } 
    }
    else speedBlock3 = 160;
    
    analogWrite(MD_1_ENB, speedBlock1);
    analogWrite(MD_2_ENB, speedBlock2);
    analogWrite(MD_2_ENA, speedBlock3);     
  }

  // ----  TIMERS
  if (millis() > (timer_protected_sensor1 + 1000)) protected_sensor1 = false;
  if (millis() > (timer_protected_sensor3 + 1500)) protected_sensor3 = false;
  if (millis() > (timer_protected_sensor5 + 1500)) protected_sensor5 = false;
  if (millis() > (timer_protected_sensor7 + 1000)) protected_sensor7 = false;
  if (millis() > (timerStation + 15000)) flag_station_open = true; // Delay 15 sec.

  bluetoothEvent();

}  

// ----------- FUNCTIONS ----------- //
void serialEvent() {
  if (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == 'z') {
      stringComplete = true;
    }
  }
}

void bluetoothEvent() {
  if (Bluetooth.available()) {
    char inChar = (char)Bluetooth.read();
    inputString += inChar;
    if (inChar == 'z') {
      //Serial.println(inputString); // Command from App
      stringComplete = true;
    }
  }
}

void sendDataViaI2C() {
  Wire.beginTransmission(addressI2C);
  Wire.write(dataToI2C);
  Wire.endTransmission();
}
LOCAL unit sketchArduino
// -------------------------------------------------- //
// WWW.ARDUINORAILWAYCONTROL.COM                      //
// local_urb.ino                                      //
// V.2.0  11/24/2019                                  //
//                                                    //
// SMALL INTERLOCKING                                 //
// For URB unit V.2.FINAL                             //
// https://arduinorailwaycontrol.com/urb_unit.html    //
//                                                    //
// Author: Steve Massikker                            //
// -------------------------------------------------- //
void(* resetFunc) (void) = 0;

#include <Wire.h> 
#include <Servo.h>

// SERVO
#define JUNCTION_EN 4
Servo J1;  // TURNOUT A
Servo J2;  // TURNOUT B

// SIGNALS
#define S_LA_RED 3 // SIGNAL LINE A
#define S_LB_RED 2 // SIGNAL LINE B
#define S_B3_RED 6 // SIGNAL BLOCK 3
#define S_B3_GRN 5
#define S_OUT_RED 10 // SIGNAL OUT
#define S_OUT_GRN 9
#define S_B1_RED 17 // SIGNAL BLOCK 1
#define S_B1_GRN 16
#define S_B2_RED 15 // SIGNAL BLOCK 2
#define S_B2_GRN 14


// RELAY
#define RELAY_LA 13 //  LINE A
#define RELAY_LB 12 //  LINE B

// Variables
byte dataFromI2C;
unsigned long millisJunctions, timerStation;
bool switch_A = true, 
     switch_B = false,
     flag_blink_AB = false,
     flag_change_junc = false;

bool flag_interlocking = false,
     flag_station_open = true;
     
bool open_block1 = true, 
     open_block2 = true,
     open_block3 = true;

void setup() {

  // Initializie Hardware Serial & I2C
  Serial.begin(9600);
  Wire.begin(2); // Set address #2
  Wire.onReceive(receiveI2C);

  // Initialize pins  
  pinMode (JUNCTION_EN, OUTPUT);
  pinMode (RELAY_LA, OUTPUT);
  pinMode (RELAY_LB, OUTPUT);  
  pinMode (S_LA_RED, OUTPUT);
  pinMode (S_LB_RED, OUTPUT);
  pinMode (S_B3_GRN, OUTPUT);
  pinMode (S_B3_RED, OUTPUT);
  pinMode (S_B1_RED, OUTPUT);
  pinMode (S_B1_GRN, OUTPUT);  
  pinMode (S_B2_RED, OUTPUT);
  pinMode (S_B2_GRN, OUTPUT);
  pinMode (S_OUT_RED, OUTPUT);
  pinMode (S_OUT_GRN, OUTPUT); 

  // Initialize Servos
  J1.attach(7);
  J2.attach(8);

  // Set default
  J1.write(180); J2.write(0);
  delay(900);
  digitalWrite(JUNCTION_EN, LOW);
  digitalWrite(S_LA_RED, LOW); 
  digitalWrite(S_LB_RED, HIGH);   
  digitalWrite(S_B1_GRN, LOW);
  digitalWrite(S_B1_RED, HIGH);
  digitalWrite(S_B2_GRN, LOW);
  digitalWrite(S_B2_RED, HIGH);
  digitalWrite(S_B3_GRN, LOW);
  digitalWrite(S_B3_RED, HIGH);
  digitalWrite(S_OUT_GRN, HIGH);    
  digitalWrite(S_OUT_RED, LOW);
  digitalWrite(RELAY_LA, LOW); // Line A is ON 
  digitalWrite(RELAY_LB, HIGH); // Line B is OFF
}

void loop() {

// ---- COMMAND PARSING
  if (dataFromI2C != 0) {
    
    switch (dataFromI2C) {

      // RESET
      case 99: resetFunc(); break;

      // SWITCH A
      case 30: J1.write(0);
           delay(50);
           switch_A = false;
           flag_change_junc = true;
           digitalWrite(JUNCTION_EN, HIGH);
           Serial.println("SWITCH A Branch");
           millisJunctions = millis();
           break;

      case 31: J1.write(180);
           delay(50);
           switch_A = true;
           flag_change_junc = true;         
           digitalWrite(JUNCTION_EN, HIGH);
           Serial.println("SWITCH A Straight");         
           millisJunctions = millis();
           break;

      // SWITCH B
      case 32: J2.write(0);
           delay(50);
           switch_B = false; 
           flag_change_junc = true;             
           digitalWrite(JUNCTION_EN, HIGH);
           Serial.println("SWITCH B Branch");
           millisJunctions = millis();
           break;

      case 33: J2.write(180);
           delay(50);
           switch_B = true; 
           flag_change_junc = true;             
           digitalWrite(JUNCTION_EN, HIGH);
           Serial.println("SWITCH B Straight");
           millisJunctions= millis();
           break;

      // MODE
      case 50: flag_interlocking = false;  
           break;
      case 51: flag_interlocking = true;  
           break; 

      // BLOCKS STATE
      case 101: open_block1 = false;
           Serial.println("BLOCK 1");
           break;
      case 102: open_block2 = false;
           open_block1 = true; 
           Serial.println("BLOCK 2");           
           break;
      case 103: open_block3 = false;
           open_block2 = true;
           Serial.println("BLOCK 3");
           break;
      case 104: open_block3 = true;
           flag_station_open = false;
           timerStation = millis();
           Serial.println("OUT");
           break;
    }
     
    dataFromI2C = 0;
  }

// ---- SIGNALS
  // BLOCK 1
  if (flag_interlocking) {
    if (open_block1) {
      digitalWrite(S_B1_GRN, HIGH); 
      digitalWrite(S_B1_RED, LOW);     
    }
    else {
      digitalWrite(S_B1_GRN, LOW); 
      digitalWrite(S_B1_RED, HIGH); 
    }
  // BLOCK 2
    if (open_block2) {
      digitalWrite(S_B2_GRN, HIGH); 
      digitalWrite(S_B2_RED, LOW);     
    }
    else {
      digitalWrite(S_B2_GRN, LOW); 
      digitalWrite(S_B2_RED, HIGH); 
    }
  // BLOCK 3
    if (open_block3) {
      digitalWrite(S_B3_GRN, HIGH); 
      digitalWrite(S_B3_RED, LOW);     
    }
    else {
      digitalWrite(S_B3_GRN, LOW); 
      digitalWrite(S_B3_RED, HIGH); 
    }
  }
  else {
    digitalWrite(S_B1_GRN, LOW);
    digitalWrite(S_B1_RED, HIGH);
    digitalWrite(S_B2_GRN, LOW);
    digitalWrite(S_B2_RED, HIGH);
    digitalWrite(S_B3_GRN, LOW);
    digitalWrite(S_B3_RED, HIGH);
  }   

  // OUT
  if (flag_station_open) {
    digitalWrite(S_OUT_GRN, HIGH);    
    digitalWrite(S_OUT_RED, LOW);
  }
  else {
    digitalWrite(S_OUT_GRN, LOW);    
    digitalWrite(S_OUT_RED, HIGH);
  }

// ---- RELAY
  if (flag_change_junc) {

  	if (switch_A && !switch_B) { // Line A
      digitalWrite(S_LA_RED, LOW);
      digitalWrite(S_LB_RED, HIGH); // RED     
      digitalWrite(RELAY_LA, LOW);
      digitalWrite(RELAY_LB, HIGH); 
      flag_blink_AB = false;
  	}
  	else if (!switch_A && switch_B) { // Line B
      digitalWrite(S_LA_RED, HIGH); // RED
      digitalWrite(S_LB_RED, LOW);       
      digitalWrite(RELAY_LA, HIGH); 
      digitalWrite(RELAY_LB, LOW); 
      flag_blink_AB = false;     
  	}
  	else { // Undefined
      digitalWrite(RELAY_LA, HIGH); 
      digitalWrite(RELAY_LB, HIGH); 
      flag_blink_AB = true;     
  	}
 
    flag_change_junc = false; 
  } 

  if (millis() > (millisJunctions + 900)) digitalWrite(JUNCTION_EN, LOW);
  if (millis() > (timerStation + 15000)) flag_station_open = true; // Delay 15 sec.  

  if (flag_blink_AB) {
  	static bool tick_blink;
    static unsigned long blinkMillis;
    if (millis() > (blinkMillis + 500)) { // 500 - blinking optimal period
      tick_blink = !tick_blink;
      blinkMillis = millis();
    }
    digitalWrite(S_LA_RED, tick_blink);
    digitalWrite(S_LB_RED, !tick_blink);
  }

}

// ----------- FUNCTIONS ----------- //

void receiveI2C(int howMany) {
  while (Wire.available() > 0) {
    dataFromI2C = Wire.read();
  }
}

Schematics

Track Plan
Plan cg7lyl279h
Circuit of Interlocking system
Circuit gtae4qo1gw

Comments

Similar projects you might like

Advance Automatic Railway Crossing System

Project showcase by Pawan singh and Akansh Saxena

  • 5,619 views
  • 2 comments
  • 16 respects

Wireless Laser-Gate Timing System for Track and Field

Project showcase by Pablerdo

  • 2,882 views
  • 9 comments
  • 30 respects

Smart Parking System

Project in progress by Md. Khairul Alam

  • 59,628 views
  • 36 comments
  • 128 respects

Security System Using Password by Arduino & Python

Project in progress by muhammed amar slik

  • 5,507 views
  • 2 comments
  • 15 respects

Renewing the Nikko Turbo 2 RC Car

Project tutorial by MarcoGPS

  • 3,127 views
  • 2 comments
  • 10 respects
Add projectSign up / Login