Inspired by some of some of Geoff Bunza’s work, John Cornell used an Arduino Uno to control level crossing (grade-crossing) booms and LED flashers. The details of John’s project are described below.
The booms are controlled by small servo-motors. Occupation detection is done via a simple circuit using a small toroidal transformer to detect the DCC feed to the track, in a block extending either side of the crossing. The occupation detection circuit and the Arduino are powered directly from the track as well.
Details of the project are shown below – enjoy!
John Cornell
Arduino Sketch
// Example Level Crossing Control
// Version 1 John Cornell 2015
// Uses software servo Library
//
#include <Servo.h>
Servo gate1servo; // create servo object to control crossing gate 1
//ASSUMPTION Gate is down at position 30 and up at position 120
Servo gate2servo; // create servo object to control crossing gate 2
//ASSUMPTION Gate is down at position 30 and up at position 120
int sensor1 = 5; // IR sensor pin Assumption== Pin goes LOW when train detected
int led1 = 10; // Led 1 pin first alternating flasher
int led2 = 11; // Led 2 pin first alternating flasher
int led3 = 12; // Led 3 pin second alternating flasher
int led4 = 13; // Led 4 pin second alternating flasher
int gateposition = 120; // variable to store the servo gateposition
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
void setup()
{
gate1servo.attach(3); // attaches the servo on pin 3 to the servo object
gate2servo.attach(4); // attaches the servo on pin 4 to the servo object
gate1servo.write(gateposition); //start assuming no train
gate2servo.write(gateposition); //start assuming no train
pinMode(sensor1, INPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
digitalWrite(led1, LOW); // Start with all flashers off
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
flash_time = millis(); // time since sketch started
}
void loop()
{
if ((digitalRead (sensor1)==LOW)&& (gates_started==0)) {
gates_started = 1;
starting_sequence();
}
if (gates_started) flash_leds(); //gates are down continue flashing
if ((digitalRead(sensor1)==HIGH)&&(gates_started==1)) { //Train has left
ending_sequence();
}
}
void starting_sequence() {
long wait_time;
// flash_time = millis(); was this wrong?
wait_time = millis()+3000;
while (wait_time > millis()) flash_leds(); //flash before dropping gates
for(gateposition = 120; gateposition>30; gateposition-=1) // goes from 120 degrees to 30 degrees
{
gate1servo.write(gateposition); // tell servo to go to gateposition in variable 'gateposition'
gate2servo.write(gateposition); // tell servo to go to gateposition in variable 'gateposition'
flash_leds(); // keep flashing leds
delay(40); // waits 40ms to slow servo
}
}
void ending_sequence() {
for(gateposition = 30; gateposition<120; gateposition++) // goes from 30 degrees to 120 degrees
{
gate1servo.write(gateposition); // tell servo to go to gateposition in variable 'gateposition'
gate2servo.write(gateposition); // tell servo to go to gateposition in variable 'gateposition'
flash_leds(); // keep flashing leds
delay(40); // waits 40ms to slow servo
}
gates_started = 0; // gates are open
digitalWrite(led1, LOW); // flashers completely off
digitalWrite(led3, LOW);
digitalWrite(led2, LOW);
digitalWrite(led4, LOW);
}
void flash_leds() {
if (flash_time > millis()) return;
flash_state = ~flash_state;
digitalWrite(led1, flash_state); // Alternate flashers
digitalWrite(led3, flash_state);
digitalWrite(led2, ~flash_state);
digitalWrite(led4, ~flash_state);
flash_time = millis()+flash_interval;
}
Project Diagrams and Photos



