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

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.

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