Introdution Starter Kit

First example especially for the model railroad beginners, shows how to just start playing with your railroad using Arduino and a smartphone. It is enough to have a any classic starter kit and even a schoolboy will build this scheme in a few minutes.

Also see the project for kids, for simpler games with toy trains

 

As a result, you get convenient wireless control from your phone or tablet and, much more interestingly, many additional capabilities. For example, by changing the sketch you can add any inertia to your train, as well as add new features described on the site.

Electrical schematic diagram

An example in this figure is a typical version of robot control based on Arduino. Similar schemes you will easily find on the Internet. The only difference is that the output of the motor driver is connected to the rails, and not directly to the motor. Of course, you can use your combinations of Bluetooth modules and motor-drivers, as well as ready shields. I recommend the L298N Dual H-Bridge Motor Controller and HC-06 Bluetooth modules.

You can directly connect RX to TXD and TX to RXD, but some Bluetooth modules sometimes have problems with signal transmission due to different signal levels between Arduino and Bluetooth module. Therefore, there is a resistive divider in the circuit. The nominal value of R1 is 2 kOhm, R2 is 1 kOhm.

Another variant this experiment on my dashboard Arduino PROJECT HUB.

More reliable variant

If you have URB 2.7, then everything becomes much easier. There is no way to make a mistake when constructing the scheme on a breadboard, and no domestic pet will rip out the wires :) And this option will also allow you to collect a more interesting potential, namely dual-channel control – which allows you to play together use two different phones or tablets.

Arduino sketch

This sketch is based on the example SerialEvent from Arduino IDE. In general, all the sketches of this project are written at such a level so that they can be easily converted for to your needs. Their complexity at level a examples Arduino IDE.

Tap the link sketch and upload code to Arduino IDE. In the test sketch, the processing of the command is moved to the function, and the end flag instead of the end of the stroke (/ n) uses the "z" character. This example with variations is the basis of all the other sketches, and its understanding is the starting point.

The sketch structure is as follows: the Arduino inputs and their purpose are described first, and the libraries used are also listed. Declaring global variables. Then comes the block setup with the announcement of the state of the inputs, the initialization of libraries and built-in functions.


//// LIBRARIES ////

//// GPIO PINS ////

// L298
#define IN1_PIN 4
#define ENA_PIN 5
#define IN2_PIN 6

//// VARIABLES ////
boolean stringComplete = false;
String inputString = "";
int speedLoco;

void setup() {

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

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

}

Arduino pins 4, 5 and 6 connected with L298. Pin D5 – PWM (speed loco), pins D4 and D6 – locomotive direction. LED_BUILTIN – internal virtual pin for Arduino LED. Variables inputString and stringComplete see in SerialEvent example.

Parsing the command received from the smartphone:


void loop() {

  if (stringComplete) {
    //THROTTLE
    if (inputString.charAt(0) =='t') {
      if (inputString.charAt(1) =='0') {
        analogWrite(ENA_PIN, 0);
        speedLoco = 0;
      }
      if (inputString.charAt(1) =='1') {
        analogWrite(ENA_PIN, 80);
        speedLoco = 1;
      }
      if (inputString.charAt(1) =='2') {
        analogWrite(ENA_PIN, 100);  // START LOCO
        speedLoco = 2;
      }

You can change the PWM pitch to start movement locomotive, thus setting up your train.


      if (inputString.charAt(1) =='3') {
        analogWrite(ENA_PIN, 150);
        speedLoco = 3;
      }
      if (inputString.charAt(1) =='4') {
        analogWrite(ENA_PIN, 200);
        speedLoco = 4;
      }
      if (inputString.charAt(1) =='5') {
        analogWrite(ENA_PIN, 255);
        speedLoco = 5;
      }
    }

    // DIRECTION
    if (inputString.charAt(0) =='d') {
      if (inputString.charAt(1) =='r') {
        digitalWrite(IN1_PIN, HIGH);
        digitalWrite(IN2_PIN, LOW);
      }
      if (inputString.charAt(1) =='f') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, HIGH);
      }
      if (inputString.charAt(1) =='s') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, LOW);
        analogWrite(ENA_PIN, 0);
        speedLoco = 0;
      }
    }

    //LIGHT
    if (inputString.charAt(0) =='l') {
      if (inputString.charAt(1) =='a') {
        digitalWrite(LED_BUILTIN, HIGH);
      }
      if (inputString.charAt(1) =='b') {
        digitalWrite(LED_BUILTIN, LOW);
      }
    }

The flag of eneded complite command.


    inputString = "";
    stringComplete = false;
  }
}

Function serialEvent provided serial communicate between application ArduinoTrain BtControl and Arduino.


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

Arduino Train App

Install a free Arduino Train for Kids or Android Train Junior applications from Google Play.

Paired your Android device with HC-06 bluetooth module:

  • Enter the network settings of the system. Select the connection Bluetooth.
  • Turn on the power supply of the URB with the installed HC-06 modules.
  • Tap discovering devices of the bluetooth. In the list of detected devices, select HC-06 and pair them with your android device (default password - 1234).
  • Close the system settings.

Run application and push the blue Bluetooth button, and select your HC-06 module. Connect will be established. With this button you can break the connection and establish it again.

Running and troubleshooting

In this example, it's hard to make a mistake. But shit happens :) If you have collected everything, have included, but it does not work we will look for the reason. At the same time we will understand how to act in such situations.

First, if the indicate LEDs on all devices do not glow, then most likely you have wrong the polarity or problem with your power adapter. If the power is OK, the application Arduino Train is running on your smartphone, but you can not connect to the Bluetooth channel, the most common mistake is the wrong device selection. Make sure that your choise HC-06 or your BT adapter.

The connection is established - "You connected: XX:XX:XX" (in the case of HC-06, the indicator glows, not blinking), but the locomotive does not move over the commands of the smartphone. First we will check our design. If you touch Toggle Light on application, but the Arduino Nano LED does not light up, then problem with transferring data through the serial port from bluetooth to arduino. Try to put the resistors or level converter or... Incorrect wiring again.

If all the previous steps are completed, but the locomotive still does not move, then with digital multimeter checking the condition motor-driver's and the locomotive's.

Update your first sketch

Any sketch presented on this site is not a dogma. Let's add to the previous sketch the second software serial port, it's add the independence of the bluetooth channel from the USB. Now you can download sketches from your computer via USB to Arduino without disabling Bluetooth, which makes it convenient for experiments with sketches reprogramming.

If you are using versions Arduino Train Junior or PRO, the management capabilities are significantly extended. But since all versions of applications use the same protocol, the sketches will work the same with any version.

This example is developed for URB (v.2.4-2.7) unit. You can collect a similar scheme on the breadboard, but URB is much more convenient. In the circuit we will add supply 5 volts from the USB connector, thus dividing the power for control and for locomotive. As result we will get rid of interference to the control electronics when trains run (also this allows to increase the voltage on the rails up to 16-20 volts if you need it).

Also in this configuration there is a very interesting opportunity for experiments with your own command variants (see the basic protocol of the commands on Android Goods). You will run second train from PC use your custom commands. And, as a bonus, you can see commands sending from Android to Arduino in Arduino IDE Terminal for debugging.


//// LIBRARIES ////

#include <SoftwareSerial.h>

//// GPIO PINS ////

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

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

//// VARIABLES ////
boolean stringComplete = false;
String inputString = "";
int speedLoco1, speedLoco2;

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);

}

Since in this version the USB connection is constant, in the code is added data for output to the terminal: Serial.print([data for input]). Try it, it helps a lot in debugging. For example, commands coming from the application ArduinoTrain BtControl are duplicated in the Arduino IDE terminal. Providing this code is placed at the very beginning of the loop block.


void loop() {

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

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

    //THROTTLE 1 LOCO
    if (inputString.charAt(0) =='t') {
      if (inputString.charAt(1) =='0') speedLoco1 = 0;
      if (inputString.charAt(1) =='1') speedLoco1 = 1;
      if (inputString.charAt(1) =='2') speedLoco1 = 2;
      if (inputString.charAt(1) =='3') speedLoco1 = 3;
      if (inputString.charAt(1) =='4') speedLoco1 = 4;
      if (inputString.charAt(1) =='5') speedLoco1 = 5;
    }

    // DIRECTION 1 LOCO
    if (inputString.charAt(0) =='d') {
      if (inputString.charAt(1) =='r') {
        digitalWrite(IN1_PIN, HIGH);
        digitalWrite(IN2_PIN, LOW);
      }
      if (inputString.charAt(1) =='f') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, HIGH);
      }
      if (inputString.charAt(1) =='s') {
        digitalWrite(IN1_PIN, LOW);
        digitalWrite(IN2_PIN, LOW);
        analogWrite(ENA_PIN, 0);
        speedLoco1 = 0;
      }
    }

    //THROTTLE 2 LOCO (COMPUTER)
    if (inputString.charAt(0) =='u') {
      if (inputString.charAt(1) =='0') speedLoco2 = 0;
      if (inputString.charAt(1) =='1') speedLoco2 = 1;
      if (inputString.charAt(1) =='2') speedLoco2 = 2;
      if (inputString.charAt(1) =='3') speedLoco2 = 3;
      if (inputString.charAt(1) =='4') speedLoco2 = 4;
      if (inputString.charAt(1) =='5') speedLoco2 = 5;
    }


    // DIRECTION 2 LOCO (COMPUTER)
    if (inputString.charAt(0) =='d') {
      if (inputString.charAt(1) =='n') {
        digitalWrite(IN3_PIN, HIGH);
        digitalWrite(IN4_PIN, LOW);
      }
      if (inputString.charAt(1) =='v') {
        digitalWrite(IN3_PIN, LOW);
        digitalWrite(IN4_PIN, HIGH);
      }
      if (inputString.charAt(1) =='o') {
        digitalWrite(IN3_PIN, LOW);
        digitalWrite(IN4_PIN, LOW);
        analogWrite(ENB_PIN, 0);
        speedLoco2 = 0;
      }
    }

    inputString = "";
    stringComplete = false;
  }

  // PWM OUT1
  switch (speedLoco1) {
      case 0: analogWrite(ENA_PIN, 0); break;
      case 1: analogWrite(ENA_PIN, 80); break;
      case 2: analogWrite(ENA_PIN, 100); break;
      case 3: analogWrite(ENA_PIN, 150); break;
      case 4: analogWrite(ENA_PIN, 200); break;
      case 5: analogWrite(ENA_PIN, 255); break;
      default: analogWrite(ENA_PIN, 0); break;
  }

  // PWM OUT2
  switch (speedLoco2) {
      case 0: analogWrite(ENB_PIN, 0); break;
      case 1: analogWrite(ENB_PIN, 80); break;
      case 2: analogWrite(ENB_PIN, 100); break;
      case 3: analogWrite(ENB_PIN, 150); break;
      case 4: analogWrite(ENB_PIN, 200); break;
      case 5: analogWrite(ENB_PIN, 255); break;
      default: analogWrite(ENB_PIN, 0); break;
  }

  bluetoothEvent();
}

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') {
      stringComplete = true;
    }
  }
}

By consecutively typing the "dnz" , "u2z", "u3z", "u4z" commands in the terminal, you start the locomotive on the second raill path, and will by typing "doz" - stop it. The same simple protocol works with Android application. It's very simple.

Note the change in the locomotive throttle parsing code. PWM processing for the motor-driver is carried out in a separate block. It is in it you can apply mathematical operations to introduce inertia into the movement of the train. And think up this code yourself!


Railway modelling. History of control.

I'm sure that you know this story, but still I will repeat the main stages.

The first trains were driven by miniature electric motors to which electricity was supplied via rails. Almost all modern models of locomotives can work in this mode. The principle is very simple and understandable even for children – it is enough to press a 9 volt battery to the rails and the train moves. If you change the polarity (unfold) the batteries, the train will start moving in the opposite direction. If a controlled transformer or rheostat is used instead of a battery, it becomes possible to adjust the speed by changing the voltage on the rails. In this way, have been made most of the obsolete control panels that are still very popular.

This principle of management had a significant disadvantage: if you put several locomotives on the rails, they start moving simultaneously. This was overcome by isolating individual sections of the rail and blocking them using a relay or by installing separate consoles for each section. What caused the following problem, the complexity of the electrical wiring has greatly increased. And even now you can see well-made analog railroad models with a very large number of wires. On the other hand, despite the number of wires, the principle itself is very obvious and understandable.


With the beginning of the 1980s, the concept of DCC was introduced. The voltage on the rails will constanted, and the control signals uses of time modulation were transmitted along the same rails. Accordingly, the consoles changed, now they broadcast a control signal. The decoder installed on the locomotive converted these commands into voltage and polarity to the motor. The decoder on the locomotive also added new features – motion sounds, headlight lighting effects and cockpit lighting. Now this is the main principle in railway modeling.

DCC consoles also elegantly solve the problem of switching junctions and light signalling, there is no need to separately pull the wires to motor points - there too there are decoders. But this in theory, in practice DCC has generated many new problems: when building several lines and using several locomotives, it is necessary to install boosters that distribute the load. Because of the difference in the supply voltage of the drives and locomotives, the wires again need to be pulled through the entire layout. Each manufacturer has a different command system and compatibility is still a very narrow place. Features programming of consoles and locomotives – the main part of the discussions in profile forums. And most importantly, DCC is closed, very incomprehensible and very the cumbersome solution compared to the classical one. For example, troubleshooting in decoders, boosters or in the console itself is very difficult.

Since the beginning of the mass distribution of computers and modern electronics, the modelers have created several universal DCC standards, but in my opinion this all now looks like a giant zoo of disparate and very over-complicated devices.

Modern digital consoles are very good and similar to a specialized computer with a lot of blocks, and it seems to me that they contradict the principle of Occam's razor. Also the price of such a set is simply fantastic.


If you look at these solutions from the side – it's obvious that the DCC is just a data bus and microcontrollers installed in the console and decoders. And if you try to use Arduino, and this is a microcontroller Atmega, you can use both the classic control option and the DCC.

Combinations of DCC and Arduino designed out a lot, and they work well. But I'm of the opinion that this way is too complicated. Therefore, I returned to DC concept, only instead of the transformer I apply the ready-made block L298 with Pulse-width modulation PWM) to control locos. Also for Arduino there are a lot of reliable cheap modules. The Arduino programming language is very simple and flexible.

Reprogramming Arduino gives you almost infinite possibilities for updating the layout. It's like updating the firmware of modern electronic gadgets. As the site is being updated, I will publish new ideas on automation and drawing of railway devices. Now on the site you will find all the necessary details for creating switching motors, light signals, consoles and many others. Using this information, any fashion designer can, step by step, realize his own projects.


Grandson of my friend from Slovenia plays in the railway from the phone

Next steps

Reprogramming Arduino gives you almost infinite possibilities for updating your layout. It looks like a update firmware of modern electronic gadgets.

As the site is being updated, I will publish new ideas on automation and drawings of railway devices. Now on the site you will find all the necessary details for the creation of switch-motors, light signals, consoles and much more. Using this information, any modeler can, step by step, realize his own projects.