Under the gun

Ok, so here's my sob story....

I have a 5 year old son who happens to be a train fanatic (as all young boys should be..)

I have built him a surround for his O-scale track with three signal lights and a crossing flasher. I am trying to program a Uno to control all of these functions using three IR sensors to detect the train wheels.

I am new to code (but learning). I am not one to ask for help with anything, but I am deploying for ten months in a few days (Army) and really don't want to let the little fellow down. I can either get the flasher to work, or I can get the signal to work. I can not get the loop to change gears (to put it in my terms) between the two.

For simplicity, I have wired all my signal lights together in an array that will do the job with only three functions (red, green and yellow). The crossing signal has two separate LED's that need to flash alternately.

Can I plead for some assistance in showing me the error of my ways?

I have tried some examples using "case" examples, but alas, no joy..

Here is my "code" (note the self loathing tone). I think I have reached the point of saturation and this may be complete gibberish, but here it is....

If this isn't the proper forum or method to ask for help, MODS please delete, and accept my apologies.


const int CRS1 = 10; // Crossing light Left
const int CRS2 = 9; // Crossing light Right
const int rrCrossinIn = 2; // Crossing Signal sensor
const int rrCrossing = HIGH; // HIGH MEANS NO TRAIN
const int RS1Pin = 3; //Rail Signal Sensor 1
const int RS1 = HIGH; // HIGH MEANS NO TRAIN
const int RS2Pin = 4; //Rail Signal Sensor 2
const int RS2 = HIGH; // HIGH MEANS NO TRAIN
const int RED = 11; // Signal Output 1
const int YELLOW = 12; // Signal Output 2
const int GREEN = 13; // Signal Output 3
int crossingswitch = 2; // variable for reading the switch status
int signalswitch1 = 3;
int signalswitch2 = 4;

void setup() {

pinMode(CRS1, OUTPUT);
pinMode(CRS2, OUTPUT);
pinMode(crossingswitch, INPUT);
pinMode(RS1Pin, INPUT);
pinMode(RS2Pin, INPUT);
pinMode(RED, OUTPUT);
pinMode(YELLOW, OUTPUT);
pinMode(GREEN, OUTPUT);

signalswitch1 = digitalRead(RS1Pin);
signalswitch2 = digitalRead(RS2Pin);
crossingswitch = digitalRead(rrCrossinIn);

}

void loop() {

green();
yellow();
red();
crs();
}

void green() {

if (signalswitch1 == LOW) {

digitalWrite(GREEN, HIGH);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);

}
if (signalswitch1 == HIGH) {

digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);

}
}

void yellow() {

signalswitch1 = digitalRead(RS1Pin);

if (signalswitch2 == LOW) {

digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, HIGH);
digitalWrite(RED, LOW);
delay(500);

}
if (signalswitch2 == HIGH) {

digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);

}
}

void red() {

signalswitch1 = digitalRead(RS1Pin);

if (signalswitch1 == LOW) {

digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, HIGH);

}
if (signalswitch1 == HIGH) {

digitalWrite(GREEN, LOW);
digitalWrite(YELLOW, LOW);
digitalWrite(RED, LOW);

}
}

void crs()
{

if (crossingswitch == LOW) //if the switch on:
{
digitalWrite(CRS1, HIGH); //red1 LED on
digitalWrite(CRS2, LOW); //red2 LED off
delay(400); //wait 400ms
digitalWrite(CRS1, LOW); //red1 LED off
digitalWrite(CRS2, HIGH); //red2 LED on
delay(400);
}
if (crossingswitch == HIGH) //if the switch off
{
digitalWrite(CRS1, LOW); //red1 LED on
digitalWrite(CRS2, LOW); //red2 LED off

}

}

Can you clarify how the signal switches RS1 and RS2 are used with the green, red and yellow LEDs? You don't read RS2 in the code (aside from once in setup).

Sorry, I have modified this so much that even I am not sure where I'm at...here is the scenario.
I have 3 GYR (Green yellow red) signal lights. IF the train signals the first sensor (say RS1), then green will turn on. IF RS1 and 2 are both high, then Yellow is on. IF only RS2 is high, then red. IF Crossing Switch is high, then the crossing loop kicks in.

Hope this makes sense

Edit: and thanks for the reply!

This compiles but I'm unable to test it. Give it a try:

const int CRS1 = 10;            // Crossing light Left
const int CRS2 = 9;             // Crossing light Right
const int rrCrosspin = 2;      // Crossing Signal sensor
//
const int RS1pin = 3;           // Rail Signal Sensor 1
const int RS2pin = 4;           // Rail Signal Sensor 2
const int RED = 11;             // Signal Output 1
const int YELLOW = 12;          // Signal Output 2
const int GREEN = 13;           // Signal Output 3

const byte gyrStates[4][3] =
{
    //R    Y    G
    {LOW, LOW, LOW},        //RS2:RS1 = 00
    {LOW, LOW, HIGH},       //RS2:RS1 = 01
    {HIGH, LOW, LOW},       //RS2:RS1 = 10
    {LOW, HIGH, LOW}        //RS2:RS1 = 11
    
};

void setup() 
{  
    pinMode( CRS1, OUTPUT );
    pinMode( CRS2, OUTPUT );
    pinMode( rrCrosspin, INPUT );
    //
    pinMode( RS1pin, INPUT_PULLUP );
    pinMode( RS2pin, INPUT_PULLUP );
    //
    pinMode( RED, OUTPUT );
    pinMode( YELLOW, OUTPUT );
    pinMode( GREEN, OUTPUT );

    //signalswitch1 = digitalRead( RS1Pin );
    //signalswitch2 = digitalRead( RS2Pin );
    //crossingswitch = digitalRead( rrCrossinIn );

}//setup

void loop() 
{ 
    gyr();
    crs();
    
}//loop

void gyr( void )
{
    byte
        sensors;
    sensors = 0;
    sensors |= (digitalRead(RS1pin)==HIGH)?0x01:0x00;
    sensors |= (digitalRead(RS2pin)==HIGH)?0x02:0x00;
    
    digitalWrite(GREEN, gyrStates[sensors][2]);
    digitalWrite(YELLOW, gyrStates[sensors][1]);
    digitalWrite(RED, gyrStates[sensors][0]);
    
}//gyr

void crs()
{
    static unsigned long
        timeBlink = 0;
    static bool
        bledState = false;

    if( (millis() - timeBlink) >= 400 )
    {
        timeBlink = millis();
        bledState ^= true;
         
    }//if
    
    switch( digitalRead( rrCrosspin ) )
    {
        case    LOW:
            digitalWrite( CRS1, (bledState)?HIGH:LOW );
            digitalWrite( CRS2, (bledState)?LOW:HIGH );
            
        break;

        case    HIGH:
            digitalWrite( CRS1, LOW );  //red1 LED on
            digitalWrite( CRS2, LOW );  //red2 LED off
            
        break;
        
    }//switch
    
}//crs

Thanks for your service :slight_smile:

Initial tests look promising. I'll wire the whole thing up tonight / in the morning and give it a good run.

I left at 04:00 this morning to take the little fellow on an Amtrak ride from New Orleans to Lafayette, LA, and am trying to get him to bed now..

You can never know how much I appreciate the help.

Thank You!

int crossingswitch = 2;       // variable for reading the switch status
int signalswitch1 = 3;
int signalswitch2 = 4;

Do these initial values make a lick of sense?

  signalswitch1 = digitalRead(RS1Pin);
  signalswitch2 = digitalRead(RS2Pin);
  crossingswitch = digitalRead(rrCrossinIn);

One time, it setup(), and then forget about reading the pin states again. Does THAT make sense?

pinMode(crossingswitch, INPUT);
  ...
  crossingswitch = digitalRead(rrCrossinIn);

Hmmm

I have written up some code for you (no classes today :D). I hope it is easy to understand for your level. I have not tested it but it does compile.

const int crossingLeftLight = 10; // Crossing light Left
const int crossingRightLight = 9; // Crossing light Right
const int crossingSensor = 2;  // Crossing Signal sensor
const int railSignalSensor1 = 3;  //Rail Signal Sensor 1
const int railSignalSensor2 = 4;  //Rail Signal Sensor 2
const int redLED = 11; // Signal Output 1
const int yellowLED = 12; // Signal Output 2
const int greenLED = 13; // Signal Output 3
int crossingSwitch;       // variables for reading the switch status
int signalSwitch1;
int signalSwitch2;
unsigned long crossingLightTimer; //keep track of crossing light time
unsigned long crossingLightPeriod = 400; //change this to change crossing light period

void setup() 
{
  pinMode(crossingLeftLight, OUTPUT);
  pinMode(crossingRightLight, OUTPUT);
  pinMode(crossingSensor, INPUT);
  pinMode(redLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(railSignalSensor1, INPUT);
  pinMode(railSignalSensor2, INPUT);
  crossingLightTimer = 0;
}//end setup

void loop() 
{
  readSensors();
  setRGBSignal();
  flashCrossingLights();
} //end loop

void readSensors()
{
  crossingSwitch = digitalRead(crossingSensor);
  signalSwitch1 = digitalRead(railSignalSensor1);
  signalSwitch2 = digitalRead(railSignalSensor2);
}//end readSensors

void setRGBSignal()
{
  //no signal tripped
  if(signalSwitch1 == HIGH && signalSwitch2 == HIGH)
  {
    digitalWrite(greenLED, LOW);
    digitalWrite(yellowLED, LOW);
    digitalWrite(redLED, LOW);
  }
  //signal 1 ONLY tripped
  else if(signalSwitch1 == LOW && signalSwitch2 == HIGH)
  {
    digitalWrite(greenLED, HIGH);
    digitalWrite(yellowLED, LOW);
    digitalWrite(redLED, LOW);
  }
  //both signals tripped
  else if(signalSwitch1 == LOW && signalSwitch2 == LOW)
  {
    digitalWrite(greenLED, LOW);
    digitalWrite(yellowLED, HIGH);
    digitalWrite(redLED, LOW);
  }
  //signal 2 ONLY tripped
  else if(!signalSwitch1 == HIGH && signalSwitch2 == LOW)
  {
    digitalWrite(greenLED, LOW);
    digitalWrite(yellowLED, LOW);
    digitalWrite(redLED, HIGH);
  }
}//end setRGBSignal

void flashCrossingLights()
{
  //flash crossing lights
  if(crossingSwitch == HIGH)
  {
    //if crossing light period is up change lights
    if(millis() - crossingLightTimer >= crossingLightPeriod)
    {
      //check current state of crossing lights
      //if the left light is off (this could be either if the left
      //light is off and the right light is on, or both lights are off)
      //turn the left light on and right off
      if(digitalRead(crossingLeftLight) == LOW)
      {
        digitalWrite(crossingLeftLight, HIGH);
        digitalWrite(crossingLeftLight, LOW);
      }
      //otherwise toggle to the other state
      else
      {
        digitalWrite(crossingLeftLight, LOW);
        digitalWrite(crossingLeftLight, HIGH);
      }
      //reset timer to the time at which we toggled the crossing lights
      crossingLightTimer = millis();
    }
  }
  //turn crossing lights off
  else
  {
    digitalWrite(crossingLeftLight, LOW);
    digitalWrite(crossingRightLight, LOW);
  }
}//end flashCrossingLights

Blackfin, I see you posting a lot of complete solutions for people who are struggling and I admire you for that. However, I find that a lot of the code you write is not appropriate for the level of the people you are helping out.
Looking at the code OP has written. Do you think ternary operators, 2D arrays and bitwise ORs are appropriate for someone at his level? Sure the code may work, but if OP needs to modify it they have to then go and figure out what all that stuff means. And quite frankly I think a lot of that stuff could look kinda scary to beginners.

Metallor:
Blackfin, I see you posting a lot of complete solutions for people who are struggling and I admire you for that. However, I find that a lot of the code you write is not appropriate for the level of the people you are helping out.
Looking at the code OP has written. Do you think ternary operators, 2D arrays and bitwise ORs are appropriate for someone at his level? Sure the code may work, but if OP needs to modify it they have to then go and figure out what all that stuff means. And quite frankly I think a lot of that stuff could look kinda scary to beginners.

I understand what you are saying. Thanks.

In some cases people aren't interested in learning so much as just getting something done. In this case, the OP was under time pressure to get something cool working for his little guy.

Generally speaking most of what I post is pretty straightforward. I try -- when time permits -- to comment pretty extensively (though not as much as I should...) so the recipient can understand what a section of code is doing, even they don't quite get how, say, an exclusive-OR works.

I think this approach is more productive and helpful overall than the tactics employed by some others, tactics that often involve condescension, sarcasm, berating and other needlessly abusive attitudes.

Metallor:
I find that a lot of the code you write is not appropriate for the level of the people you are helping out.

Blackfin:
Generally speaking most of what I post is pretty straightforward.

No, it's not. It's the exact opposite of that most of the time.

elvon_blunden:
No, it's not. It's the exact opposite of that most of the time.

I have no idea if that is true in general but it is certainly true for this...

bledState ^= true;

Blackfin:
I understand what you are saying. Thanks.

In some cases people aren't interested in learning so much as just getting something done. In this case, the OP was under time pressure to get something cool working for his little guy.

Let's hope it works and the little one is happy. I typically wouldn't write a full solution myself but I am super free at work and this seemed like a good cause.

Blackfin:
Generally speaking most of what I post is pretty straightforward. I try -- when time permits -- to comment pretty extensively (though not as much as I should...) so the recipient can understand what a section of code is doing, even they don't quite get how, say, an exclusive-OR works.

What seems straightforward to you may not seem that way to others. I am definitely guilty of assuming that someone knows something that seems obvious to me all too often (not just on this forum too).

Blackfin:
I think this approach is more productive and helpful overall than the tactics employed by some others, tactics that often involve condescension, sarcasm, berating and other needlessly abusive attitudes.

Everyone has their own approach. I typically try to point someone in the right direction so they have to put some effort in themselves and hopefully learn something along the way, rather than just giving them the "answer" straight off the bat. I guess some people will take an answer and study it to learn, and some will just take it and run, then come back later asking for the next solution having not learned anything. Each to their own.
Some people could probably be a bit nicer, but then again maybe they are sick of seeing simple things that could easily be found with a bit of googling, thought and effort posted over and over again and are somewhat jaded.

Sorry to derail your thread KG5KRZ, good luck with this project.

Yes, I might have been indulging in a little hyperbole when I said "most of the time" but it's certainly "much of..".

Blackfin:
I think this approach is more productive and helpful overall than the tactics employed by some others, tactics that often involve condescension, sarcasm, berating and other needlessly abusive attitudes.

While it's abundantly clear that there is lots of "condescension, sarcasm, berating and other needlessly abusive attitudes", your approach isn't actually better; it's just nicer.

Does this "needlessly abusive attitudes" mean, btw, that some level of abuse is ok?