Make a donation

Donators get access to the extended part of the site + bonus: Arduino Train DNT application.
For experiments and regular updating of the site, I need funds. I also have another project that you will like. If you are interested it, support me via donations.

Project Blog

News behind the scenes and important information

10/8/18

For two weeks, I developed and tested a code for an automatic railway interlocking system. I also built a full-featured layout for such a system. It seemed to me that this was enough to introduce to you this coolest opportunity of Arduino. But it turned out that the explanation of these features and advantages that represents an interlocking require very detailed explanations. That is, it is not enough to make a system; much more effort is needed to present it. What I am doing now. You can support me to make this happen faster :)

The preliminary video of interlocking system

Railway interlocking

9/18/18

Dear friends! In the beginning of September, I closed the group on Facebook, because its management took me a very long time. I did not have time to update the site and develop the project.

I understand that Facebook was a convenient platform for you – but the problem is that it is not indexed by search engines and the groups are closed to an external visitor. Therefore, I suggest that you use the Reddit.com portal.

Welcome, it will be interesting!

Reddit community

9/16/18

Yesterday I began to upload in a new sketch of the project in a Arduino NANO and could not do it. I find solved this problem and eventually found out that it arises after the update of Arduino IDE to 1.8.7. As a result, I put the checkbox "old bootloader" and this was the solution. But I received the most interesting information later from Reddit:
Comment from sleemanj to SteveMassikker via /r/arduino sent 5 hours ago
Yeah, a particularly bone-headed decision by Arduino if you ask me, new Nano boards have a bootloader running at 115200 instead of 57600 like all other 16MHz bootloaders previously.
So now everybody, even those using official Nanos sold before this year, may need to choose the "old bootloader" option, and know to do so.
Very thankful, Sleemanj!

Don't upload sketch

Complete modules for a model railway

Set of railway modules and sketches Arduino.

bidirectional interlocking module

 



The URB project opportunities allows you to design individual modules, and then combine them together to obtain ready-made designs. A detailed video for the production of all modules is present on my YouTube channel. All modules have a flat base, which allows them to be used in the absence of sublayout's space – that is, they can be used on the floor and on the table, which distinguishes them from other similar designs.

The bidirectional interlocking module

Soon new module

With this module, I begin part about the Automation of train traffic using the project URB. The main question arising in many people of community of railway modeling – Why needed the Automation? First of all, in order to avoid the dismal fate of moving a lone train via a circle (most videos with train models on the Internet look exactly this way). Your layout is completely transformed when several trains move on it, see my video – the feeling of playing together is much stronger. The problem is that the modelling is very individual and the partner for the game is not always there, and even with the DCC control you need a second participant and a corresponding set of DCC equipment. My project is initially designed to manage a lot of participants and without additional equipment. So, my suggestion is to solve this problem, need adding the possibility of self-propelled trains by adding sensors to your layout. Secondly, it's interesting and not boring.

Rail crossing

PDF

This module has advanced settings, in the control Arduino sketch you can individually adjust the speed of the barriers, their position and use any lighting effects. The rail crossing is managed automatically or from my applications, or from computer.
Full description and sketches for the rail crossing is in the Donators Zone.

Signals

PDF

When developing my signals, I took into account first of all the maximum manufacturability and the cost of their manufacture. This design assumes a mass production of signals by the modeler. In addition, the signals are very strong and maintainable.

Turnout Mashine

PDF

A universal and reliable turnout's point-motor suitable for any scale. See also the video for adjustments details.

Where to buy Arduino details for the project

Buyers guide — How to cheap buy details of Arduino

Buyers guide

Many people when beginning to learn Arduino buy KIt Arduino BOX for 50-100 dollars or euros. DO NOT DO THAT! Most of the items in the box are not needed!

I did not want to write this guide for a long time, because I thought in Internet the information was enough to indicate that this is a very cheap project. I am the same buyer of these goods as you are. That is, I do not produce, sell or advertise the producers of these details. And I do not have any benefit from such activities.
But I was wrong, it turned out that this is very important. I will give my method of buying these goods and the approximate prices.

The first advice is to take several identical parts at once, it is not only cheaper, but also relieves you of the need to re-order. Be greedy! For example, for my project you need a few Arduino NANO, when buying five pieces on the trade portals such as aliexpress.com or alibaba.com one piece will cost only $3.2 (2.7€). On Ebay 5 pieces of Arduino NANO will cost 3.3€ for one, but the delivery will be much faster.

 

The second advice. Be very careful when choosing a product on these trading portals – the product description is often very brief and uninformative. For example, you can buy cheaper the same Arduino Nano Atmega168P, but with another CPU (need 328P) which will very restrict you in writing sketches and applying in the project. Also apply this recomandations to modules of Bluetooth and Motor-drivers, compare the picture on my site and on the sites of sellers, they should be identical (in part because of this I bring pictures instead of diagrams).

be careful

The third advice. Buy from local vendors consumables (wires, connectors, etc.). Shops such as Radioshack are almost everywhere. If you look a little you will find that very often next to you there are private sellers of details of Arduino, it is slightly more expensive than on sites, but at times faster. Plus there will be communication, often people trade Arduino not for profit, but for the sake of a hobby (just like me).

All items for one URB unit bought in this way are for me a less than $4 or approximately 3€.

consumables

 

How to search

I buy mostly on AliExpress. The interface of all major online stores is about the same, so this is a general recommendation. Enter the product you are interested in in the search line, select the average price and… Start looking at the references to SIMILARITIES or HOT SELLING. Having stopped by a particular salesman, see what other Arduino products offers. Pay attention to the shipping cost!

Conclusions

I took the simplest set of parts for installation the electronics for "Example of a simple layout" from the site of Horby. And it's not even a wireless console. The price difference with the same functionality eightfolded, this despite the fact that the expansion options for my project is much greater. The attempt to calculate the price of the necessary components from the Pro series from the company ROCO led to a difference of 25 times!

And for me it was a bit surprising that I did not find on these sites a classic set for DC control.

Compare URB project with ready solution

Now let's just count. I will compare the price of electronics, without wires and power supply blocks, for Example of a Simple Layout presented on it site. I'm not so sure about real prices, but approximately in out June 2018 so:

URB project
Detail Quantity Price $ Price €
URB unit 2 4.00 x 2 3.40 x 2
Arduino NANO 2 3.50 x 2 3.00 x 2
Arduino Train Junior App 1 9.99 9.99
Servo SG-90 4 1.40 x 4 1.20 x 4
Relay 2ch 2 1.20 x 2 1.10 x 2
Bluetooth HC-05 1 2.80 2.60
Motor-driver L298 1 1.50 1.30
Total 37 34
DC control

All well-known manufacturers have ceased production DС control systems.

DCC control
Detail Quantity Price $ Price €
Hornby DCC Select Controller 1 139.99 121.99
Digital Locomotive Decoder 2 25.99 x 2 22.50 x 2
Hornby Accessory Decoder 1 52.00 48.99
Surface Mounted Point Motor 4 12.99 x 4 9.99 x 4
Total 296 256

Track Sets

Ready-to-use set of URB project components and sketches for classic Track Sets.

Railway sets

At the beginning of each module description, the set of components required to install the control for this set of rails is given. It is only necessary to connect the elements of the URB project according to the scheme and upload the ready firmware (sketch) to Arduino.

Many manufacturers of railway models produce sets of rails for the construction of classical railways. For your convenience, I've made a section where you can take a ready-made solution for such sets and using it. Simply start controlling trains, signals and turnouts without the sketching writing process.

Connect power to these circuits you can see here.

One way Yard

To this example, I made two sketches and two schemes for connecting the URB unit. The first circuit and sketch are designed to use the servo as an point-motor. The second example relates to the electromagnetic coils actuator for switching the turnout.

Pay attention to the connection of the wire + 12V to the INDUCT jumper, since an inductive load is used in example 2. In some cases (if the coils point-motor are released long time enough), there may not be enough current for switching, in this case connect two outputs of the ULN2003 chip in parallel (PD5+PD6 and PD7+PD8), and, accordingly, change the second sketch.


  • Connect to rails, signal and turnout
    void(* resetFunc) (void) = 0; // RESET FUNCTION
    
    #include <SoftwareSerial.h>
    #include <Servo.h>
    
    // I/O PINS
    #define ENA_PIN 3
    #define IN1_PIN 2
    #define IN2_PIN 4
    #define JUNCTION_EN 8
    #define SIGNAL_A_GREEN 14
    #define SIGNAL_A_RED 15
    #define RELAY_A 17
    
    Servo J1;
    
    SoftwareSerial Bluetooth(12, 13); // RX, TX
    
    // VARIABLES
      
      // SERIAL EVENT
      bool stringComplete = false;
      String inputString = "";
    
      // JUNCTIONS
      bool switch_A = true;
      unsigned long millisJunction;
      
      // SPEED TABLE
      byte speedArrayA [] = {70, 100, 140, 180, 210, 255}; // CUSTOM THROTTLE
      byte speedLocoA;
    
      // CHECK CHANGES 
      bool flag_change_junc; 
    
    
    void setup() {
    
    // Initialize Serial
      Serial.begin(9600);
      Bluetooth.begin(9600);
      inputString.reserve(4);
    
    // Initialize Motor Driver
      pinMode(ENA_PIN, OUTPUT); 
      pinMode(IN1_PIN, OUTPUT); 
      pinMode(IN2_PIN, OUTPUT);
    
    // Initialize Servos & SET DEFAULT POSITIONS
      pinMode(JUNCTION_EN, OUTPUT);
      pinMode(9, OUTPUT);  
      J1.attach(9);
      J1.write(180);
      delay(50);
      digitalWrite(JUNCTION_EN, HIGH);
      delay(600);
      digitalWrite(JUNCTION_EN, LOW);
    
    // Initialize Signals & Relay
      pinMode(SIGNAL_A_GREEN, OUTPUT); 
      pinMode(SIGNAL_A_RED, OUTPUT); 
      digitalWrite(SIGNAL_A_RED, HIGH);
      pinMode(RELAY_A, OUTPUT);  
      digitalWrite(RELAY_A, HIGH)  
    }
    
    void loop() {
    
    // ----  START PARSING INCOMING APP COMMANDS  
      if (stringComplete) {
    
        // RESET LAYOUT
        if (inputString =="000z") resetFunc();
    
        // LOCO CONTROL FUNCTIONS
        if (inputString.charAt(0) =='a') {
          byte speedLocoA = 0; // be on the safe side set throttle to 0
    
          // Speed (0-6)
          if (inputString.charAt(1) =='0') { 
            if (inputString.charAt(2) =='0') speedLocoA = 0;
            if (inputString.charAt(2) =='2') speedLocoA = speedArrayA[0];
            if (inputString.charAt(2) =='4') speedLocoA = speedArrayA[1];
            if (inputString.charAt(2) =='6') speedLocoA = speedArrayA[2];
            if (inputString.charAt(2) =='8') speedLocoA = speedArrayA[3];
          }
          if (inputString.charAt(1) =='1') {
            if (inputString.charAt(2) =='0') speedLocoA = speedArrayA[4];
            if (inputString.charAt(2) =='2') speedLocoA = speedArrayA[5];    
          }
    
          // Direction, Stop and AWS
          if (inputString.charAt(1) =='d') {
            if (inputString.charAt(2) =='f') { // (f) Forward
              digitalWrite(IN1_PIN, HIGH);
              digitalWrite(IN2_PIN, LOW); 
            }
            if (inputString.charAt(2) =='b') { // (b) Backward
              digitalWrite(IN1_PIN, LOW);
              digitalWrite(IN2_PIN, HIGH); 
            }  
            if (inputString.charAt(2) =='s') { // (s) Stop button
               digitalWrite(IN1_PIN, LOW);
               digitalWrite(IN2_PIN, LOW); 
               speedLocoA = 0;
            } 
    /* AWS        
            if (inputString.charAt(2) =='r') { // (r) Release button | AWS
               aws_driverA = true;
               millisDeblockA = millis();       
            } 
    */
          }
    
          analogWrite(ENA_PIN,speedLocoA); // set throttle
        }
    
        // JUNCTIONS
        if (inputString.charAt(0) =='j') {    
         
          // Switch A
          if (inputString.charAt(1) =='a') { 
            if (inputString.charAt(2) =='0') {
              switch_A = false;
              J1.write(0); delay(50);
              digitalWrite(JUNCTION_EN, HIGH);
              millisJunction = millis();
            }
            if (inputString.charAt(2) =='1') {
              switch_A = true;
              J1.write(180); delay(50);
              digitalWrite(JUNCTION_EN, HIGH);
              millisJunction = millis();
            }
          } 
    
          flag_change_junc = true;
        }  
    
        inputString = "";
        stringComplete = false;
      
      }
    
    // ----  LOGIC BLOCK
      if (flag_change_junc) {
    
         if (switch_A) {
           digitalWrite(SIGNAL_A_GREEN, LOW);
           digitalWrite(SIGNAL_A_RED, HIGH);
           digitalWrite(RELAY_A, HIGH); // LINE A OFF              
         }
         else {
           digitalWrite(SIGNAL_A_GREEN, HIGH);
           digitalWrite(SIGNAL_A_RED, LOW);
           digitalWrite(RELAY_A, LOW); // LINE A ON        
         }
    
        flag_change_junc = false;
      }
    
      if (millis() > (millisJunction + 600)) digitalWrite(JUNCTION_EN, LOW);
     
      bluetoothEvent();
    }
    
    //// FUNCTIONS ////
    void bluetoothEvent() {
      if (Bluetooth.available()) {
        char inChar = (char)Bluetooth.read();
        inputString += inChar;
        if (inChar == 'z') {
          stringComplete = true;
        }
      }
    }
    

  • Connect to rails, signal and turnout
    void(* resetFunc) (void) = 0; // RESET FUNCTION
    
    #include <SoftwareSerial.h>
    
    // I/O PINS
    #define ENA_PIN 3
    #define IN1_PIN 2
    #define IN2_PIN 4
    #define PM_A 6
    #define PM_B 7
    #define SIGNAL_A_GREEN 14
    #define SIGNAL_A_RED 15
    #define RELAY_A 17
    
    SoftwareSerial Bluetooth(12, 13); // RX, TX
    
    // VARIABLES
      
      // SERIAL EVENT
      bool stringComplete = false;
      String inputString = "";
    
      // JUNCTIONS 
      bool switch_A = true;
      unsigned long millisJunction;
      
      // SPEED TABLE
      byte speedArrayA [] = {70, 100, 140, 180, 210, 255}; // CUSTOM THROTTLE
      byte speedLocoA;
    
      // CHECK CHANGES 
      bool flag_change_junc; 
    
    
    void setup() {
    
    // Initialize Serial 
      Serial.begin(9600);
      Bluetooth.begin(9600);
      inputString.reserve(4);
    
    // Initialize Motor Driver
      pinMode(ENA_PIN, OUTPUT); pinMode(IN1_PIN, OUTPUT); pinMode(IN2_PIN, OUTPUT);
    
    // Initialize Point-motor & SET DEFAULT POSITIONS
      pinMode(PM_A, OUTPUT);
      pinMode(PM_B, OUTPUT);
      digitalWrite(PM_A, HIGH);
      delay(600);
      digitalWrite(PM_A, LOW);
    
    // Initialize Signals & Relay
      pinMode(SIGNAL_A_GREEN, OUTPUT); 
      pinMode(SIGNAL_A_RED, OUTPUT); 
      digitalWrite(SIGNAL_A_RED, HIGH);
      pinMode(RELAY_A, OUTPUT);  
      digitalWrite(RELAY_A, HIGH) 
    }
    
    void loop() {
    
    // ----  START PARSING INCOMING APP COMMANDS  
      if (stringComplete) {
    
        // RESET LAYOUT
        if (inputString =="000z") resetFunc();
    
        // LOCO CONTROL FUNCTIONS
        if (inputString.charAt(0) =='a') {
          byte speedLocoA = 0; // be on the safe side set throttle to 0
    
          // Speed (0-6)
          if (inputString.charAt(1) =='0') { 
            if (inputString.charAt(2) =='0') speedLocoA = 0;
            if (inputString.charAt(2) =='2') speedLocoA = speedArrayA[0];
            if (inputString.charAt(2) =='4') speedLocoA = speedArrayA[1];
            if (inputString.charAt(2) =='6') speedLocoA = speedArrayA[2];
            if (inputString.charAt(2) =='8') speedLocoA = speedArrayA[3];
          }
          if (inputString.charAt(1) =='1') {
            if (inputString.charAt(2) =='0') speedLocoA = speedArrayA[4];
            if (inputString.charAt(2) =='2') speedLocoA = speedArrayA[5];    
          }
    
          // Direction, Stop and AWS
          if (inputString.charAt(1) =='d') {
            if (inputString.charAt(2) =='f') { // (f) Forward
              digitalWrite(IN1_PIN, HIGH);
              digitalWrite(IN2_PIN, LOW); 
            }
            if (inputString.charAt(2) =='b') { // (b) Backward
              digitalWrite(IN1_PIN, LOW);
              digitalWrite(IN2_PIN, HIGH); 
            }  
            if (inputString.charAt(2) =='s') { // (s) Stop button
               digitalWrite(IN1_PIN, LOW);
               digitalWrite(IN2_PIN, LOW); 
               speedLocoA = 0;
            } 
    /* AWS        
            if (inputString.charAt(2) =='r') { // (r) Release button | AWS
               aws_driverA = true;
               millisDeblockA = millis();       
            } 
    */
          }
    
          analogWrite(ENA_PIN,speedLocoA); // set throttle
        }
    
        // JUNCTIONS
        if (inputString.charAt(0) =='j') {    
         
          // Switch A
          if (inputString.charAt(1) =='a') { 
            if (inputString.charAt(2) =='0') {
              switch_A = false;
              digitalWrite(PM_A, HIGH);
              millisJunction = millis();
            }
            if (inputString.charAt(2) =='1') {
              switch_A = true;
              digitalWrite(PM_B, HIGH);
              millisJunction = millis();
            }
          } 
    
          flag_change_junc = true;
        }  
    
        inputString = "";
        stringComplete = false;
      
      }
    
    // ----  LOGIC BLOCK
      if (flag_change_junc) {
    
         if (switch_A) {
           digitalWrite(SIGNAL_A_GREEN, LOW);
           digitalWrite(SIGNAL_A_RED, HIGH);
           digitalWrite(RELAY_A, HIGH); // LINE A OFF              
         }
         else {
           digitalWrite(SIGNAL_A_GREEN, HIGH);
           digitalWrite(SIGNAL_A_RED, LOW);
           digitalWrite(RELAY_A, LOW); // LINE A ON        
         }
    
        flag_change_junc = false;
      }
    
      if (millis() > (millisJunction + 600)) {
        digitalWrite(PM_A, LOW);
        digitalWrite(PM_B, LOW);
      }      
     
      bluetoothEvent();
    }
    
    //// FUNCTIONS ////
    void bluetoothEvent() {
      if (Bluetooth.available()) {
        char inChar = (char)Bluetooth.read();
        inputString += inChar;
        if (inChar == 'z') {
          stringComplete = true;
        }
      }
    }