Arduino Railroad Controller with iPhone Control (BLE, sonar, relays, etc)

Hey Guys,

Thought i'd share with you my current project. I built a railroad control system with a Mega. It handles everything from monitoring crossing gates, controlling a signal bridge, and controlling some track turnout. Some technologies used: relays, servos, dc motor, ble chip, electromagnet, and more). Had a lot of fun building this prototype!

Check out the video explaining the setup here: Link
And a bonus video where I added a car system: Link

If you have ANY questions about anything, please let me know. Thanks for viewing.

Nice project, I assume by your comment that you had "tried a current sense to trigger the crossing" that you are running DC not DCC, I like the sonics idea and servos are a great animation technique.

As it turns out I am also in the throws of developing a full featured DC system, but mine is based on the UNO, less pins but there is sufficient for the project, my points control uses a separate UNO and a 16 servo driver board that only uses 2 wires, this may be useful to you as your project develops to the layout stage. Link here http://www.ebay.com.au/itm/191736126715?_trksid=p2057872.m2749.l2648&ssPageName=STRK%3AMEBIDX%3AIT

Keep up the good work, there are not many Arduino Railroaders around that i have come across. :slight_smile:

PS: Just a thought......
I am hoping to put sound into my hand controller with a board i have found, but have not had much luck getting Tech details/Library info on it, maybe you have come across it in your travels, I'll attach a link below. http://www.ebay.com.au/itm/161962325684?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT

The key requirement is a very fast response time, about 100-150ms, I think this board will do it but cant get the data to prove it. There are other options out there but they start around $60 Australian plus post.

If you or anyone has used this item, all help appreciated.
Thanks. :slight_smile:

Hey WL888! thanks for checking it out :slight_smile: I actually run DCS, for ho the voltage on the track is around 19 vdc, about 3 amps. The current sensor I spoke of actually just reports voltage to the Arduino, but divided by 5 so the Arduino pin can handle it. With DCS, and DCC, the voltage on the track is pretty constant, however when the engine passes over a isolated block of track, you can measure the slight drop from it drawing current. This is similar to what real trains do. I might experiment more with this technique as I plan to add end of train devices to my trains which would draw current and help me detect the end of the train!

Thanks for the links, I had the HQ-300 laying around from another project, but I wouldn't mind programming my own sound board as well. I was thinking of getting one of these Adafruit Audio FX Sound Board - WAV/OGG Trigger with 2MB Flash : ID 2133 : $19.95 : Adafruit Industries, Unique & fun DIY electronics and kits.

I've also heard of people using http://www.midlandhardware.com/529527.html?gclid=Cj0KEQjw94-6BRDkk568hcyg3-YBEiQAnmuwkvTklrXtTXaQ7VZptM4y0402FhikLAkIg2_tcWxFAhkaAsIj8P8HAQ#.V0TtV1eMB-U and having more realistic results.

Yep..looked at the Adafruit but their postage is more than the item is worth...thats why i was looking at the chinese board.

The sound card is to hold several series of sound files, each series related to a specific Loco, which is selected from the LCD menu and controlled from the Throttle pot, as i don't run DCC the sound will come from the controller.

That is until I can figure a way to Selectively send them to the Loco to a Bluetooth Speaker.

I have just finished my crossing control using the 16 servo board and IR sensors, the sound will come from an Ebay MP3 player. This leaves me with potentially 14 more animations available from the same hardware.

If you are interested i will post the code here. :slight_smile:

WL888, yeah I'd love to see a video of what you've built :slight_smile: Just noticed you were in Australia, what type of trains do you run?

My layout is Australian theme circa 1906 Narrow Gauge ON30.
So, everything is either scratch or bash...layout is work in progress, but have had some trains running.
Don't know about a video but here is a proof of concept snap of the crossing.

/* Level Crossing Control
 * converted to use the Adafruit I2C 16 servo controller 
 * with UNO R3
 * Version V2.1 25/05/2016
 * Doug wl888
 * credits for original sketch to
 *  Version 1.4  Geoff Bunza 2015
*/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();                      // called this way, it uses the default address 0x40
int gate1servo = 0;
int gate2servo = 1;                                                    //ASSUMPTION Gate is down at position gatedownposition and up at position gateuppostion         
int gateuppostion  =  475;                                                    // servo position for gate up
int gatedownposition = 175;                                                   // servo position for gate down
int sensor1 = 8;                                                              // IR sensor pin Assumption== Pin goes LOW when train detected
int sensor2 = 9;                                                              // IR sensor pin Assumption== Pin goes LOW when train detected
int led1 = 2;                                                                 // Led 1 pin first alternating flasher
int led2 = 4;                                                                 // Led 2 pin first alternating flasher
int Bell = 3;                   //<<<<<<<at present this switches a LED but will trigger sound from an Ebay MP3 player
int gateposition = 120;                                                       // variable to store the servo gateposition
int leaving_sensor; // = 6;                                                   // this will tell which sensor shows train leaving
int gates_started = 0;                                                        // this says if the crossing is active
int flash_state = 0;
long flash_time = 0;
long  flash_interval = 900;                                                   // time in milliseconds between alternating flashes
int sensor_count = 0;
unsigned long previousMillisWAIT=0;                                           //Wait Millis() setup
int intervalWAIT = 30;
//=========================================================
void setup()
{
    Serial.begin(9600);
    pwm.begin();
    pwm.setPWMFreq(60);
    pinMode(sensor1, INPUT);  
    pinMode(sensor2, INPUT);
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
    pinMode(Bell,OUTPUT);  
    digitalWrite(led1, LOW);                                                    // Start with all flashers off
    digitalWrite(led2, LOW);
    digitalWrite(Bell, LOW);
    flash_time = millis();
}
//======================================================== 
void loop()
{
  if ((digitalRead (sensor1)==LOW)&& (gates_started==0)) {
    gates_started = 1;
    leaving_sensor = sensor2;
    starting_sequence();
  }
  if ((digitalRead (sensor2)==LOW)&& (gates_started==0)) {
    gates_started = 1;
    leaving_sensor = sensor1;
    starting_sequence();
  }
  if (gates_started) flash_leds();                                          //gates are down continue flashing
  if ((digitalRead(leaving_sensor)==LOW)&&(gates_started==1)) {             //train is starting to leave
                                                                            //as long as the leaving sensor is active the train is still in the crossing                                        
  while (gates_started==1)  {                                               //now check if train is REALLY gone
    sensor_count = 0;
    for (int i=1; i<40; i++)  {
      if (digitalRead(leaving_sensor)==LOW) sensor_count++;
          delay (30);
                  flash_leds();
                  }
    if (sensor_count==0) gates_started=0;
    flash_leds();
    }
                                                // we only get here if the train has really left the crossing
                ending_sequence();
  }
}
//==============================================================
void starting_sequence()  {
  digitalWrite(Bell,HIGH);
  long wait_time;
  flash_time = millis();
  wait_time = millis()+3000; 
  while (wait_time > millis())  flash_leds();                             //flash before dropping gates
  for(gateposition = gateuppostion  ; gateposition>gatedownposition ; gateposition-=1)  // goes from gateuppostion  degrees to gatedownposition degrees
  {  
     pwm.setPWM(0, 0, gateposition);
     pwm.setPWM(1, 0, gateposition);                            
    flash_leds();                                                         // keep flashing leds
    delay(40);                                                            // waits 40ms to slow servo
  }
}
//=============================================================== 
void ending_sequence()  {
    for(gateposition = gatedownposition ; gateposition<gateuppostion  ; gateposition++)   // goes from gatedownposition degrees to gateuppostion  degrees
  {  
     pwm.setPWM(0, 0, gateposition);
     pwm.setPWM(1, 0, gateposition);                            
    flash_leds();                                                             // keep flashing leds
    delay(40);                                                                // waits 40ms to slow servo
  }
  digitalWrite(led1, LOW);                                                    //  flashers completely off
  digitalWrite(led2, LOW);
  digitalWrite(Bell,LOW);
}
//============================================================== 
void flash_leds()  {
  if (flash_time > millis()) return;
  flash_state = ~flash_state;
  digitalWrite(led1, flash_state);                                            // Alternate flashers
  digitalWrite(led2, ~flash_state);
  flash_time = millis()+flash_interval;
}