Project tutorial

Simple Command Station for Model Railway Layouts © GPL3+

Command station for classical route. Switch points, control trains from two independent devices. Automate signals. Intro URB conception.

  • 748 views
  • 5 comments
  • 8 respects

Components and supplies

Ard nano
Arduino Nano R3
×1
09670 01
SparkFun Dual H-Bridge motor drivers L298
×1
Bluetooth module HC-05 (HC-06)
×1
ULN2003A High-Current Darlington Transistor Arrays
×1
Servo (generic)
×3
12009 06
SparkFun Level Shifter Board
×1
Generic 2-channel relay for Arduino
×1
Any miniature lamps 5-9V for signals (max current per lamp - 0.1A)
×10

Apps and online services

About this project

This instruction illustrate principal create railway classical model layout control unit. A communicate through bluetooth between Arduino and Android (or computer, or minicomputer) allows you to switch arrows, run trains.

The relay breaked current on blocked lines depending on the position of the junctions. SIgnals also change state. Look at the Arduino sketch to understand the logic of these switches. Also you will see the mechanism of power on / off on the servo drive only at moment of switching the junction.

This is also a good example for understanding the system commands of the ArduinoTrainBtControl application and the URB concept. You can also send these commands directly from the serial port terminal (via USB) or connect your Raspberry Pi.

Universal Railmodelling Bus (URB) - unit to create electrical diagrams for any railway projects and more, details on my site.

Code

Railway Command StationArduino
Arduino on the classical toy railway
// ARDUINORAILMAKET.RU
// V.4.1
// 01.04.2017
// Author: Steve Massikker


/////// SIMPLE COMMAND STATION ///////

#include <SoftwareSerial.h>
#include <Servo.h>

//// GPIO PINS ////

// SOFTWARE SERIAL
SoftwareSerial Bluetooth(12, 13); // RX, TX

// L298
#define ENA_PIN 6
#define IN1_PIN 7
#define IN2_PIN 5
#define IN3_PIN 2
#define IN4_PIN 4
#define ENB_PIN 3

// RELAY
#define RELAY_IN1 14
#define RELAY_IN2 15

// SIGNALS
#define CHANNEL_1 19
#define CHANNEL_2 18
#define CHANNEL_3 17
#define CHANNEL_4 16

// JUNCTIONS
#define JUNCTION_EN 8 
#define JUNCTION1_PIN 9
Servo JNC1;
#define JUNCTION2_PIN 10
Servo JNC2; 
#define JUNCTION3_PIN 11
Servo JNC3; 


//// VARIABLES ////
boolean stringComplete = false;
String inputString = ""; 
unsigned long millisJunction;


void setup() {

// Initialize Serial
  Serial.begin(9600);
  Bluetooth.begin(9600);   
  inputString.reserve(16); 

// Initialize Motor Driver
  pinMode(ENA_PIN, OUTPUT); 
  pinMode(IN1_PIN, OUTPUT); 
  pinMode(IN2_PIN, OUTPUT); 
  pinMode(IN3_PIN, OUTPUT); 
  pinMode(IN4_PIN, OUTPUT); 
  pinMode(ENB_PIN, OUTPUT);  

// Initialize relay & signals
  pinMode(RELAY_IN1, OUTPUT); 
  pinMode(RELAY_IN2, OUTPUT); 
  pinMode(CHANNEL_1, OUTPUT); 
  pinMode(CHANNEL_2, OUTPUT); 
  pinMode(CHANNEL_3, OUTPUT); 
  pinMode(CHANNEL_4, OUTPUT); 

// Initialize Servos
  pinMode(JUNCTION1_PIN, OUTPUT); 
  JNC1.attach(JUNCTION1_PIN);
  pinMode(JUNCTION2_PIN, OUTPUT); 
  JNC2.attach(JUNCTION2_PIN);
  pinMode(JUNCTION3_PIN, OUTPUT); 
  JNC3.attach(JUNCTION3_PIN);  
  pinMode(JUNCTION_EN, OUTPUT);

//// STARTUP ////   

// Junction
  digitalWrite(JUNCTION_EN, HIGH);
  delay(80);
  JNC1.write(0);
  delay(100);  
  JNC2.write(0);
  delay(100);  
  JNC3.write(180); 
  delay(800);
  digitalWrite(JUNCTION_EN, LOW);  

// Realy & Signal 
  digitalWrite(RELAY_IN1, HIGH);
  digitalWrite(RELAY_IN2, HIGH);
  digitalWrite(CHANNEL_1, LOW);
  digitalWrite(CHANNEL_2, HIGH);
  digitalWrite(CHANNEL_3, LOW);
  digitalWrite(CHANNEL_4, HIGH); 

// L298 N (optional)
  digitalWrite(IN1_PIN, LOW);
  digitalWrite(IN2_PIN, LOW);
  digitalWrite(IN3_PIN, LOW);
  digitalWrite(IN4_PIN, LOW);
  digitalWrite(ENA_PIN, LOW);
  digitalWrite(ENB_PIN, LOW);

}

void loop() {

  if (stringComplete) {
    Serial.print("inputString = ");    // PRINT COMMAND //
    Serial.println(inputString);       // TO SERIAL     //

// ----------- START COMMAND PARSING ----------- // 

    //THROTTLE LOOP TRACK
    if (inputString.charAt(0) =='t') {   
      if (inputString.charAt(1) =='0') {
        analogWrite(ENB_PIN, 0);
      }
      if (inputString.charAt(1) =='1') { 
        analogWrite(ENB_PIN, 80);
      }
      if (inputString.charAt(1) =='2') {
        analogWrite(ENB_PIN, 100);  // START LOCO
      }
      if (inputString.charAt(1) =='3') { 
        analogWrite(ENB_PIN, 150);
      }
      if (inputString.charAt(1) =='4') {
        analogWrite(ENB_PIN, 200);
      }    
      if (inputString.charAt(1) =='5') { 
        analogWrite(ENB_PIN, 255);
      } 
    }

    // DIRECTION LOOP TRACK
    if (inputString.charAt(0) =='d') {
      if (inputString.charAt(1) =='r') {
        digitalWrite(IN3_PIN, HIGH);
        digitalWrite(IN4_PIN, LOW);
      }
      if (inputString.charAt(1) =='f') {
        digitalWrite(IN3_PIN, LOW);
        digitalWrite(IN4_PIN, HIGH);
      }
      if (inputString.charAt(1) =='s') {
        digitalWrite(IN3_PIN, LOW);
        digitalWrite(IN4_PIN, LOW);
        analogWrite(ENB_PIN, 0);
      } 
    }
      
    //THROTTLE TEST TRACK
    if (inputString.charAt(0) =='u') {   
      if (inputString.charAt(1) =='0') {
        analogWrite(ENA_PIN, 0);
      }
      if (inputString.charAt(1) =='a') { 
        analogWrite(ENA_PIN, 60);
      }
      if (inputString.charAt(1) =='b') {
        analogWrite(ENA_PIN, 90);  
      }
      if (inputString.charAt(1) =='c') { 
        analogWrite(ENA_PIN, 120);
      }
      if (inputString.charAt(1) =='d') {
        analogWrite(ENA_PIN, 150);
      }    
      if (inputString.charAt(1) =='e') { 
        analogWrite(ENA_PIN, 180);
      } 
      if (inputString.charAt(1) =='f') { 
        analogWrite(ENA_PIN, 210);
      } 
      if (inputString.charAt(1) =='g') { 
        analogWrite(ENA_PIN, 240);
      } 
      if (inputString.charAt(1) =='h') { 
        analogWrite(ENA_PIN, 255);
      }       
    }

    // DIRECTION TEST TRACK
    if (inputString.charAt(0) =='d') {
      if (inputString.charAt(1) =='n') {
        digitalWrite(IN1_PIN, HIGH);
        digitalWrite(IN2_PIN, LOW);
      }
      if (inputString.charAt(1) =='v') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, HIGH);
      }
      if (inputString.charAt(1) =='o') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, LOW);
        analogWrite(ENA_PIN, 0);
      } 
    }

    //JUNCTIONS  
    if (inputString.charAt(0) =='j') { 
      if (inputString.charAt(1) =='a') { 
        digitalWrite(JUNCTION_EN, HIGH);
        JNC1.write(0);
        delay(100); // servo start current limitation
        JNC2.write(0);        
        millisJunction = millis();  
        digitalWrite(CHANNEL_1, LOW);        
        digitalWrite(CHANNEL_2, HIGH);
        delay(100);
        digitalWrite(RELAY_IN1, HIGH);                
      }
      if (inputString.charAt(1) =='b') { 
        digitalWrite(JUNCTION_EN, HIGH);
        JNC1.write(180);
        delay(100); // servo on start current limitation
        JNC2.write(180);        
        millisJunction = millis();  
        digitalWrite(CHANNEL_1, HIGH);        
        digitalWrite(CHANNEL_2, LOW);
        delay(100);
        digitalWrite(RELAY_IN1, LOW);      
      }
      if (inputString.charAt(1) =='c') { 
        digitalWrite(JUNCTION_EN, HIGH);
        JNC3.write(180);
        millisJunction = millis();  
        digitalWrite(CHANNEL_3, HIGH);        
        digitalWrite(CHANNEL_4, LOW);
        delay(100);
        digitalWrite(RELAY_IN2, HIGH);      
      } 
      if (inputString.charAt(1) =='d') { 
        digitalWrite(JUNCTION_EN, HIGH);
        JNC3.write(0);
        millisJunction = millis();  
        digitalWrite(CHANNEL_3, LOW);        
        digitalWrite(CHANNEL_4, HIGH);
        delay(100);
        digitalWrite(RELAY_IN2, LOW);      
      }  
    }

// ----------- END COMMAND PARSING ----------- // 

    inputString = "";
    stringComplete = false;    
  }

  bluetoothEvent(); 
  if (millis() > (millisJunction + 800)) digitalWrite(JUNCTION_EN, LOW); // off power servo

}

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

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

void bluetoothEvent() {
  while (Bluetooth.available()) {
    char inChar = (char)Bluetooth.read();
    inputString += inChar;
    if (inChar == 'z') {
      stringComplete = true;
    }
  }
}

Schematics

Circuit
Command station on Arduino NANO
Simplecommandstation l50v2yipng
Route plan
Classical route rqomz6k3um

Comments

Similar projects you might like

A DIY Smart Insole to Check Your Pressure Distribution

Project tutorial by Juliette van der Pas

  • 1,291 views
  • 7 comments
  • 13 respects

Arduino LIDAR

Project tutorial by abhinav

  • 12,452 views
  • 4 comments
  • 18 respects

Arduino Mega Chess

Project showcase by Sergey_Urusov

  • 3,448 views
  • 14 comments
  • 24 respects

Sprout: Modern Indoor Self Watering Planter

Project tutorial by Jonathan Pereira

  • 3,487 views
  • 3 comments
  • 22 respects

VU Meter on Steroids: Arduino Nano and WS2812Bs

Project in progress by WannaDuino

  • 3,117 views
  • 5 comments
  • 13 respects

Arduino Apple Watch

Project tutorial by Karlstrom

  • 1,745 views
  • 0 comments
  • 6 respects
Add projectSign up / Login