Model Railway Start Sets

The samples presented in this tutorial are simple, but sequential. You can use ANY model train kit with metal rails (you can also control old versions of LEGO TRAINS with metal rails or DC LIONEL).

Hardware Requirements: any microcontroller, a Bluetooth module, a motor-driver and several wires.

Software: premade Sketches in this tutorial are for the most popular Arduino products — NANO, UNO, MEGA and ESP32 (for ESP32 Bluetooth module is not needed).

Principal of train control

Entry level

To get started with the URB control system, try the free application Arduino Train DEMO. From there, you can try the paid applications which also work with these examples, while adding more complexity and features.

 

NANO-UNO

Arduino NANO and UNO

ATmega328 is an 8-bit MCU

Each type of a microcontroller (MCU) has its individual specs, and pin layout (they are also called GPIO — a General-Purpose Input/Output is an uncommitted digital signal pin).

Arduino NANO and UNO use the same MCU: ATmega 328, and, accordingly, the number and capabilities of GPIO are the same.

This circuit is a typical version of robotic control based on Arduino. Similar schemes can be easily found 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.

Before the assembly of the circuit, you need to upload to Arduino program called a sketch. Sketch for this experiment 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.

GETTING STARTED
  1. Upload UNO/NANO sketch (based on SerialEvent from Arduino IDE.)
  2. Assemble the circuit
  3. Play trains!
Start with NANO and UNO

MEGA

Arduino MEGA

ATmega2560 is an 8-bit MCU

Arduino MEGA is redundant for this simple track-plan, but many modelers already have such a board. Therefore, I added a sketch for the ATmega2560 8-bit MCU.


ESP32

ESP32 DOIT

32-bit MCU
Wi-Fi & BT/Bluetooth LE

Note: this chip works with logic levels of voltage of 3.3 V.

Unlike the classic Arduino boards (NANO, UNO and MEGA) natively supported by the IDE Arduino development environment, special libraries from Espressif Systems are required to program this module based on the ESP32 chip. Also note that the programming syntax of this chip is significantly different from that adopted in the Arduino programming environment.

If you have an initial level of programming in C ++, then using this chip in a project will not be difficult. But if you are new to programming, please do not use this complex chip in your projects.

Basic level

The first thing you need to believe, that most microcontrollers pins are universal. There are no rules for connecting this particular data wires from external device to this particular Arduino pin (with several restrictions).

Arduino NANO pinout

In the picture you can see that only pins D3, D5, D6, D9, D10, D11 can output a PWM control signal. Pins A0-A7 have enhanced capabilities for processing the incoming analog signal and so on. We will use all these features later.

In the URB project, a more understandable way of assigning Arduino pins is used. Before the Setup() block, the pinout is described using the #define construction code. In it, you write the names of the pins that you understand, and then use them in the main code.

Continuing with a simple BLINK example, you can connect a real LED to any Arduino data pin, and it will flash just like the built-in one. But if you try to connect the LED, for example to the pin D2 of Arduino, and do not change the sketch, nothing will happen. The fact is that Arduino needs to explain what you have connected to it. And these explanations you must do at the beginning of the code of the sketch. Such a section is void setup() called. And this code is executed once after turning on the power or resetting the microcontroller, then the main loop void loop() is executed endlessly.
It is enough to change this code:

  void setup() {
    // initialize digital pin LED_BUILTIN as an output.
    pinMode(LED_BUILTIN, OUTPUT);
  }  
  void loop()  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
  } 

on that:

  void setup() {
    // initialize digital pin D2 as an output.
    pinMode(2, OUTPUT);
  }  
  void loop()  {
    digitalWrite(2, HIGH);
    delay(1000);
    digitalWrite(2, LOW);
    delay(1000);
  } 

and it will work.

Tracks basics – add a turnout

The URB Project you can connect any types point-motors for switching turnouts – servo, electromagnetic and having a stepper or DC motor. Features of the use of different types, see the section «Plugging Point-Motors to your turnouts». But in this experiment I will use the classic solenoid mechanism. The sketch is written for this type of device. So you need a separate power source with a voltage of 12 to 16 volts for switching these point-motors. Therefore, you need have a separate output on your power supply terminal block of or have a separate source of this voltage.

Add switch-machine

The motorization of turnouts is the next stage that any modeler implements when building his own layout. The project involves the management of any type of railroad switches. In this example, you can add control to one turnout. Note how easy it is to add new code to the sketch.

Any of GPIO pins of the microcontroller can control the point-motor contacts with a simple command: digitalWrite(Number GPIO, HIGH/LOW state). But the output voltage and current from the pins (GPIO) are too small to move the solenoid inside the coil, thereby moving swith point rails of your turnout. Therefore, a current amplifier is needed. For this you can use a simple circuit with transistors, but in my project I use only ready-made electronic components. This is an assembly of Darlington transistors placed in a finished chip. Chip manufacturers produce many variants of such chips and you can apply any of them. In the Arduino environment, the most common chip is ULN 2003, so it is used in this example.

Darlington Array

In this sketch you can see commands for switching turnouts. ja1z and ja0z – commands to switch the turnout A to positions of straight or branch. First letter (j – junction), second letter (a) means the individual number of the turnout, the third – switch points position (1 – straight, 0 – branch).

…
  if (inputString.charAt(0) =='j') { 
    // Switch A
    if (inputString.charAt(1) =='a') { 
      if (inputString.charAt(2) =='0') { // Branch
        digitalWrite(2, LOW);
        digitalWrite(3, HIGH);
      }  
      if (inputString.charAt(2) =='1') { // Straight
        digitalWrite(3, LOW);
        digitalWrite(2, HIGH);
      } 
    }
  }
…
UNO/NANO MEGA

 

Later I will show how to add a code to the sketch to automatically turn off the voltage from solenoids after switching position of the turnout.

Plugging Point-Motors to your turnouts

Magnetic coil (solenoid machine)

To control this type of point motors, the project uses a ULN2003 chip or similar. You only need to select the voltage for your machine, and if you want the time needed to move the core of the coil.

Turnout Servo Motor

The servo is natively controlled by Arduino. Servo.h library allows an Arduino board to control RC (hobby) servo motors. Servos have integrated gears and a shaft that can be precisely controlled. Standard servos allow the shaft to be positioned at various angles, usually between 0 and 180 degrees. The Servo library supports up to 12 motors on most Arduino boards and 48 on the Arduino Mega.

Especially for the URB project, I developed an original easy adjustable and cheap servo point motor.


Insulated rail joiners and relays

Add switch-machine

The URB project operates in the classic DC control mode. This means that, unlike the DCC control systems with a decoder in the locomotive, sections of rail tracks are controlled, not the locomotive itself.

Contrary to popular belief among supporters of DCC systems, this control method has much more possibilities. The transparency and reliability of the DC system are obvious – you always know what is happening, due to the lack of modulation of the digital signal under voltage for the decoder on the train and the elementary principal of «Rails – DC motor inside of a loco». To identify possible malfunctions, a conventional voltmeter is enough.

But other benefits are less obvious. For example, the creation of an interlocking system for several trains in the DCC system is impossible without the use of a very complex subsystem for controlling the position of all trains on a layout with online identification by using local «GPS for the hobby room» (see Faller system). To implement interlocking or other options for automatic control of train traffic in the URB system, several sensors are enough…

An example of controlling multiple trains is this sketch. You can increase the number of lines by simply increasing the number of relays and switches. Sketch do contain having code of the algorithm, which automatically activates the line depending on the position of the turnouts. Also in this sketch, the voltage from the solenoids is turned off after the timeout you define (I set 0.7 sec).

…
  if (millis() > (millisJunctionsA + 700)) {
    digitalWrite(JUNCTION_EN, LOW);
    digitalWrite(JUNCTION_EN, LOW);
  } 
  if (millis() > (millisJunctionsB + 700)) {
    digitalWrite(JUNCTION_EN, LOW);
    digitalWrite(JUNCTION_EN, LOW);
  } 
…
UNO/NANO MEGA

An important feature of microcontrollers is the versatility of GPIO. You can change the destination of any Arduino pin by changing code of header's sketch. For example, I changed pins numbers that control point motors, and now the pins D2 and D3 now control the relay module. You can see more interesting examples in the video. Sketches for them do not differ from the above.

Details

Insulated rail joiners
Insulated rail joiners

Rail joiners are small clips used to join two sections of track mechanically. They come in metal (nickel silver) which also connects the rails electrically, and plastic which are insulated to isolate the two sections of track electrically.

Relay module
Relay

A Relay is an electrically operated switch. Many relays use an electromagnet to mechanically operate the switch and provide electrical isolation between two circuits.


The fun feature of the URB control system is the simultaneous control of trains and layout by several players. Arduino Train Junior Pro, DUO and Tablet applications support multiplayer for two participants, the Quadro app up to four.

In the new version of the Protocol version 2.4 four letters are reserved for these purposes – a, b, c and d. This is a very flexible solution – you can alone control trains and the layout, switching between sections of railtracks (for example, between the outer and inner circles in this example), or adding additional Bluetooth modules to playing on multiple smartphones or tablets. The rule is simple: you need one Bluetooth module for one smartphone, two Bluetooth modules for two phones, etc.

The speed of data transmission and processing in Arduino is much higher than in DСС control systems, so there is practically no delay between the movement of the traction control in the application and the reaction of the locomotive to this effect. This is very similar to analog control using a transformer – instant response. To make it even more interesting, you can enable several modes of inertia in the Pro and DUO applications, which will simulate the movement of light, medium and heavyweight trains.

Dual control can be applied in other games. The scheme given at the beginning of this page for Arduino and the sketch to it may will also apply to any other similar systems, for example, to toys like Electric Loop Road Racing.

Advanced level

The main advantage of my project is the combine of many microcontrollers (Arduino boards) to each other, as well as to external computers or other digital devices. Thus, there are no hardware restrictions on the number and types of devices using on your layout (turnouts, sensors, signals, lights, any mechanisms and other). This is a clear difference to other railway control systems.

All the possibilities of the URB project are revealed when several Arduino are connected to the mesh. The flexibility of the system lies in the fact that you can use several types of Arduino boards in one project and connect them together using any standard bus for microcontrollers. Examples in this section use multiple serial connections and the I2C bus.

The only restriction necessary for the implementation of my control system in your railway layout is the allocation of one Arduino as COMM, all the other Arduino should be LOCAL.

The video shows a complete analysis of the sketch code for such a system. If you noticed, then almost all the videos on my YouTube channel use the URB unit.
I repeat, the use of this adapter board for my project is not a prerequisite!

COMM LOCAL

Signal system

First you need to introduce you to the Smart Track function and Boolean logic.

Boolean logic

You have already met with the comparison operators IF and ELSE. By adding to them Boolean variables (having only two states), you can very simply describe the behavior of your layout.

I apply the following rule to turnouts: if the point (switch rail) has a direct position, then the value of the variable «1» or TRUE; if the point has a branch position is the variable «0» or FALSE. The same for the active / passive the line's states.

By using these variables, the COMM remembers the state of all lines and turnouts, and you can use comparison operators to program the logic of the behavior of signals, relays and other things.

 

signal system track-plan

To demonstrate the advantages of a system of several Arduino, in this example I will give two solutions for a standard track-plan.

 

A long time used contacts mechanically connected to the points of turnout. An example of such old-school excellent mechanics is Twin Coil Switch Machines with signal contactors.

Old Twin Coil Switch Machines

This simple system activated a rails line according to the position of the turnout. This works well, but as soon as you need to make a more complex switching logic, for example if you have three turnouts, there are very big problems with creating circuit.

Microcontrollers elegantly solve such problems. Instead of connecting multiple relays and wires or soldering many discrete elements, the logic of the lines and signals is transferred to the sketch code. Therefore, you can always add, modify or correct errors by simply reprogramming a sketch without having to change the electric circuit.

Code for switching relays between lines

if (switch_A == true) {
  digitalWrite(RELAY, LOW);
}  
if (switch_A == false) {
  digitalWrite(RELAY, HIGH);
}  

Now I will add another turnout, and I will only need to rewrite the sketch without changing a circuit on the layout.

In the C programming language (Arduino sketches), it is customary to reduce the comparison operators of Boolean logic. Instead if (switch_A == true) is written if (switch_A) and instead of if (switch_A == false) – if (!switch_A) (sign «!» means inverse). Since the state of the switch_A variable can take only two values, you can use the else operator. Two letters && are a comparison operator AND.

if (switch_A && switch_B) {
  digitalWrite(RELAY, LOW);
}
else {
  digitalWrite(RELAY, HIGH);  
}

 

Smart track

Look, in case you haven't noticed, I tricked you a bit with the code for two turnouts. In fact, given that each turnout can have two states, the number of options will be four. If you add even more turnouts, the situation will quickly get out of your control.

In the URB project, this misunderstanding is resolved by grouping variables of turnouts and moving the logic of switching relays and signals to LOCAL Arduinos.

But before it, let's look at all the options for the states of signals and relays turning on / off the corresponding lines (see pictures).

I suggest the following algorithm:
– if the Switch A is in the branch position, then Signal 1 is yellow with a white line indicating the movement of trains along the Line A. Signal 2 is green and the corresponding relay activates line A.
– remaining states of Signal 1 depend on the positions of switches B and C and the position of switch A (to straight).

if (!switch_A) { // Branch position
  digitalWrite(RELAY_LINE_A, LOW); // Line A ON
  digitalWrite(SIGNAL_1_YELLOW, LOW); // ON
  digitalWrite(SIGNAL_1_WHITE, LOW); // ON
  digitalWrite(SIGNAL_1_GREEN, HIGH); // OFF
  digitalWrite(SIGNAL_1_RED, HIGH); // OFF 
  digitalWrite(SIGNAL_2_GREEN, LOW); // ON
  digitalWrite(SIGNAL_2_RED, HIGH); // OFF        
}
else { // Straight position
  digitalWrite(RELAY_LINE_A, HIGH); // Line A OFF
  digitalWrite(SIGNAL_1_YELLOW, HIGH); // OFF
  digitalWrite(SIGNAL_1_WHITE, HIGH); // OFF
  digitalWrite(SIGNAL_2_GREEN, HIGH); // OFF  
  digitalWrite(SIGNAL_2_RED, LOW); // ON

  // Code for Switches B and C  
}

But before we create the sketches, let's calculate the number of pins on the Arduino necessary for this track-plan. The motor-driver needs three pins, three relays are needed on three lines – these are three pins. Signal 1 has four LEDs, signals 2-6 have two LEDs each. A total of 20 pins.

In this example, I will use servos to switching the turnouts, these are three pins (in the case using the classic inductive point-motors needs six pins). And, as you can see, the number of GPIOs (pins) on the Arduino NANO, UNO and ESP32 is not enough even for such a simple experiment.

The most unreasonable solution to the problem of lack of pins is the use of Arduino MEGA. Firstly, this does not solve the problem itself, as soon as you try to control the layout with ten or more turnouts and signals, you again will not have enough GPIOs. Secondly, the number of wires and the complexity of the electrical circuit will quickly lead you to disheartening. Thirdly, the dimensions of the sketch will very quickly exceed five hundred lines, and you will not be able to understand what you programmed in a few days ago.

In the URB project, you can increase the number of GPIOs (pins) you need by simply increasing the number of Arduino. This dramatically simplifies the circuit and sketches. You can transfer data between several Arduino via serial communications, routed buses of type I2C or wireless channels.

In this example, I will show two options for such a solution:
– Serial connection of two Arduinos (MEGA and UNO)
– Connection via I2C bus of three Arduino NANO.


Layout circuit

To demonstrate the flexibility of the URB system, I will connect the servos, relays and signals in these sketches in different ways. Using URB units allows you to placed Arduino directly to the installation location of the drives and signals on your layout, which simplifies the setup, length and number of wires. Later you will be add new devices to your layout without changing the wiring, due to the availability free Arduino pins. That is, you can consider the URB unit as a socket with remote control through the application.

Since in the URB project there is always one COMM and several LOCAL Arduino, so, COMM always has a Bluetooth and receives control commands from the application. In the example with serial communications, MEGA is COMM, in the sketch for URB units, since they are the same, you can assign COMM to any of them by simply installing the Bluetooth module on it. The algorithm switching relays and signals on lines B and C, depending on the state of the turnouts B and C in the first sketch for MEGA and UNO, is performed on MEGA. In the case of three URB units, this algorithm runs on local units.

3 URB units (3 NANO)

Three URB units COMM (URB#1) LOCAL (URB#2) LOCAL (URB#3)

In the sketches for the URB units there is a code that implements auto-shutdown of servos after switching the turnouts and moving position of turnouts to the default position.

Arduino MEGA + Arduino UNO (NANO)

MEGA-UNO serial COMM (MEGA) sketch LOCAL (UNO-NANO) sketch

Sketches for MEGA – UNO and 3 URB units perform the same functions, only for URB units the sketches are more concise and, due to the standardization of the devices connection, their code is universal. That is, you can simply copy the sketch code from the snippets and adjust it, instead of creating a new one.
Also, the signals in the version for URB units are connected through a current amplifier, that is, you can use not only LEDs, but also old signals with incandescent bulbs.


Power supply

In examples on the Advanced Level section, we create an extensive network of many URB units and a large number of railway peripherals connected to them. Because of this, the load current on 5V can become significant, so we need more powerful power sources compared with the charger for phone. I highly recommend a 5V power supply with a current of at least 2 amps.

The ideal solution can be a computer power supply, it immediately gives out voltages both 5V and 12V with protection. Also, most railway sets usually include a 9-18V power supplies. Also, you can apply two standard power supplies, to 5V and 12V, by combining their negative wires together.


Let's bring all of the previous pieces together!

Big Layout

The URB project is a constant discovery of new opportunities. Sometimes it even surprises me. When I created the protocol and applications, it seemed to me that I was making a railway layout control system. Then when I started experimenting with sensors it turned out that we can create automatic train movement specific to the scenario. Then, modelers who were interested in the URB project began to connect automatic decouplers, drawbridges and control of MAGNORAIL system. Suddenly, we've discovered that Arduino microcontrollers have no boundaries for creativity and experimentation.

The network topology of URB allows you to mix data buses in any way convenient for you. The Arduino code variant for this is shown in the example above, but for a Big Layout I created a circuit consisting of a serial connection an Arduino MEGA as COMM and Local URB units with two separate segments I2C (the length of the I2C bus is limited to 3 meters).

Planning

Big Layout plan

The flexibility and universality of URB gives you the opportunity to make decisions about the organization of the behavior of devices on your layout. This lead to replacing the COMM URB in the Big Layout with an Arduino MEGA.

This change complicated the connection of the railway periphery to the system in comparison with the URB unit and requires more attention when installing the wires. However, this configuration provides more flexibility when creating a network thanks to Arduino MEGA's four serial ports. Serial data routing simplifies the connection of sensors and increases the length of data buses. Combining serial connections with I2C buses, you can create a heterogeneous network with various types of microcontrollers and Arduino modules. For example, connecting a sound module (or several) with a serial interface.

I want to control my layout from my mobile phone or tablet. Before connecting the circuits and writing the code, I need to figure out how the trains will move via the layout lines. I have two independent circles and a rail connecting them. With a scale of 1:87, the size of the layout is about 4x2 meters (14x7 ft). In addition, I want to run the wires of the electrical circuit mainly along the external contour of the layout, and also I want to avoid wiring in the back of the layout. And lastly, I don't yet know how many signals and channels of lighting control layout I need. I want to be able to add or change my layout in the future.

Observing the basic rule of the URB project (place units as close to the railway periphery as possible) – I placed these units on a draft picture of the layout. Now I can make a connection map. In this layout, I use the HO PIKO Point electric motors to move levers of turnouts, which means that I need current drivers (ULN2003). Each of them can control three motors which dictates the number of URB units needed for the switches.

Switches

Now divide the rails into sections. An example of TWO CIRCLES gives me a way of dividing the plan into sections of outer A (green) and inner B (blue) sections.

Next add isolated rail lines and give them a name. Connect a relay to these lines later.

Switches

From the picture there are 8 Lines in total, 8 relays are needed. In addition, there is a Transition Line along which you can move trains from the outer circle to the inner circle and vice versa, requiring two more relays. To simplify the sketches connect all relays to the Arduino MEGA using two relay modules one 8 relay unit and one 2 relay unit.

Logic & Algorithm

This is a rather complicated yet interesting stage. The function of the URB project is to make the lines operate automatically based on the position of the turnout switches.

Turnouts

There may be several options for these algorithms, and it all depends on your preferences. For Yard and Depot Lines, the algorithm directly depends on the position of the turnout switch J3 and J4. For Lines 1 and 2, I made a dependency; with the direct position of the turnouts, Line 2 is active, with the branch position, Line 1 is active. But if the J2 is in the branch position, both lines are blocked. The blocking algorithm for Lines 5 and 6 depends on the turnouts J10 and J12.

As you can see, these are already quite complex interactions in which it is easy to get confused. There is a solution – make a Karnaugh map. In the next section I will show how to do this without using the theory of logic and at the same time optimize the switching of turnouts.

An important function of URB should be noted – moving levers of turnouts to the default position.

In traditional DC or DCC train operation, when you turn on the layout, the position of turnouts is unknown. Moreover, during operation you can also forget the position of turnouts, this will cause delays, inconvenience, and crashes! Therefore, for each layout you will need to set the initial position, which will correspond to the variables switch_N. When you turn on the power or by command from the set default position button, all turnouts will automatically switch to this initial position and signal states are set. I chose the following starting position:

Switches

Karnaugh map

 

Default
J1 – TRUE, J2 – TRUE, J3 – TRUE,
J4 – FALSE, J5 – TRUE, J6 – TRUE,
J7 – FALSE, J8 – FALSE, J9 – FALSE,
J10 – TRUE, J11 – TRUE, J12 – TRUE
J1 – FALSE, J3 – TRUE, J8 – TRUE, J9 – FALSE

 

J3 – FALSE, J8 – TRUE, J9 – FALSE

 

J1 – TRUE, J2 – FALSE, J4 – FALSE, J6 – TRUE, J7 – TRUE, J9 – TRUE

 

J10 – FALSE, J12 – FALSE

 

J10 – TRUE, J12 – FALSE

 

J5 – FALSE, J6 – FALSE, J7 – FALSE, J11 – FALSE, J12 – TRUE

 

A dual relay will transfer voltage to Station Line 3 either from section A or from section B depending on the position of the turnout J7. These relays switch independently of the algorithm.

Arduino understands the values of Boolean variables in the form of TRUE or FALSE as 1 and 0. This translates to 1 representing the unswitched/straight/primary position of the turnout points and 0 to the switched/curved/secondary position.

 

Matching between Active Lines and Turnouts Table
# J1
Switch A
J2
Switch B
J3
Switch C
J4
Switch D
J5
Switch E
J6
Switch F
J7
Switch G
J8
Switch H
J9
Switch I
J10
Switch J
J11
Switch K
J12
Switch L
Depot Line (see circuit) 1
Yard Line 0 1 0
Station Line 1 0 1 1 0
Station Line 2 (Default) 1 1 1 0 1 1 0 0 0 1 1 1
Station Line 3 A 0 0 0 0 1
Station Line 3 B 1 0 0 1 1 1
Station Line 4 (Default) 1 1 1 0 1 1 0 0 0 1 1 1
Station Line 5 0 0
Station Line 6 1 0

Look at your layout railpaths and fill out the table. Do not try to build an algorithm without creating a rail lines state table. If the railpath does not depend on the position of the particular turnout or if the position of the turnout blocks the track, then the table cell remains empty.

You can also combine hardware and software switching solutions. For example, the Depot relay of line and Line 3 is connected in series, so in the first row of the table there is only one value (see the relay diagram).

Using this table, I made algorithms for enabling corresponding lines. In this example, turnouts J corresponds to the SWITCH buttons in the Arduino Train application (J1 → Switch A, etc.). I use separate names of the real turnouts on the layout (J #) and app buttons (Switch #) to control them. This can later be used to optimize switching.

Optimization

One command from the application can switch several turnouts at once. For example, it is logical to switch two turnouts J20 and J21 at the same time. That is, using the Switch W button on the app through a sketch, you can assign any change in position of any number of turnouts and etc. To implement this behavior of point-motors in the project, it is possible to assign the Switch command to a several turnouts J # like this:

void controlJunctions() {
  …
  // Switch W
  if (inputString.charAt(1) =='w') { 
    if (inputString.charAt(2) =='0') {
      switch_W = false;
      digitalWrite(J20_BRANCH, HIGH); // two Junctions at once
      digitalWrite(J21_BRANCH, HIGH);      
    } 
    if (inputString.charAt(2) =='1') {
      switch_W = true;
      digitalWrite(J20_STRAIGHT, HIGH); // two Junctions at once
      digitalWrite(J21_STRAIGHT, HIGH);      
    } 
  }
Line power

Another unique and important function of URB is that you can connect the relay to any Arduino on your layout to reduce the number of wires and simplify the circuit, in this example all the relays are connected to MEGA only to simplify understanding of the sketch code. This algorithm also allows you to build any system of railway signals, according to the principles described above.

…
void setup () {
  …
  // Set relays states by Default
  digitalWrite(RELAY_Depot, HIGH);  //  OFF 
  digitalWrite(RELAY_Yard, HIGH);  //  OFF 
  digitalWrite(RELAY_Line1, HIGH);  //  OFF 
  digitalWrite(RELAY_Line2, LOW);  //  ON 
  digitalWrite(RELAY_Line3, HIGH);  //  OFF 
  digitalWrite(RELAY_Line4, LOW);  //  ON 
  digitalWrite(RELAY_Line5, HIGH);  //  OFF 
  digitalWrite(RELAY_Line6, HIGH);  //  OFF 
  // Power to Line 3 from Section A
  digitalWrite(RELAY_Transition, HIGH);  // From Section A 
  … 
}
void setup () {
  …
  // Station Line 1
  if (!switch_A && switch_C && switch_H && !switch_I) {
    digitalWrite(RELAY_Line1, LOW);  //  ON 
  }
  else digitalWrite(RELAY_Line1, HIGH);  //  OFF
  … 
}    
Relays connections

If you notice, relay destinations 5 and 6 are sequentially reversed. These are the advantages of microcontrollers and Arduino in particular. You do not need to follow the procedure for connecting wires to pins (GPIO). Connect as you like, later you assign a pin number to a specific device in a sketch. In my example, all the relay control output wires are connected to the digital side connector of the MEGA, in the header of the sketch, write the correspondence between RELAY_Line6 and pin D51 using operator #define.

After the planning stage, all the data to place Arduino /URB units has been identified, enabling the creation of the electrical circuit and sketches. Next, open the corresponding snippets in the Arduino IDE editor and adapt them to the layout.


Programming the COMM

According to the plan created above, I determine the details of connecting to Arduino MEGA. Then, guided by the picture of the connected devices, I add them to the sketch header. The method of controlling point motors is given in the section Tracks basics – add a turnout. For this layout two ULN2003 chips are needed, pins D22-D33 are connected to the inputs of these chips. Thus, the sketch for MEGA will directly control the turnouts J1 – J6, and send commands to switch the remaining turnouts to the URB #2 unit through the Serial 3

Bus I2C MEGA will be used to control the light channels of URB #5 unit. I suggest using six channels to illuminate buildings and lights. If you need more channels, add one more unit (6) to the I2C bus. The pull-up resistors necessary for the correct operation of the I2C bus are installed on the URB #5 unit.


URB #2

In addition to the main function of executing commands, this URB unit also translates the commands from the MEGA serial interface to its own I2C bus, essentially creating a local router.

I rewrote this sketch from the snippet for the COMM URB unit, to demonstrate the universality of the rules for creating code for the project.

URB #2

URB #3

Sketch for URB 3 is a «LOCAL for URB» snippet. The functionality of this unit completely coincides with the example of using I2C bus. This sketch shows the practical application of the URB unit for the management of turnouts. You can use free pins later to connect signals or other peripherals.

URB #3

URB #5

This is a good example of adding an additional URB module to the finished layout for future expansion. You can also change the voltage for the LEDs, for example, connect them to 12 volts for standard LED stripes.

Also here is the algorithm of the RANDOM function, which ensures the random inclusion of lighting elements on your layout.

You can assign any lighting effects to your LEDs.

 URB #5 

Troubleshooting

After launching an experiments, you may notice some confusion. For example, if you typed the command: «jd0z» – the point-motor turned the turnout to straight position instead of the expected one a branch position. This is the logic chain: the command on the serial port → conversion to the byte-command → resend via I2C → processing on the local URB → a switching of the turnout D. This is quite a long chain of communication with many possible places for error. So, the rule is the following: setting the final position of turnout or the color of the signal should be made on the final URB unit to which they are connected.

In other words, you can build the correct logical model, but signals sent from the communication station cause an inverted response – instead of the expected red signal, the green signal is turned on. To fix this change the state of the outputs of the local URB (by changing the description of the outputs in the header of the sketch).

The number of units for the Big Layout compared to the old version of the site is reduced to three. As practice has shown, the example with 6 units was too complicated to study and raised many questions. Nevertheless, a version with 6 units is available on the old version of the site. I would also like to note that all project sketches and all application are compatible with each other and do not require additional changes.

The examples on this site are hard to get wrong, but shit happens :) Following these instructions and reversing the process, now you will diagnose your problems. The hardware of the URB project consists of modules that can operate autonomously. Therefore, troubleshooting is a simple checking of the modules by one. You can always connect the URB unit to the computer and add test commands to sketch from the Protocol to check it. For more information, see Running and troubleshooting.


Railway layout for Imre

My friend Imre from Hungary sent me his project. It turned out an excellent video about the adaptation of the URB control system for a specific railway layout. This example consists of two parts. The first is the planning of the electrical circuit, the second is the implementation.

Imre Layout's sketches (Zip)

This sketches was programmed for Protocol 2.1 and URB 2.122.


Dogbone

Dogbone track-plan

Many modelers like the Dogbone rail plan. I created this example especially for them, showing the universal capabilities of URB. For automatic operation of the loops, you need four IR sensors, which you need to modify according to my instructions. You can watch the basic working principles of sketching in videos.

COMM URB

A sketch should not cause you difficulties with its understanding, it is a common URB LOCAL snippet. Sensor signals from a local unit are transmitted through a serial connection. Turnouts J Loop A and J Loop B switch automatically and do not depend on the application command. The loops operation algorithms are symmetrical for COMM and LOCAL units.

To add turnouts controlled from the application, connect a new unit via the I2C bus, as in the example of the Big layout.

COMM URB

LOCAL URB

This sketch preprocesses the sensor signals and transfers their state to the COMM unit. Feature is the control of a motor-driver 2 from COMM via a serial. This method is also used in the Interlocking system.

Pay attention to the another location of the sensors on the layout and the associated direction of train movement when entering the loop.

LOCAL URB