Basic sketch

The main example that implements trains control along two independent lines from two phones. Two Bluetooth modules provide two communication channels over serial ports, one of which is software serial. This example is fully functional only with the application version of Pro. A video on YouTube shows the work of this sketch.

Components of the example: any versions URB, Arduino NANO, 5V to 3.3V Logic Level Converter, two modules HC-06 (05) and motor-driver L298. The principles of the whole project are the same as in the example for beginners.

The system works like this. The user's control actions on the phone or tablet are converted by the application into protocol commands, which are then transmitted via Bluetooth to Arduino. The sketch parses these commands and in accordance with them changes the levels on the outputs of D2-D7.

By changing the pwm-variable in the code, you can individually adjust the parameters of the movement of your locomotives. Slightly changing the code, you can enter such physical parameters as inertia, locomotive thrust power and others!

Another fun application of URB - games like Raceway Toy. It is enough to hide the URB and details in the accurate box, and your children will use their smart phone not only for online games! If you permanently change the control parameters in a sketch, then for an adults this famous game becomes not boring.

Communicate station sketch

Typical connections

URB to PC connection
Switch-motor
station control panel
Control panel
lights on  layout
Lighting layout
railway crossing barrier gear
Railway crossing
signalling
Light signals
Automate

Introduction to I2C bus

After several successful experiments, the modeler faces the problem of lack of I/O pins on Arduino. And many people try to solve this problem directly, change board UNO or NANO to bigger Arduino (DUE, Mega). It seems to me wrong, the problem still remains. The best way - to unite the microcontrollers to the network, which allows you to scale the I/O pins almost endlessly. The I2C bus is a good fit for this. It has native support in the Arduino and has addressing, in contrast to the serial connection solution.

Many people do not know about the use of this bus for building a network, the most famous example of its application is the connection of a LCD screen to Arduino by two wires. There is even a widespread module LCD Adapter Plate I2C on chip PCF 8574 for Arduino, and it will come in handy later.

The bus I2C works with addresses in master-slave mode. This means that only the main device can send data, other I2C blocks on the bus can only respond to requests from the main, or simply execute commands. This limitation gives some inconvenience in transferring data from sensors from local URB to the communication station, which in my project is always the master by default.

For Arduino there is no good library that implements the multi-master mode for this bus, and, as far as I know, this is due to the great difficulties of arbitrating the bus in this mode. In general, I'm in favor of using only the built-in libraries of Arduino.

Therefore, I place here sketches that combines both data transfer and a query with subsequent data retrieval. This is different from the classic examples the Wire library from Arduino IDE.

Chain of three URB's

Components of the example: 3 URB (v.2.6-2.7), 3 Arduino NANO, 1 Logic Level Converter, 1 module HC-06 (05), 2 servos Micro Tower, 1 ULN2003 (DIP-16) and Hall sensor module.

To power this design, just connect the USB cable. This is one of the examples of «design on the table» on which it is convenient to practice sketches. The joint operation of the URB blocks allows you to rotate the servos by commands from a computer or my application, and also rotate the drives to a position of 90 degrees as the magnet approaches the Hall sensor. Also, the URB #2 using the ULN 2003 turns on servos only at the moment of their rotation.

Of course, it is possible to assemble a circuit with servos, a bluetooth module and a sensor on one URB board, but this simple example illustrates how to apply the bus to a layout.

Sketch URB #1 Sketch URB #2 Sketch URB #3

Railway peripheries

This is my favorite part of the site. Here you will find ways and ready solutions for making mechanisms and details for reviving your layout.

Here is collected all the fun that I came up with.

If you think about what we need for a railway layout, then the answer to this question will be only three things: devices for something moving (or rotating), sensors and lightings. The specialization of each of these things will give us all solutions for the periphery. And the first chapter is devoted to moving gizmos.

1. Switch-motor

By this mechanism, I am proud as designer! The task was to make such a reliable junction switch-mechanism, which will simply and quickly manufactured, while ensuring accuracy of moving the rod to a tenth of a millimeter.

Given the large error in the position of the lever of the cheap servo when stopping after rotation, and the need of convenient adjustment without tools at the installation site, the task seemed to me unsolvable. However, I came up with, and even much more.

Shoulders slingshot, as well the mechanism, made of thin galvanized sheet metal, this material is available almost everywhere. So, by bending them with your finger you can adjust the stroke of the rod and, accordingly, the accuracy of the junction switch position. In addition, these shoulders act as a damper, parrying the errors of the mechanical transmission and securely fix the switch mechanism in the extreme positions. But that is not all. If the servo arm is stop to a position of 90 degrees, the mechanism is unlocked and you can switch the junction manually.

In the ArduinoTrain BtControl Pro app there is a special button «Deblock».

Video instruction on the manufacture of two variants of the switch-mechanism. The drawings are here. This mechanism can for linear displacement of layout elements.

You can install this mechanism vertically, horizontally, at an angle, on the layout, under the layout - anywhere! Using long rods and rockers to change the movement vector, it is possible to mechanize very complex multi-junctions yards.

Also you can also use URB to control your switch point with a standard inductive drive.

2. Lighting

Lighting adds a realism to the model railway layout. But simple light bulbs are boring, it is better if every window of all houses will individually turn on the light. Even better, if there are fade-in effects, or flashing, like a broken fluorescent tube. Also, street lights should use dimming and station buildings should also be included in lights groups. This means we need a lot of control channels and it's expensive and complica-a-a-a-ted.

And here not! With the URB it's easy, and even more so, you can add a random algorithm for lighting windows, you can also still put an ambient light sensor and your railway world will react to begin the night. You can control this and the real buttons on the control of the layout, and from the phone using my application. And you will periodically change lighting rules by simply uploading a new sketch!

My layout on assembled on a shelf, and there are 48 light channels, and this is far no limit.

Connecting LED Lighting

Each URB has 6 skrew outputs D2-D7 with a current of up to 500 mA (7 if you do not use servos). Outputs D3, D5 and D6 in the middle can be operated in PWM mode and you will use them for dimming. All pins have a voltage of 5 volts, so you can easily calculate the maximum number of LEDs possible to connect to one pin. For example, if you use cylindrically LED of white light, then its current with a serial current-limiting resistor of 150 Ohm is about 25 mA, then their total numbers will be 20 per channel. Numbers more powerful SMD LEDs, like 3528, assembling will be less per channel. Pay attention to the non-standard connection scheme with a common plus. Just in case :) instead of LEDs it is possible to include usual bulb lamps, only at them very much big a current!

ULN2003 DIP-16 is a cheap and widely available chip. In my experience, part of the copies of this chip (depending on the manufacturer) starts to get very hot at currents of more than 350 mA per channel. But even if it broke, you can easily replace it.

Starting with the version of URB 2.6 it is possible to connect a 12 V load. You can connect 12V LED-tapes direct to the pins. Read more here.

DIY examples

There are seven channels on the group of houses on the video. Since there is a need for a simple ON/OFF mode, it is possible to make the 8-channels management even cheaper using a ready LCD I2C module on the chip PCF8574. You can see how he gets commands via the I2C bus from the communication dual URB.

Assembly instructions for this device are included in the Donators Documentation Kit.

To avoid complicated installation of LEDs in windows, as usual, I offer you a ready-made convenient solution. Take a picture of the house in which you want to install lighting and using a graphic program make a simple template, another option is to squeeze food foil to the facade and create a relief of windows with your finger, then draw the template on thick paper. Collect the box of smaller size than the area of the house (see photo). Then simply glue the LEDs with a double-sided tape in windows places, and connect them with a wires to the circuit shown above. LEDs can simply be cut from –į LED strip. Arrays of resistors are very convenient in this case.

It is better to choose LEDs of different wavelengths in nanometers. Thus, you can use many shades of light from warm to cold white.

Local URB control and effects

It is not difficult to control such a number of channels if you adhere to the main rule: all LEDs from a particular building (for example, a house) should be connected to the nearest URB. Do not use long wires! Everything will work, but you will get confused when you start to write sketches. If you have a multi-window structure, or a houses group, use PCF8574. Thanks to this rules, most of the management of the lighting channels is performed by a local URB. Only the general command comes from the communication station.

After such a long introduction, I'll explain why there are so many channels. In the real world, people turn the light on and off randomly. The simplest way to simulate this is to introduce delays, for example at station: first lights are switched on in the cafeteria and the cashier's area, after the light is on the entire first floor, then on the second and finally the platform lighting turns on.

You can see how it works on the general video of the project. The light on the platform can also flash several times, and only after then constantly glow. That is, you can do it programmatically yourself, and then how convenient it is for you to change the behavior of the layout. And of course, you can apply fade-in fade-out effects, it is especially suitable for street lights. I installed on my layout a separate URB with a photodetector, and now when the room gets dark, if the power of the layout is turned on, he turns on the evening lights. The Arduino platform also allows you to use the function random() for this. I think sketches for this you write yourself, or will push me to continue the topic.

Main control

In order not to be confused with the word «channel», we leave it for local URBs. Here I will use the word «lines».

In the application ArduinoTrain BtControl version of the Pro is 10 control lines, in the version of Light - 2 lines.

The commands sent by the Application to the Communication station are described in the protocol. They are also parsing in the same program block as the locomotive management commands. It's very simple!

Thus, changing the local URB address in the code, you distribute linear commands in them through I2C bus, and they, as described above, do the rest of the work. For example, the Communicate URB #1 translated command "laz" as byte command variable, and send this into the local URB #3 and #5. URB #3 dimmed up the street lights, URB #5 with the set delays in her sketch, sequentially turns on the station lighting (see introduce picture at How it Station). Sketches for this you can adapt from samples «Basic sketch» and «Introduction to I2C bus».

3. Signalling system

Railway signals are rarely found on layout, and their availability is a sign of professionalism. Not this the modelers do not want to install them, but that not a trivial task - the algorithm for switching many signals needs to corrected for each railway line. So you need a large computer with software or branded digital sets from manufacturers. Or soldering their own boards on logic chips.
But with the Arduino everything becomes much better. Convenient direct connection of signals and sensors to the URB connectors provides easy installation. Together with the availability of information on the position of all junctions and the ease of programming Arduino all it is now easiest. Without any computers! Just turn layout power on and everything works!

In fact, programming automatic switching of light signals is a fun. I mean, get a peep of how this luminous color "magic" works itself after the your sketch has been filled and running. In this chapter I give a simple example, but even it shows ways to automate the movement of trains. Next, in the chapters Automation and Layout A, everything will be even more cool!

Again, I will give several principles:

  1. The best option is if the switching logic is programmed in the sketch of the URB to which the signals are connected.
  2. The communication station provides only general control of the status of the layout lines.
  3. Do not do manual control of traffic lights, let everyone do sketches on Arduinos.

On the diagram, I drew a two-wire connection of signals. If you have a three-wire signal with a ground contact, then the sketch does not need any changes, just connect the GND contact to the GND of the URB.

In this example, the railroad yard is controlled by a URB to which two switch-motors, a dual relay and two semaphores are connected. From the communication station to in the URB comes one command to switch two junctions, the rest of the action is performed by the URB. So you can split two oncoming trains in one line. By modifying this sketch you can control signal lights of the dead-end branch and other things. With the addition of sensors to appear, you can do an interlocking on your layout (soon there will be an article called Automate II).

Please note that this sketch is also a changed version of the sketch for URB #2 from the example of «Introduction to I2C bus», nothing complicated. Also in the sketch are added the lighting commands of the station.

The yard sketch

Feedback

Version 4.4 and higher of the application, feedback is fully supported. This makes it possible to extend the use of layout sensors to control trains. Add line state information to the application interface. And gradually will be new features to the project. URB was originally designed for this possibility and the re-equipment of the layout hardware for the use of feedback is not required. You only need to correct the sketch for the URB.

Currently, two feedback options are supported: automatic train stop before deadlock and displaying in the application the real position of junctions on the layout. The first possibility is called AWS and will expand in the future.



AWS

The AWS button in the application was made to unlock the sensor. An example with a deadlock explains this principle, but you can expand the scope of this function by changing the communication station sketch yourself to your needs. In the example, the train moves along the line to the deadlock and when the locomotive crosses with the sensor position from the line, the current turns off the relay. This is a well-known solution. But, when there will be a necessity of movement of a train again, there will be a problem - while the train is over the sensor it is impossible to move again. Thus, upon the command from the application, it is necessary to bypass the signal from the sensor. To do this, the application always had a button AWS (Deblock), which forced the sketch ignore the signal from the sensor for five seconds.

However, the player did not know why the locomotive does not move, and for him now information about the sensor's operation is the bright yellow glow of the button, and by pressing it the line is unlocked and it goes out. When the train will not move again in five seconds interval, then the signal will turn bright yellow again.

The sketch that implements these functions can be taken from the chapter Example of a simple layout.

The junction position

The motor switching of the junction in railway modeling gives a lot of unobvious opportunities and gives rise to several problems. For example, the position of the junction can be uniquely associated with traffic light signals and, as a result, get a ready signal system. But at the same time, most of the modellers make bulky and complex panels, and their upgrade will very complicity. This problem is further aggravated by the fact that the position of the arrows is not always known after the layout is turned on.

All this was taken into account in the development of this project by changing the sketches of a particular URB, you can program any logic of the behavior of the signals. Also in the application there is a button 'Default', which sets junction to the position assigned user, the same happens when the layout is initialized when the power is turned on. Since there may be more than one player in the project, this button also helps to synchronize the position of the lines during the game.

There was one problem, the visual control of the position of the lines had to be carried out in a separate position indication board. Now, with the support of feedback, the need for this has disappeared. The picture's icon in the application now corresponds to the actual position of the junction on the layout.

If you do not want to use this function, or you have a version "Junior", which does not support switching junctions with feedback, then in the version PRO there is a switch "Feedback" which disables this option. When using feedback mode the sketch remains unchanged, the line for returning information to the application is appended to it. In the layout below, feedback is implemented in the sketches.


Example of a simple layout

Summarizing the previous articles, step by step in this chapter build a simple layout.

Planning

There is no need to change your ideas in favor of electrical connections in your layout. The idea of this project, based on the data bus does not limit you in the design - connect the rails as you like. You can always easily change your layout by simply updating sketches. Also, you do not need to immediately install all the devices on the layout, it is easier to gradually increase the functionality: first make a control system for trains, and then add signals, switch-mechanisms and so on. All devices on the layout can be connected to any URB on the layout. The only rule is if more than two devices are installed in the local location of the layout, then you need to install the URB there. That is, do not pull the wires from the device to the microcontroller through the entire layout.

Step 1

In order for the article to be "live", in the process of writing I will come up with a layout and add functionality to it. In doing so, I will be rewrite sketches, and, if necessary, I will added new blocks of URB.

I conceived a layout from one circle, station and central yard.

Step 2

The connection of the motor-driver and the sketch is described in detail here or here, so we will immediately consider the general solution together with the mechanization of junctions. For this I use three URB blocks.

To the first URB I connect the motor driver and junctions 1 and 2, to the second URB - junction 3, and to the last URB - junction 4. The first URB named Communicate URB. For each URB, the sketches are shown below. All blocks are connected by a four-wire bus (brown line).

Communicate URB

// ARDUINORAILWAYCONTROL.COM
// Communication_station_simple_layout.ino
// V.1
// 01.04.2017
// Author: Steve Massikker
// For Universal Rail Bus unit  V.2.4 and higher

/////// COMMUNICATE STATION ///////


#include <SoftwareSerial.h>
#include <Servo.h>
#include <Wire.h>

//// GPIO PINS ////

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

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

// SERVO
#define JUNCTION_EN 8
#define JUNCTION1_PIN 9
Servo J1;
#define JUNCTION2_PIN 10
Servo J2;


//// VARIABLES ////
boolean stringComplete = false;
String inputString = "";
int addressI2C;
byte dataToI2C; 
unsigned long millisJunction;

void setup() {

// Initialize I2C
  Wire.begin();  // Master I2C mode

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

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

// Initialize Servos
  pinMode(JUNCTION1_PIN, OUTPUT); J1.attach(JUNCTION1_PIN);
  pinMode(JUNCTION2_PIN, OUTPUT); J2.attach(JUNCTION2_PIN);  
  pinMode(JUNCTION_EN, OUTPUT); 

}

void loop() {

  if (stringComplete) {
    

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

    //THROTTLE
    if (inputString.charAt(0) =='t') {   
      if (inputString.charAt(1) =='0') analogWrite(ENA_PIN, 0);
      if (inputString.charAt(1) =='1') analogWrite(ENA_PIN, 50);
      if (inputString.charAt(1) =='2') analogWrite(ENA_PIN, 100);
      if (inputString.charAt(1) =='3') analogWrite(ENA_PIN, 150);
      if (inputString.charAt(1) =='4') analogWrite(ENA_PIN, 200); 
      if (inputString.charAt(1) =='5') analogWrite(ENA_PIN, 255); 
    }

    // 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);
      } 
    }
 
    // JUNCTIONS

    // J1
    if (inputString.charAt(0) =='j') {
      if (inputString.charAt(1) =='a') {
        J1.write(0);
        delay(25);
        digitalWrite(JUNCTION_EN, HIGH); // servo power on
        millisJunction = millis();  // servo power off
        Bluetooth.print("az"); // feedback command 
      }
      if (inputString.charAt(1) =='b') {
        J1.write(180);
        delay(25);
        digitalWrite(JUNCTION_EN, HIGH);
        millisJunction = millis();
        Bluetooth.print("bz");
      } 

    // J2   
      if (inputString.charAt(1) =='c') {
        J2.write(0);
        delay(25);
        digitalWrite(JUNCTION_EN, HIGH);
        millisJunction = millis();
        Bluetooth.print("cz");
      }  
      if (inputString.charAt(1) =='d') {
        J2.write(180);
        delay(25);
        digitalWrite(JUNCTION_EN, HIGH);
        millisJunction = millis();
        Bluetooth.print("dz");
      } 

    // J3              
      if (inputString.charAt(1) =='e') {
        dataToI2C = 30; 
        addressI2C = 2;
        sendDataViaI2C(); 
        Bluetooth.print("ez");
      }  
      if (inputString.charAt(1) =='f') {
        dataToI2C = 31; 
        addressI2C = 2;
        sendDataViaI2C(); 
        Bluetooth.print("fz");
      }

    // J4              
      if (inputString.charAt(1) =='g') {
        dataToI2C = 30; 
        addressI2C = 3;
        sendDataViaI2C(); 
        Bluetooth.print("gz");
      }  
      if (inputString.charAt(1) =='h') {
        dataToI2C = 31; 
        addressI2C = 3;
        sendDataViaI2C(); 
        Bluetooth.print("hz");
      } 
    }      

// ----------- END COMMAND PARSING ----------- // 
    dataToI2C = 0;
    inputString = "";
    stringComplete = false;    
  }

  bluetoothEvent();
  if (millis() > (millisJunction + 800)) digitalWrite(JUNCTION_EN, LOW);  // delay servo power OFF
 
}

// ----------- FUNCTIONS ----------- // 

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

void sendDataViaI2C() {
  Wire.beginTransmission(addressI2C);
  Wire.write(dataToI2C);
  Wire.endTransmission();
}
URB#2

// ARDUINORAILWAYCONTROL.COM
// URB_2_simple_layout.ino
// V.1
// 01.04.2017
// Author: Steve Massikker
// For Universal Rail Bus unit  V.2.4 and higher

/////// URB#2 ///////

#include <Servo.h>
#include <Wire.h>

// SERVO
#define JUNCTION_EN 8
#define JUNCTION1_PIN 9
Servo J1;

//// VARIABLES ////
boolean stringComplete = false;
String inputString = "";
byte dataFromI2C; 
unsigned long millisJunction;

void setup() {

// Initialize I2C
  Wire.begin(2);  // I2C address 2
  Wire.onReceive(receiveI2C);

// Initialize Serial
  Serial.begin(9600);

// Initialize Servos
  pinMode(JUNCTION1_PIN, OUTPUT); J1.attach(JUNCTION1_PIN);
  pinMode(JUNCTION_EN, OUTPUT); 

}

void loop() {
// COMMAND PARSING
  if (dataFromI2C != 0) {
    switch (dataFromI2C) {

    case 30: J1.write(0);
             delay(25);
             digitalWrite(JUNCTION_EN, HIGH);
             millisJunction = millis(); break;

    case 31: J1.write(180);
             delay(25);
             digitalWrite(JUNCTION_EN, HIGH);
             millisJunction = millis(); break;
    } 

  dataFromI2C = 0;

  }

  if (millis() > (millisJunction + 800)) digitalWrite(JUNCTION_EN, LOW);

} 

// ----------- FUNCTIONS ----------- // 

void receiveI2C(int howMany) {
  while (Wire.available() > 0) {
    dataFromI2C = Wire.read();
    if (dataFromI2C != 0) {
      Serial.println("I2C - ");  
      Serial.print(dataFromI2C);
    }
  }
}

URB#3

Since before this step the functions of URB#2 and URB#3 are the same, then the sketches are the same. The only difference between the two is to change the address of I2C to 3 in the void setup section:

 
// Initialize I2C
  Wire.begin(3);  // I2C address 3

Step 3

By this step, you already have a full-featured circuit and you can play using the entire line of applications Arduino Train. Also, you can directly test the device layout using a computer.

Now, in order to use several locomotives, we will add four relays, with which we will block the rails depending on the position of junctions. I propose to connect the dual relay units to URB#2 and URB#3. So just change their sketches, for URB#2 and URB#3 sketches will be equal. The sketch of the communication station will be left unchanged.

In the same sketch you can add signals, the logic of their behavior corresponds to the relay switching. Attach the signal wires to the contacts of URB A0-A3 and add strokes to the sketch like: digitalWrite(14, HIGH); ... etc.

URB#2 and URB#3

// ARDUINORAILWAYCONTROL.COM
// URB_2_simple_layout.ino
// V.2
// 01.04.2017
// Author: Steve Massikker
// For Universal Rail Bus unit  V.2.4 and higher

/////// URB#2 ///////

#include <Servo.h>
#include <Wire.h>

// SERVO
#define JUNCTION_EN 8
#define JUNCTION1_PIN 9
Servo J1;

// RELAY
#define RELAY_1 12
#define RELAY_2 13

//// VARIABLES ////
boolean stringComplete = false;
String inputString = "";
byte dataFromI2C; 
unsigned long millisJunction;

void setup() {

// Initialize I2C
  Wire.begin(2);  // or Wire.begin(3);
  Wire.onReceive(receiveI2C);

// Initialize Serial
  Serial.begin(9600);

// Initialize Servos
  pinMode(JUNCTION1_PIN, OUTPUT); J1.attach(JUNCTION1_PIN);
  pinMode(JUNCTION_EN, OUTPUT);

// Initialize Relays   
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);

}

void loop() {
// COMMAND PARSING
  if (dataFromI2C != 0) {
    switch (dataFromI2C) {

    case 30: J1.write(0);
             delay(25);
             digitalWrite(JUNCTION_EN, HIGH);
             millisJunction = millis(); 
             delay(50);
             digitalWrite(RELAY_1, HIGH);
             digitalWrite(RELAY_2, LOW); break;

    case 31: J1.write(180);
             delay(25);
             digitalWrite(JUNCTION_EN, HIGH);
             millisJunction = millis(); 
             delay(50);
             digitalWrite(RELAY_1, LOW);
             digitalWrite(RELAY_2, HIGH); break;
    } 

  dataFromI2C = 0;

  }

  if (millis() > (millisJunction + 800)) digitalWrite(JUNCTION_EN, LOW);

} 

// ----------- FUNCTIONS ----------- // 

void receiveI2C(int howMany) {
  while (Wire.available() > 0) {
    dataFromI2C = Wire.read();
    if (dataFromI2C != 0) {
      Serial.println("I2C - ");  
      Serial.print(dataFromI2C);
    }
  }
}


Step 4

Add AWS stop feature. To do this, we place two Hall sensors on rails. The implementation of this function is described above. It remains only to write the code in the Communication URB and the URB#2 sketches.

You can use either light or infrared sensors of your choice.

URB#2

Initialize sensors in the header of the sketch.


#define HALL_A 10
#define HALL_B 11

//// VARIABLES ////
byte dataToI2C, dataFromI2C; 

Define the state I/O pins in the Void Setup code block.


// Initialize Halls
  pinMode(HALL_A, INPUT); 
  pinMode(HALL_B, INPUT);

  Wire.onReceive(receiveI2C);
  Wire.onRequest(requestI2C);

Adding code to Void Loop for response of the sensors state on request from the Communication station. And at the end of the sketch, insert the processing function I2C. See also there.


  if ((digitalRead(HALL_A) == LOW) || (digitalRead(HALL_B) == LOW) ) dataToI2C = 1;    
  else dataToI2C = 0;

  // ----------- FUNCTIONS ----------- // 

void receiveI2C(int howMany) {
  while (Wire.available() > 0) {
    dataFromI2C = Wire.read();
    if (dataFromI2C != 0) {
      Serial.println("I2C - ");  
      Serial.print(dataFromI2C);
    }
  }
}
  
void requestI2C() {
  Wire.write(dataToI2C);
}
Communication station

The sketch of the –°ommunication station is even easier to change. You just need to add two variables to the sketch header - boolean deblockAWS; and unsigned long millisAWS;


// --------------- I2C REQUEST --------------- // 

  static unsigned long prevTime = 0;

  if (millis() - prevTime > 300) {
    addressI2C = 2;
    Wire.requestFrom(addressI2C, 1);    // request byte from slave device 
    prevTime = millis();
    dataFromI2C = Wire.read(); 
  }

  if ((dataFromI2C == 1) && (!deblockAWS)) {
     Bluetooth.print("hall1z");
     analogWrite(ENA_PIN, 0);
  } 

  if (millis() > (millisAWS + 5000)) deblockAWS = false;  

And in the parsing block add the code.


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

    //AWS
    if (inputString =='d1') deblockAWS = true; 

 

Step 5

The last step will be lighting on the layout. The application allows you to manage several light channels, and we will apply this opportunity to the station, the central yard and a separate city. I will add one more URB for city.

The principle of the code is the same as with junctions - the Communication URB after receiving a command from the Application translate them to the final URB. URB turns on or off D2-D7 lighting channels, applying delay or fading effects to them. I leave it to you to write these sketches yourself.


Two player mode

Under Construction


Setting up layout devices
in sketches

Under Construction