Go Down

Topic: Model Railway signal lights (Read 171 times) previous topic - next topic

John40131

Hi I am using this sketch to control up to 6 sets of signal lights on a model Railway and as my program skills are almost none, but I used this sketch i found on another forum and extendedto use 6 pushbuttons to control 6 sections, what I would like to happen is in each void loops is to add an IR sensor so the light will stay on Green till the sensor is triggered were at the moment it is just a 5 second delay so after the Green LED lights it will go back to RED, how can I put a wait command without stopping the Arduino so the other pushbuttons will still function..the signal is a RED YELLOW GREEN plus 2 sets of WHITE lights for direction LEFT or RIGHT...

Also as I am a relative novice with Arduino sketches and I am sure there is another way for this sketch but it works for me.

I would be very grateful for any help.

Regards John

lesept

You should consider writing your code as a kinf of state machine. For each traffic light and IR sensor pair, you use a state variable (for example a boolean variable) reading true or false depending on if the IR beam is visible or cut. Then depending on the value of each state variable, you set the light's color as it must be.

Be careful that a train crossing such an IR beam may provide random state during the time it passes (because of possible holes in the train or wagons through which light can pass), so maybe you'll have to wait one or two seconds of steady visible beam to change your state variable.

But this may come later on.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

John40131

Hi,
The problem is I would realy struggle to write a code in that manner without some practical help and i have not really got the time, I am 71 and brain power is at a premium, so thats why I get help from other peoples sketches,

Regarding the Arduino IR detector thay have been used a lot normally under the base board over the track 2 holes and when a train passes it activates.or a bit of silver foil under a loco or carraige.

Regards John

Robin2

#3
Sep 19, 2019, 05:51 pm Last Edit: Sep 19, 2019, 05:52 pm by Robin2
The problem is I would realy struggle to write a code in that manner without some practical help and i have not really got the time, I am 71 and brain power is at a premium, so thats why I get help from other peoples sketches,
I am only a few years behind you and I reckon my brain power is still sufficient for programming :)

However if you just just want someone to write a program for you please ask in the Gigs and Collaborations section of the Forum and be prepared to pay.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

UKHeliBob

Not a solution to your problem but here is a sketch that may give you some ideas of how to do timing without blocking execution of other code
Code: [Select]

const byte ledPins[] = {3, 5, 6};
const byte buttonPins[] = {A3, A2, A1};
const byte NUMBER_OF_BUTTONS = sizeof(buttonPins) / sizeof(buttonPins[0]);
byte currentButtonStates[] = {HIGH, HIGH, HIGH};
byte previousButtonStates[] = {HIGH, HIGH, HIGH};
byte ledStates[] = {HIGH, HIGH, HIGH};
unsigned long stateChangeTimes[] = {0, 0, 0};
unsigned long currentTime;
unsigned long onPeriod = 5000;

void setup()
{
  Serial.begin(115200);
  for (int b = 0; b < NUMBER_OF_BUTTONS; b++)
  {
    pinMode(buttonPins[b], INPUT_PULLUP);
    pinMode(ledPins[b], OUTPUT);
    digitalWrite(ledPins[b], ledStates[b]);
  }
}

void loop()
{
  currentTime = millis();
  for (int b = 0; b < NUMBER_OF_BUTTONS; b++)
  {
    currentButtonStates[b] = digitalRead(buttonPins[b]);
    if (currentButtonStates[b] != previousButtonStates[b])  //state changed
    {
      if (currentButtonStates[b] == LOW)  //button has become pressed
      {
        ledStates[b] = LOW;
        digitalWrite(ledPins[b], ledStates[b]);
        stateChangeTimes[b] = currentTime;
      }
    }
    else if (currentTime - stateChangeTimes[b] >= onPeriod)
    {
      ledStates[b] = HIGH;
      digitalWrite(ledPins[b], ledStates[b]);
    }
  }
}

It reads 3 inputs and turns on a corresponding LED when an input goes LOW.  The LED stays on for 5 seconds without interfering with reading inputs or the timing for other LEDs

It could easily be extended to control 6 sets of LEDs, which you might like to try as it would, I believe, then replicate your current program.  It would also be possible to control the turning on/off of LED pairs using external sensors rather than pushbutton inputs

As Robin has indicated, if you want the full program written for you then this thread would be better placed in the Gigs and Collaborations section of the forum.  I am afraid that I will not be able to give you further help due to other commitments but good luck with your project.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

wildbill

As already noted, each of your signal control functions needs to be a little state machine and as a part of that, all the delays have to go. Not too tricky to do for someone familiar with the concept.

But before that, I suggest that you get the IR sensor wired up and being read by your sketch. Obviously, one would be enough to prove the concept but there's little point rebuilding your sketch until you have that one working.

John40131

Hi,
Thanks for Help but I dont have funds to pay being on state pension and that pays bills, but I have looked around and I think Robojax videos may help me more than this forum.

John

Robin2

#7
Sep 19, 2019, 08:39 pm Last Edit: Sep 19, 2019, 08:41 pm by Robin2
I think Robojax videos may help me more than this forum.
There are lots of online Arduino video Tutorials and they fulfil a complementary role alongside this Forum. I have not used any so I can't advise about which is best.

The author of this series of Turtorials (in the Introductory Tutorials section of this Forum) also posts on the RMWeb Forum.

After learning from the Tutorials if you run into problems with your own program we will try to help if you post it here and describe the problem.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

lesept

I am only a few years behind you and I reckon my brain power is still sufficient for programming :)
...R
Good to know for us, followers... :)
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

John40131

Thank you very much for the Sketch I will try that, and it great to know some people will take the time to help as I cannot get my head around code, I did alot dbase in the 1980s but thats all gone, but the basic millis sketch from a youtube may help just a mater of working out what I want it to do in my existing sketch and also having the IR Avoidance sensor which goes low when triggered as my trigger to send signal back to RED.... I will get there... Thanks

John

John40131

Robin2

I presume you have ben programming for quite some time, well I havnt and the number of times I have needed is not very many, so unless you keep up with programming you forget or at least i do my expertise are in Electronics and 3D printing and CNC and Solidworks designs not Arduino programs...

John

wildbill

Here's your code adapted to use a state machine for one platform:
Code: [Select]

//Bolton Trinty Street Station signal lights
//By John Marshall

const int upplatform3RedLed = 7;  //This set are Platform 3 direction signals for Preston or Blackburn
const int upplatform3YellowLed = 8;
const int upplatform3GreenLed = 9;
const int upplatform3WhiteLed1 = 10; //Centre LED
const int upplatform3WhiteLed2 = 11; //Left LED
const int upplatform3WhiteLed3 = 12; //Right LED

const int upmainRedLed = 13;  //This set are Up Main direction signals for Preston or Blackburn
const int upmainYellowLed = 14;
const int upmainGreenLed = 15;
const int upmainWhiteLed1 = 16; //As above LEDs
const int upmainWhiteLed2 = 17;
const int upmainWhiteLed3 = 18;

const int downmainRedLed = 19;  //This set are Down main direction signals for Manchester
const int downmainYellowLed = 20;
const int downmainGreenLed = 21;
const int downmainWhiteLed1 = 0; //not used
const int downmainWhiteLed2 = 0; //not used
const int downmainWhiteLed3 = 0; //not used

const int downplatform1or2RedLed = 22;  //This set are Platform 1 or 2 direction signals for Manchester
const int downplatform1or2YellowLed = 23;
const int downplatform1or2GreenLed = 24;
const int downplatform1or2WhiteLed1 = 25;
const int downplatform1or2WhiteLed2 = 26;
const int downplatform1or2WhiteLed3 = 27;

const int upplatform1or2RedLed = 28;  //This set are Platform 1 direction signals for Preston or Blackburn
const int upplatform1or2YellowLed = 29; //But maybe never went in this direction ???
const int upplatform1or2GreenLed = 30;
const int upplatform1or2WhiteLed1 = 31;
const int upplatform1or2WhiteLed2 = 32;
const int upplatform1or2WhiteLed3 = 33;

const int mainLedDelay = 5000;

const int pushButton1 = 2;
const int pushButton2 = 3;
const int pushButton3 = 4;
const int pushButton4 = 5;
const int pushButton5 = 6;
const int pushButton6 = 40;
const int pushButton7 = 41;
const int pushButton8 = 42;

int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;
int buttonState7 = 0;
int buttonState8 = 0;

const byte IRSensorPin = 43;

enum States {START,RED,YELLOW,GREEN};

void setup()
{
  pinMode (upplatform3RedLed, OUTPUT);  //All void setup for Platform 3 Preston or Blackburn
  pinMode (upplatform3YellowLed, OUTPUT);
  pinMode (upplatform3GreenLed, OUTPUT);
  pinMode (upplatform3WhiteLed1, OUTPUT);
  pinMode (upplatform3WhiteLed2, OUTPUT);
  pinMode (upplatform3WhiteLed3, OUTPUT);
  pinMode (upmainRedLed, OUTPUT);  //All Void Setup for Up Main for Preston or Blackburn
  pinMode (upmainYellowLed, OUTPUT);
  pinMode (upmainGreenLed, OUTPUT);
  pinMode (upmainWhiteLed1, OUTPUT);
  pinMode (upmainWhiteLed2, OUTPUT);
  pinMode (upmainWhiteLed3, OUTPUT);
  pinMode (downmainRedLed, OUTPUT);  //All Void Setup for Down Main to Manchester
  pinMode (downmainYellowLed, OUTPUT);
  pinMode (downmainGreenLed, OUTPUT);
  pinMode (downmainWhiteLed1, OUTPUT);
  pinMode (downmainWhiteLed2, OUTPUT);
  pinMode (downmainWhiteLed3, OUTPUT);
  pinMode (downplatform1or2RedLed, OUTPUT);  //All Void Setup for Down Platform 1 or 2 to Manchester
  pinMode (downplatform1or2YellowLed, OUTPUT);
  pinMode (downplatform1or2GreenLed, OUTPUT);
  pinMode (downplatform1or2WhiteLed1, OUTPUT);
  pinMode (downplatform1or2WhiteLed2, OUTPUT);
  pinMode (downplatform1or2WhiteLed3, OUTPUT);
  pinMode (upplatform1or2RedLed, OUTPUT);  //All Void Setup for Down Platform 1to Manchester
  pinMode (upplatform1or2YellowLed, OUTPUT);  // But maybe never used
  pinMode (upplatform1or2GreenLed, OUTPUT);
  pinMode (upplatform1or2WhiteLed1, OUTPUT);
  pinMode (upplatform1or2WhiteLed2, OUTPUT);
  pinMode (upplatform1or2WhiteLed3, OUTPUT);
  pinMode(pushButton1, INPUT);
  pinMode(pushButton2, INPUT);
  pinMode(pushButton3, INPUT);
  pinMode(pushButton4, INPUT);
  pinMode(pushButton5, INPUT);
  pinMode(pushButton6, INPUT);
  pinMode(pushButton7, INPUT);
  pinMode(pushButton8, INPUT);
  digitalWrite(upplatform3RedLed, HIGH);  //All void setup outputs for Platform 3 Preston or Blackburn
  digitalWrite(upplatform3YellowLed, LOW);
  digitalWrite(upplatform3GreenLed, LOW);
  digitalWrite(upplatform3WhiteLed1, LOW);
  digitalWrite(upplatform3WhiteLed2, LOW);
  digitalWrite(upplatform3WhiteLed3, LOW);
  digitalWrite(upmainRedLed, HIGH);  //All Void Setup outputs for Up Main for Preston or Blackburn
  digitalWrite(upmainYellowLed, LOW);
  digitalWrite(upmainGreenLed, LOW);
  digitalWrite(upmainWhiteLed1, LOW);
  digitalWrite(upmainWhiteLed2, LOW);
  digitalWrite(upmainWhiteLed3, LOW);
  digitalWrite(downmainRedLed, HIGH);  //This set are Down main direction signals for Manchester
  digitalWrite(downmainYellowLed, LOW);
  digitalWrite(downmainGreenLed, LOW);
  digitalWrite(downplatform1or2RedLed, HIGH);  //This set are Platform 1 or 2 direction signals for Manchester
  digitalWrite(downplatform1or2YellowLed, LOW);
  digitalWrite(downplatform1or2GreenLed, LOW);
  digitalWrite(downplatform1or2WhiteLed1, LOW);
  digitalWrite(downplatform1or2WhiteLed2, LOW);
  digitalWrite(downplatform1or2WhiteLed3, LOW);
}

void loop()
{
routeUpplatform1();  // All Trains Up Via Platform 1 to Blackburn or Preston ( But not used at moment)
}


void routeUpplatform1()    // All Trains Up Via Platform 1 to Blackburn or Preston ( But not used at moment)
{
  static States state=START;
  static unsigned long LastEventTime;
  switch (state)
  {
  case START:
    SetRedForUpPlatform1();
    state=RED;
    break;
  case RED:
    if(digitalRead(pushButton5)==HIGH)
      {
      digitalWrite(upplatform3RedLed, LOW);
      digitalWrite(upplatform3YellowLed, HIGH);
      digitalWrite(upplatform3GreenLed, LOW);
      digitalWrite(upplatform3WhiteLed1, HIGH);
      digitalWrite(upplatform3WhiteLed2, HIGH);
      digitalWrite(upplatform3WhiteLed3, LOW);
      LastEventTime=millis();
      state=YELLOW; 
      }
    break;
  case YELLOW:
    if(millis()-LastEventTime > mainLedDelay)
      {
      digitalWrite(upplatform3RedLed, LOW);
      digitalWrite(upplatform3YellowLed, LOW);
      digitalWrite(upplatform3GreenLed, HIGH);
      digitalWrite(upplatform3WhiteLed1, HIGH);
      digitalWrite(upplatform3WhiteLed2, LOW);
      digitalWrite(upplatform3WhiteLed3, HIGH);
      state=GREEN; 
      }
    break;
  case GREEN:
    if(digitalRead(IRSensorPin)==HIGH)
      {
      SetRedForUpPlatform1();
      state=RED; 
      }
    break;
  }
}

void SetRedForUpPlatform1()
{
digitalWrite(upplatform3RedLed, HIGH);
digitalWrite(upplatform3YellowLed, LOW);
digitalWrite(upplatform3GreenLed, LOW);
digitalWrite(upplatform3WhiteLed1, LOW);
digitalWrite(upplatform3WhiteLed2, LOW);
digitalWrite(upplatform3WhiteLed3, LOW); 
}

Compiled, Not tested.

Obviously, you would need to replicate these two functions for each platform. It's not as elegant as UKHeliBob's example, but you may find it easier just to copy and paste and fix up the details of the pins for that platform.

It wouldn't really matter, but I dislike having the state code set leds to the same thing every time, so the leds only get set when transitioning out of a state. That created the need for the start state to allow the initial setting of red and the associated leds.

Robin2

#12
Sep 20, 2019, 05:56 pm Last Edit: Sep 20, 2019, 06:00 pm by Robin2
unless you keep up with programming you forget or at least i do
That's the difference between capability and current-knowledge. I had interpreted your Reply #2 to mean that you did not think you had the capability - but clearly you do. I don't like it when folk undermine their capabilities :)

It is perfectly reasonable to decide that you either don't have time or don't have sufficient interest to gain programming knowledge. For example I know nothing about Solidworks and have no plans to learn it.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up