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.

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

Links to interesting resources about electronics for railway modeling and interesting products for railway prototyping.

Railway signal heads sets

♦♦♦ China Evemodel store ♦♦♦

If you seen video how I making the signal, the most difficult moment was the production of a lenses-light head. And so I found an interesting manufacturer that relieves you of this delicate process. Compared with the ready signals, the price is more than moderate. And kits are for the railway signaling of different countries. Even resistance is included.
The scale signals of HO.

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