Project in progress
Model Railroad Grade Crossing Controller

Model Railroad Grade Crossing Controller © GPL3+

Arduino and easy to use photo occupancy sensors simplify control of the grade crossing signals and sound effects on a model railroad.

  • 1,943 views
  • 0 comments
  • 14 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
RAM Track 111 or 117 Dual Optical Detector PCB
×1
LED Flasher PCB
×1
Sound Replay PCB
×1
DFRobot 4 Relay Shield
×1
9 volt Power Supply
×1
Screw Terminal Shield
×1

About this project

Our local model railroad club had a collection of mismatched detectors, signal PCB's, a sound card, and of course the masts for each side of the track with LEDs for indicators.

We utilize an Arduino UNO to read the state of two optical detectors, generate a START pulse when occupancy is first detected, as well as a latched relay output to energize the sound card. If after 3 seconds there has been no activity at either detector, a STOP pulse is generated, and the latched relay released, turning off the sound.

Subroutines for the input debouncing, and START and STOP pulses make the main loop and hopefully the whole program much easier to follow. I've also removed most of the commenting from the debounce subroutines. They are based on the example debounce sketch and I refer you there for more detailed commenting.

Code

Capreol Museum Rail / Road Crossing ControllerArduino
// set pin numbers:
const int buttonAPin = A1;     // the number of the pushbutton pins
const int buttonBPin = A2;
 
const int ledPin =  13;      // the number of the LED pin
const int RelayA = 2;     // the number of the relay coil drive pin
const int RelayB = 3;
const int RelayC = 11;
 
// Define Variables
int buttonAState = HIGH;
int lastButtonAState = HIGH;

int RUNNING  = LOW;
int OCCUPIED = LOW;

int buttonBState=HIGH;
int lastButtonBState = HIGH;


// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.

unsigned long lastDebounceTimeA = 0;
unsigned long lastDebounceTimeB = 0;

unsigned long debounceDelay = 50;
unsigned long loopdelayA = 500;
unsigned long looptriggerA;
unsigned long loopdelayB = 500;
unsigned long looptriggerB;
unsigned long RUNNINGtime = 3000;
unsigned long RUNNINGtrigger;

#include <LiquidCrystal.h>

// Select the pin used on LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup() { 

  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("KEVino 2017");
  lcd.setCursor(0, 1);
  lcd.print("RAILCROSS");
  delay(1000);
  // scroll 16 positions (string length) to the left
  // to move it offscreen left:
  for (int positionCounter = 0; positionCounter < 16; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayRight();
    // wait a bit:
    delay(30);
  }
  {
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Railcross");
  }  
  Serial.begin(9600);
 
  pinMode(ledPin, OUTPUT);
  pinMode(RelayA, OUTPUT);
  pinMode(buttonAPin, INPUT_PULLUP);
  pinMode(RelayB, OUTPUT);
  pinMode(buttonBPin, INPUT_PULLUP);
  pinMode(RelayC, OUTPUT);
 
}

void debounceA()                         
{
  int readingA = digitalRead(buttonAPin);

  if (readingA != lastButtonAState)
  {
    lastDebounceTimeA = millis();
    looptriggerA = millis();
  }
  if ((millis() - lastDebounceTimeA) > debounceDelay)
  {
    if (readingA != buttonAState)
    {
      buttonAState = readingA;
    }
  }
  lastButtonAState = readingA;
  lastDebounceTimeA = 0;
  return;
}

void debounceB()                        // Debounce A2 input
{
  int readingB = digitalRead(buttonBPin);

  if (readingB != lastButtonBState)
  {
    lastDebounceTimeB = millis();
    looptriggerB = millis();
  }
  if ((millis() - lastDebounceTimeB) > debounceDelay)
  {
    if (readingB != buttonBState)
    {
      buttonBState = readingB;
    }
  }
  lastButtonBState = readingB;
  lastDebounceTimeB = 0;
  return;
}

void START()                      // 1/2 second pulse on Relay A,
{                                 // RUNNING set HIGH,, Relay C set.
  RUNNINGtrigger = millis();
  digitalWrite(RelayA, HIGH);
  digitalWrite(RelayC, HIGH);
  delay (500);
  digitalWrite(RelayA, LOW);
  RUNNING = HIGH;
}
void STOP()                       // 1/2 second pulse on Relay B,
{                                 // RUNNING set LOW,, Relay C cleared.
  RUNNINGtrigger = millis();
  digitalWrite(RelayB, HIGH);
  digitalWrite(RelayC, LOW);
  delay (500);
  digitalWrite(RelayB, LOW);
  RUNNING = LOW;

}

void loop()
{
  lcd.setCursor(13, 0);                            // Display seconds elapsed
  lcd.print(millis() / 1000);
 
   
  debounceA();                                     //Debounce the sensor inputs
  debounceB();                
  digitalWrite(ledPin, OCCUPIED);                  // Use LED to indicate OCCUPIED
  
  if (buttonAState == LOW || buttonBState == LOW) 
  {
    OCCUPIED = HIGH;
    RUNNINGtrigger = millis();     
    Serial.write("OCCUPIED");
    Serial.println();
     lcd.setCursor(0, 1);
     lcd.print("Occupied");  
  }
  else
  {
    OCCUPIED = LOW;
    lcd.setCursor(0, 1);
    lcd.print("        ");  
  }

  if (OCCUPIED == HIGH && RUNNING == LOW)
  {
    START();
    Serial.write("START");
    Serial.println();
      lcd.setCursor(8, 1);
      lcd.print("RUNNING"); 
  }

  if (RUNNING == HIGH)
    if ((millis() - RUNNINGtrigger) > RUNNINGtime)
    {
      STOP();
      Serial.write("STOP");
      Serial.println(); 
      lcd.setCursor(8, 1);
      lcd.print("       "); 
    }

}

Schematics

Model Railroad Grade Crossing Controller
Img 0074 imjcle37pa
Model Railroad Grade-crossing Controller
Img 0634 fwl7czpak3

Comments

Similar projects you might like

Railroad Crossing Lights

Project showcase by eldo85

  • 2,378 views
  • 4 comments
  • 6 respects

Automatic Water Level Controller

Project showcase by karthickcj0083

  • 13,048 views
  • 6 comments
  • 19 respects

Model Train Control

Project in progress by Masters

  • 6,139 views
  • 3 comments
  • 11 respects

Joystick Controller for MeArm Robot - Recording Coordinates

Project tutorial by utilstudio

  • 1,367 views
  • 2 comments
  • 18 respects

Plant Waterer Controller

Project in progress by Paulo Soares

  • 1,235 views
  • 1 comment
  • 5 respects

RGB LED Button Controller

Project showcase by Re

  • 7,942 views
  • 1 comment
  • 12 respects
Add projectSign up / Login