Advice on a simple train gate system

Hi, I have been trying to programme some code for this scenario but for some reason or another it still is not working, can anyone spot what is wrong with this code?

Thanks in advance.

Scenario: A control system which detects train coming, close a barrier (emulated by a motor) to stop vehicles from crossing and change the warning light of the two-way perpendicular traffic. When the train passes the gate would open and the lights would change back to indicate safe state meaning that the vehicles can pass.

Code:

// this constant won't change:
const int S1 = 1; // the pin that the switch indicating the train coming is attached to
const int S2 = 2; // the pin that the 2nd switch indicating that the train passed is attached to
const int L1 = 3; // the pin that the driver indication bulb is attached to
const int L2 = 4; // the pin that the driver 2nd indication bulb is attached to
const int M1_OPENING = 5; // the pin that the motor 1 is attached to
const int M1_CLOSING = 6; // the pin that the motor 1 is attached to
const int M2_OPENING = 7; // the pin that the motor 1 is attached to
const int M2_CLOSING = 8; // the pin that the motor 1 is attached to
const int EnA = 9;
const int EnB = 10;
// Variables will change:
int SW_TRN_COMING = 0; // current state of the button train coming
int SW_TRN_PASS = 0; // current state of the button train pass

void setup() {
// initialize the button pins as a input:
pinMode(S1, INPUT);
pinMode(S2, INPUT);
// initialize the LED & Motor pins as an output:
pinMode(L1, OUTPUT);
pinMode(L2, OUTPUT);
pinMode(M1_OPENING, OUTPUT);
pinMode(M1_CLOSING, OUTPUT);
pinMode(M2_OPENING, OUTPUT);
pinMode(M2_CLOSING, OUTPUT);
pinMode(EnA, OUTPUT);
pinMode(EnB, OUTPUT);
analogWrite(EnA, 255); //variable to control motor speed on h bridge L239D
analogWrite(EnB, 255); //variable to control motor speed on h bridge L239D
}

void loop() {
// read the pushbutton input pin:
SW_TRN_COMING = digitalRead(S1);
SW_TRN_PASS = digitalRead(S2);

//Decistion making
//SW state
// S1 = LOW & S2 = LOW => open gate
// S1 = HIGH & S2 = LOW => close gate
// S1 = LOW & S2 = HIGH => open gate
// S1 = HIGH & S2 = HIGH => close gate
if((SW_TRN_COMING == LOW && SW_TRN_PASS == LOW) || (SW_TRN_COMING == LOW && SW_TRN_PASS == LOW))
{
op();
}
else
{
cl();
}

}

// the part of the programme that turns on the warning lights and closes the gate after 7 seconds
void cl()
{
digitalWrite(L1, HIGH);
digitalWrite(L2, HIGH);
delay(7000); // L1 and L2 turn on 7 seconds before the gate closes to notify drivers
digitalWrite(M1_CLOSING, HIGH);
digitalWrite(M2_CLOSING, HIGH);
delay(500); //till the gates are closing
digitalWrite(M1_CLOSING, LOW);
digitalWrite(M2_CLOSING, LOW);
}
// the part of the programme that turns off the warning lights and opens the gate after 1 second
void op()
{
digitalWrite(M1_OPENING, HIGH);
digitalWrite(M2_OPENING, HIGH);
delay(500); //till the gates are opening
digitalWrite(M2_OPENING, LOW);
digitalWrite(M2_OPENING, LOW);
delay(1000);// L1 and L2 turn off 1 second after the gate opens to notify the drivers that the can drive
digitalWrite(L1, LOW);
digitalWrite(L2, LOW);
}

please use [code ] tags to make your work more readable. Secondly, if you explain what exactly is going wrong, we might be able to help you better.

// this constant won't change:
const int  S1 = 1;    // the pin that the switch indicating the train coming is attached to
const int  S2 = 2;    // the pin that the 2nd switch indicating that the train passed is attached to
const int  L1 = 3;    // the pin that the driver indication bulb is attached to
const int  L2 = 4;    // the pin that the driver 2nd indication bulb is attached to
const int  M1_OPENING = 5;    // the pin that the motor 1 is attached to
const int  M1_CLOSING = 6;    // the pin that the motor 1 is attached to
const int  M2_OPENING = 7;    // the pin that the motor 1 is attached to
const int  M2_CLOSING = 8;    // the pin that the motor 1 is attached to
const int  EnA = 9;
const int  EnB = 10;
// Variables will change:
int SW_TRN_COMING = 0;         // current state of the button train coming
int SW_TRN_PASS = 0;         // current state of the button train pass

void setup() {
    // initialize the button pins as a input:
    pinMode(S1, INPUT);
    pinMode(S2, INPUT);
    // initialize the LED & Motor pins as an output:
    pinMode(L1, OUTPUT);
    pinMode(L2, OUTPUT);
    pinMode(M1_OPENING, OUTPUT);
    pinMode(M1_CLOSING, OUTPUT);
    pinMode(M2_OPENING, OUTPUT);
    pinMode(M2_CLOSING, OUTPUT);
    pinMode(EnA, OUTPUT);
    pinMode(EnB, OUTPUT);
    analogWrite(EnA, 255); //variable to control motor speed on h bridge L239D
    analogWrite(EnB, 255); //variable to control motor speed on h bridge L239D
  }
 
void loop() {
  // read the pushbutton input pin:
  SW_TRN_COMING = digitalRead(S1);
  SW_TRN_PASS = digitalRead(S2);
 
  //Decistion making
  //SW state
  // S1 = LOW & S2 = LOW => open gate
  // S1 = HIGH & S2 = LOW => close gate
  // S1 = LOW & S2 = HIGH => open gate
  // S1 = HIGH & S2 = HIGH => close gate
  if((SW_TRN_COMING == LOW && SW_TRN_PASS == LOW) || (SW_TRN_COMING == LOW && SW_TRN_PASS == LOW))
  {
    op();
  }
  else
  {
    cl();
  }
 
}

// the part of the programme that turns on the warning lights and closes the gate after 7 seconds
  void cl()
  {
    digitalWrite(L1, HIGH);
    digitalWrite(L2, HIGH);
    delay(7000); // L1 and L2 turn on 7 seconds before the gate closes to notify drivers
    digitalWrite(M1_CLOSING, HIGH);
    digitalWrite(M2_CLOSING, HIGH);
    delay(500); //till the gates are closing
    digitalWrite(M1_CLOSING, LOW);
    digitalWrite(M2_CLOSING, LOW);
  }
// the part of the programme that turns off the warning lights and opens the gate after 1 second
  void op()
  {
    digitalWrite(M1_OPENING, HIGH);
    digitalWrite(M2_OPENING, HIGH);
    delay(500); //till the gates are opening
    digitalWrite(M2_OPENING, LOW);
    digitalWrite(M2_OPENING, LOW);   
    delay(1000);// L1 and L2 turn off 1 second after the gate opens to notify the drivers that the can drive
    digitalWrite(L1, LOW);
    digitalWrite(L2, LOW);
  }

A few comments:

if((SW_TRN_COMING == LOW && SW_TRN_PASS == LOW) || (SW_TRN_COMING == LOW && SW_TRN_PASS == LOW))

This is the same statement twice. My guess is the second one should be SW_TRN_PASS == HIGH. However, the way you wrote these the decision doesn't depend on SW_TRN_PASS, so you might as well leave it out.

delay(7000);

This is bad practice. It will block the processor for 7 seconds, allowing no other signals being processed for this interval. You can improve this by using a solution using millis(), please refer to the "several things at the same time" sticky post.

Also note that, as long as there is no train coming, your system will keep on trying to close the gates. There is no "no train is coming, do nothing" state.

Comments don't match the code:

  // S1 = LOW & S2 = LOW => open gate
  // S1 = HIGH & S2 = LOW => close gate
  // S1 = LOW & S2 = HIGH => open gate
  // S1 = HIGH & S2 = HIGH => close gate
  if ((SW_TRN_COMING == LOW && SW_TRN_PASS == LOW) || (SW_TRN_COMING == LOW && SW_TRN_PASS == LOW))

Looks like a copy & paste mistake.

Which L293 pins are these connected to?

const int M1_OPENING = 5; // the pin that the motor 1 is attached to
const int M1_CLOSING = 6; // the pin that the motor 1 is attached to
const int M2_OPENING = 7; // the pin that the motor 1 is attached to
const int M2_CLOSING = 8; // the pin that the motor 1 is attached to

pinMode(S1, INPUT);
pinMode(S2, INPUT);

How are the switches wired? Do you have pullup /pulldown resistors installed so the inputs are not floating HIGH / LOW when the switches are open?

If all wheels in Your train indicate You can copy a real train-road crossing. You need 3 sections, one short section covering the track distance as wide as the road plus some "meters", and 2 outher sections.
Than you can make the gates go down when the train enters the signaling first section. Then wait for the middle section to indicate. When both the first and middle sections does not indicate, raise the gates.
This works for all trains, long as well as short.

Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".
OR
http://forum.arduino.cc/index.php/topic,148850.0.html.
Then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom... :slight_smile:

Out of curiosity i wrote a test program for you, but you´ll need to modify it to get it working on your hardware..
I have no idea how the motors are working and so on, so the gate opening/closing parts are to be considered a placeholder. :slight_smile:

The lights should blink at set interval and the motors should turn themselves off after set interval.
I also incorporated the solution suggested by Railroader (neat trick btw! :slight_smile: ).

I might have rushed it somewhat, so there MAY be some programmatical errors in the code, use it at your own risk, or just view it as inspiration :slight_smile:

#define Sens1 4  // first sensor, WAY before the traincrossing
#define Sens2 5  // second sensor, nearer the traincrossing
#define Sens3 6  // third sensor, at/past the train crossing
#define Light1 7
#define Gate1_Open 8
#define Gate1_Close 9

// State 0 = gate open, State 1 = gate warning light, state 2&3&6&7 = gate closed, state 4 = gate opening
uint8_t State = 0;

bool lights = false; // if true = lights are supposed to be blinking
bool lightsBlynk = false; // keep track of ON/OFF cycle

bool gates = false; // if true = gates are supposed to be down
bool gateIsCycling = false; // to enable/disable the motor
bool gateIsDown = false; // if true = gate IS actually down.

uint32_t lastGateMotor = 0;
uint16_t gateMotorLimit = 1000;
uint32_t lastLights = 0;
uint32_t lightsBlynkInterval = 500;
uint32_t NOW = 0;


void setup() {
    pinMode(Sens1, INPUT);
    pinMode(Sens2, INPUT);
    pinMode(Sens3, INPUT);
    pinMode(Light1, OUTPUT);
    pinMode(Gate1_Open, OUTPUT);
    pinMode(Gate1_Close, OUTPUT);
    lights = false; // light off
    lightsBlynk = false; 
    gates = false; // gate open
}

bool checkElapsed(uint32_t timer,uint32_t limiter) {
    bool result = false;
    if (NOW - timer >= limiter) {
        result = true;
    }
    return result;
}

void loop() {
    NOW = millis();
    State = 0;
    if (digitalRead(Sens1)){  // if first sensor detects a train, add 1 to State
        State = State + 1;
    }
    if (digitalRead(Sens2)){  // if second sensor detects a train, add 2 to State
        State = State + 2;
    }
    if (digitalRead(Sens3)){  // if third sensor detects a train, add 4 to State
        State = State + 4;
    }
    switch (State) {
        case 0: { // state Gate open
            lights = false;; // light off
            gates = false; // gate open
        } break;
        case 1: { // state Gate open, warning lights ON
            lights = true; // light on
            gates = false; // gate open
        } break;
        case 2:
        case 3: 
        case 6:
        case 7: { // state Gate closing
            lights = true; // light on
            gates = true; // gate closed
        } break;
        case 4: { // state Gate opening
            lights = true; // light off
            gates = false; // gate open
        } break;
    }

    if (lights) { // invert lightsBlynk, warning light is blinking
        if (checkElapsed(lastLights,lightsBlynkInterval)) {
            lightsBlynk = !lightsBlynk; // invert light state
            lastLights = NOW;
        }
    }
    else { // if lights are off, turn off lightsBlynk (so they start ON)
        lightsBlynk = false;
    }
    digitalWrite(Light1,lightsBlynk);

    if (gates) {
        if (!gateIsDown) {
            closeGate(1); // enable gateMotor
        }
        else {
            closeGate(0); // disable gate motor
        }
    }
    if (!gates) {
        if (gateIsDown) {
            openGate(1); // enable gateMotor
        }
        else {
            openGate(0); // disable gate motor
        }
    }
}

void closeGate(uint8_t val) {
    switch (val) {
        case 0: { // disable gate motor
            if (checkElapsed(lastGateMotor,gateMotorLimit)) {
                digitalWrite(Gate1_Close,LOW);
                lastGateMotor = 0;
                gateIsCycling = false;
            }
        } break;
        case 1: { // enable gate motor}
            if (!gateIsCycling) {   
                digitalWrite(Gate1_Close,HIGH);
                gateIsCycling = true;
                lastGateMotor = NOW;
            }
            else {
                if (checkElapsed(lastGateMotor,gateMotorLimit)) {
                    gateIsDown = true;
                }
            }
        } break;
    }
}

void openGate(uint8_t val) {
    switch (val) {
        case 0: { // disable gate motor
            if (checkElapsed(lastGateMotor,gateMotorLimit)) {
                digitalWrite(Gate1_Open,LOW);
                lastGateMotor = 0;
                gateIsCycling = false;
            }
        } break;
        case 1: { // enable gate motor}
            if (!gateIsCycling) {
                digitalWrite(Gate1_Open,HIGH);
                gateIsCycling = true;
                lastGateMotor = NOW;
            }
            else {
                if (checkElapsed(lastGateMotor,gateMotorLimit)) {
                    gateIsDown = false;
                }
            }
        } break;
    }
}