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.

  • 1,101 views
  • 7 comments
  • 10 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

Play Polyphonic Tones!

by nathan_ramanathan

  • 3,373 views
  • 3 comments
  • 8 respects

Arduino Tutorial: JARVIS v1 | How to make a Home Automation

Project tutorial by rahulkhanna

  • 5,926 views
  • 10 comments
  • 47 respects

Retro 1980s LED Clock/Count Up Timer

Project in progress by randtekk

  • 1,280 views
  • 4 comments
  • 8 respects

Heart Rate Monitor Using IoT

Project tutorial by Technopaths

  • 4,065 views
  • 2 comments
  • 18 respects

Arduino MEGA Guitar Pedal

Project tutorial by electrosmash

  • 7,370 views
  • 1 comment
  • 40 respects
Add projectSign up / Login