Fun with Arduino 21 Railway Crossing UK

STD-Crossing-Gate-UKThere had been some requests to also do a UK crossing. The UK version has a couple of extra steps. First there is a yellow light, then there are two red lights and only then the red lights start blinking and then the gate closes.

We use the same 5 step approach to translate this State Transition Diagram with 2 additional states and 2 additional transitions into code.

#define GATE_SPEED   120 // [ms] lower number is higher servo speed
#define GATE_DELAY  2000 // [ms] time after double red before gate closes 
#define GATE_OPEN     60 // servo angle
#define GATE_CLOSED  135 // servo angle
#define BLINK_SPEED  400 // [ms] smaller number is faster blinking
#define YELLOW_TIME 2000 // [ms]
#define RED_TIME    1000 // [ms]
#define SERVO_PIN      3
#define LEDY_PIN       5
#define LEDR1_PIN      6
#define LEDR2_PIN      7
#define SENSOR1_PIN   10
#define SENSOR2_PIN   11

byte state = 1, transition;
byte ledr1, ledr2, blink_enabled;
byte angle    = GATE_OPEN;
byte setpoint = GATE_OPEN;
unsigned long time_to_blink;
unsigned long time_to_close_gate;
unsigned long time_for_servo;
unsigned long end_yellow_time;
unsigned long end_double_red_time;

#include <Servo.h>
Servo gate_servo;

void setup() {
  pinMode(SENSOR1_PIN, INPUT_PULLUP);
  pinMode(SENSOR2_PIN, INPUT_PULLUP);
  pinMode(LEDY_PIN, OUTPUT);
  pinMode(LEDR1_PIN, OUTPUT);
  pinMode(LEDR2_PIN, OUTPUT);
  gate_servo.attach(SERVO_PIN);
  gate_servo.write(angle);
  Serial.begin(9600);
  Serial.println("Railway Crossing Control Ready");
  Serial.println();
  Serial.println("Waiting for train");
}

void loop() {

  switch(state) {
    case 1: // idle
      if(digitalRead(SENSOR1_PIN) == LOW) transition = 12;
    break;
  
    case 2: // yellow
      if (millis() > end_yellow_time) transition = 23;
    break;
  
    case 3: // double red
      if (millis() > end_double_red_time) transition = 34;
    break;
  
    case 4: // blinking, gate still open
      if (millis() > time_to_close_gate) transition = 45;
    break;

    case 5: // blinking, gate closing
      if(digitalRead(SENSOR2_PIN) == LOW) transition = 56;

    break;

    case 6: // blinking, gate opening
      if(angle == GATE_OPEN) transition = 61;
    break;
  }

  switch(transition) {
    
    case 12: //
      Serial.println("Train detected, start yellow");
      digitalWrite(LEDY_PIN, HIGH);
      end_yellow_time = millis() + (unsigned long)YELLOW_TIME;
      transition = 0;
      state = 2;
    break;
  
    case 23: //
      Serial.println("Time to end Yellow and start Double Red");
      digitalWrite(LEDY_PIN, LOW);
      ledr1 = 1;
      ledr2 = 1;
      end_double_red_time = millis() + (unsigned long)RED_TIME;
      transition = 0;
      state = 3;
    break;
  
    case 34:
      Serial.println("Time to start Red blinking");
      blink_enabled = 1;
      time_to_close_gate = millis() + (unsigned long)GATE_DELAY;
      transition = 0;
      state = 4;
    break;
  
    case 45:
      Serial.println("Time to close the gate");
      setpoint = GATE_CLOSED;
      transition = 0;
      state = 5;
    break;

    case 56:
      Serial.println("Train detected, open the gate");
      setpoint = GATE_OPEN;
      transition = 0;
      state = 6;
    break;

    case 61:
      Serial.println("Gate fully open, stop blinking");
      Serial.println();
      Serial.println("Waiting for Train");
      blink_enabled = 0;
      ledr1 = 0;
      ledr2 = 0;      
      transition = 0;
      state = 1;
    break;  }

  if (millis() > time_for_servo) {
    time_for_servo = millis() + (unsigned long)GATE_SPEED;
    if (angle < setpoint) angle++;
    if (angle > setpoint) angle--;
    gate_servo.write(angle);
  }
    
  if(blink_enabled == 1) {
    if(millis() > time_to_blink) {
      time_to_blink = millis() + (unsigned long)BLINK_SPEED;
      ledr1 = !ledr1;
      ledr2 = !ledr1;
    }
  }
  digitalWrite(LEDR1_PIN, ledr1);
  digitalWrite(LEDR2_PIN, ledr2);
}

— 0 —

3 thoughts on “Fun with Arduino 21 Railway Crossing UK

  1. Hi Rudy

    I am a 72 years newbie on Arduino and I try to understand it but find it difficult.
    Building a level crossing and uploading a sketch is no problem.
    This sketch no 21 works nicely. thanks for that.
    I have another question: Can you also change it so that your crossing sketch an old model English railway crossing with 2 gates that turn 90 degrees to each other can move.
    Greetz Henk

    Like

Leave a comment