Model railroad signal control

I have a 3 color (R,Y,G) over 3 color (R,Y,G) signal to control a place where there is a switch track. I am controlling what combination of colors to display simply by the states of the six analog inputs and on digital pin used as an input. The inputs will be 0V or +5V based on things like occupied blocks and turnout conditions. So, we're looking at the states of 7 inputs at any time and setting the states of 6 outputs (5V or 0V) to control six LEDs. Quick example.....all low inputs will show a green LED over a red LED.

How do I program for this? Is it a bunch of IF, THEN type loops?

Thanks, Jim

How many different combinations of the 7 inputs are there that require an output ?

jschug1:
How do I program for this? Is it a bunch of IF, THEN type loops?

Either that or some tables.

https://www.arduino.cc/reference/en/language/variables/data-types/array/

There will be 5 combinations or patterns of inputs that require unique outputs.

jschug1:
There will be 5 combinations or patterns of inputs that require unique outputs.

If there are only 5 possible input patterns then I would convert the 7 inputs into bits in a byte and use switch/case on the resulting byte value to select the row of a 2 dimensional array containing data as to the required state of the LEDs, then use a function to actually set the LEDs to the required states

Thanks. I've gotten a couple of suggestions towards the use of arrays. I'll give it a shot.

Jim

jschug1:
six analog inputs... The inputs will be 0V or +5V

Why are you using analog inputs for digital signals?

jschug1:
I have a 3 color (R,Y,G) over 3 color (R,Y,G) signal to control a place where there is a switch track. I am controlling what combination of colors to display simply by the states of the six analog inputs and on digital pin used as an input. The inputs will be 0V or +5V based on things like occupied blocks and turnout conditions. So, we're looking at the states of 7 inputs at any time and setting the states of 6 outputs (5V or 0V) to control six LEDs. Quick example.....all low inputs will show a green LED over a red LED.

How do I program for this? Is it a bunch of IF, THEN type loops?

Thanks, Jim

Do NOT start programming now.

First Step:
make a logic table on PAPER, indicating each state of the 7 inputs and the resulting states of each of the 6 LEDs.

When you have this table ready, post it to the forum and some of us will come up with a good proposal.

I have a total of 7 inputs to read that will be 5V or 0V. I have a total of 6 outputs I need for 6 LEDs. I just started at A0 and went from there. I'm open to suggestions.
Jim

const byte inputPins[] = {3, 4, 5, 6, 7, 8, 9};

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  for (int p = 0; p < 7; p++)
  {
    pinMode(inputPins[p], INPUT_PULLUP);
  }
}

void loop()
{
  byte inputCode = 0;
  for (int p = 0; p < 7; p++)
  {
    bitWrite(inputCode, p, digitalRead(p));
  }
  switch (inputCode)
  {
      //cases here for each of the 5 possible values
      //set the value of an index variable
  }
  //code here to use the value of the index variable to access the output values
  //and use them
}

The analog inputs work fine for digital signals, just use digitalRead(Ax) instead of analogRead()

(Note that A6 and A7 on the Nano are analog only.)

Excel sheeet attached. Simple example of conditions for one 3 color over 3 color signal.

Jim

So just a little more clarification......The aspects are green over red, yellow over red, red over red, and yellow over yellow.

Jim

I see only 6 input columns and one output column. Have I interpreted it correctly ?

The aspects are green over red, yellow over red, red over red, and yellow over yellow.

Sorry, but that makes no sense as there are what looks like 5 rows of possible outputs. How many individual lights are required ?

Lets go with six input columns. There may be a need for a 7th input column some time in the future. I'm sorry for any confusion the chart may bring but again, there are six LEDs, red, yellow, green over red, yellow, green. The output states will be GREEN over RED, YELLOW over RED, RED over RED, and YELLOW over YELLOW. I hope this helps.

excel was fine (even if it was somehow misleading as you are using 6 inputs and 5 Leds now).

next step is to check your logic table against your hardware.
You could use simple if statements
something like this (compiles, but missing your hardware tests)

/* Model railroad signal control
  https://forum.arduino.cc/index.php?topic=659917.0

  Prototype
  by noiasca

*/

const byte signal1rPin = 2;
const byte signal1yPin = 3;
const byte signal1gPin = 4;
const byte signal2rPin = 5;
const byte signal1y2yPin = 6;

const byte block2Pin = 8;
const byte block3Pin = 9;
const byte block4Pin = 10;
const byte switch1Pin = A0;
const byte switch4Pin = A1;
const byte switch3Pin = A2;

void doSignal()
{
  static byte previousStage = 42;
  byte newStage = 42;

  // Step 1: check for pin changes
  if ( block2Pin && !switch1Pin && !switch4Pin)
  {
    newStage = 0;
    Serial.println(F("condition ")); Serial.println(previousStage);
    digitalWrite(signal1rPin, 1);
    digitalWrite(signal1yPin, 0);
    digitalWrite(signal1gPin, 0);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1y2yPin, 0);
  }
  else if ( !block2Pin && block3Pin && !switch1Pin && !switch4Pin)
  {
    newStage = 1;
    Serial.println(F("condition ")); Serial.println(previousStage);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1yPin, 1);
    digitalWrite(signal1gPin, 0);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1y2yPin, 0);
  }
  else if ( !block2Pin && !block3Pin && !switch1Pin && !switch4Pin)
  {
    newStage = 2;
    Serial.println(F("condition ")); Serial.println(previousStage);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1yPin, 0);
    digitalWrite(signal1gPin, 1);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1y2yPin, 0);
  }
  else if ( !switch1Pin && !switch4Pin)
  {
    newStage = 3;
    Serial.println(F("condition ")); Serial.println(previousStage);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1yPin, 0);
    digitalWrite(signal1gPin, 0);
    digitalWrite(signal1rPin, 1);
    digitalWrite(signal1y2yPin, 0);
  }
  else if ( !block4Pin && switch1Pin && !switch3Pin)
  {
    newStage = 4;
    Serial.println(F("condition ")); Serial.println(previousStage);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1yPin, 0);
    digitalWrite(signal1gPin, 0);
    digitalWrite(signal1rPin, 0);
    digitalWrite(signal1y2yPin, 1);
  }
  else
  {
    newStage = 255;                  // just in case your logic table has an error, 
    Serial.println(F("unspecified "));
    Serial.println(digitalRead(block2Pin));
    Serial.println(digitalRead(block3Pin));
    Serial.println(digitalRead(block4Pin));
    Serial.println(digitalRead(switch1Pin));
    Serial.println(digitalRead(switch4Pin));
    Serial.println(digitalRead(switch3Pin));
  }

  // Step 2: change lights if something new happend
  if (newStage != previousStage)
  {
    switch (newStage)
    {
      case 0 :
        previousStage = newStage;
        Serial.println(F("condition ")); Serial.println(previousStage);
        digitalWrite(signal1rPin, 1);
        digitalWrite(signal1yPin, 0);
        digitalWrite(signal1gPin, 0);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1y2yPin, 0);
        break;
      case 1 :
        previousStage = newStage;
        Serial.println(F("condition ")); Serial.println(previousStage);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1yPin, 1);
        digitalWrite(signal1gPin, 0);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1y2yPin, 0);
        break;
      case 2 :
        previousStage = newStage;
        Serial.println(F("condition ")); Serial.println(previousStage);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1yPin, 0);
        digitalWrite(signal1gPin, 1);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1y2yPin, 0);
        break;
      case 3 :
        previousStage = newStage;
        Serial.println(F("condition ")); Serial.println(previousStage);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1yPin, 0);
        digitalWrite(signal1gPin, 0);
        digitalWrite(signal1rPin, 1);
        digitalWrite(signal1y2yPin, 0);
        break;
      case 4:
        previousStage = newStage;
        Serial.println(F("condition ")); Serial.println(previousStage);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1yPin, 0);
        digitalWrite(signal1gPin, 0);
        digitalWrite(signal1rPin, 0);
        digitalWrite(signal1y2yPin, 1);
        break;
      default:
        Serial.println(F("unspecified "));  // just in case your logic table has an error
        Serial.println(digitalRead(block2Pin));
        Serial.println(digitalRead(block3Pin));
        Serial.println(digitalRead(block4Pin));
        Serial.println(digitalRead(switch1Pin));
        Serial.println(digitalRead(switch4Pin));
        Serial.println(digitalRead(switch3Pin));
        break;
    }
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println(F("\n Signal V1"));

  pinMode(signal1rPin, INPUT);
  pinMode(signal1yPin, INPUT);
  pinMode(signal1gPin, INPUT);
  pinMode(signal1rPin, INPUT);
  pinMode(signal1y2yPin, INPUT);
  pinMode(block2Pin, OUTPUT);
  pinMode(block3Pin, OUTPUT);
  pinMode(block4Pin, OUTPUT);
  pinMode(switch1Pin, OUTPUT);
  pinMode(switch4Pin, OUTPUT);
  pinMode(switch3Pin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

  doSignal();

}

Its not optimized in any way, just a beginner-write-down as a start.

Will you need only one signal with (5) LEDs or will you need more Signals with the same logic (on other Input pins) in a later stage?

On reflection, switch/case will not work based on the result of reading the inputs because the switch value must be a constant

I will be back later with more ideas

Whatever happened to green over green?

A program to experiment with

const byte inputPins[] = {A0, A1, A2, A3};
const byte NO_OF_INPUTS = sizeof(inputPins) / sizeof(inputPins[0]);

const byte ledPins[] = {3, 5, 6, 9};
const byte NO_OF_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);

struct dataDef
{
  byte targetPattern; //pattern of required active inputs
  byte ledPattern[4];  //list of LEDs to turn on
};

dataDef patterns[] =
{
  {0b00001001, {0, 1, 99, 99}},
  {0b00001000, {1, 3, 99, 99}},
  {0b00001100, {1, 2, 99, 99}} 
};

const byte NO_OF_PATTERNS = sizeof(patterns) / sizeof(patterns[0]);

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println();
  for (int input = 0; input < NO_OF_INPUTS; input++)
  {
    pinMode(inputPins[input], INPUT_PULLUP);
  }
  for (int led = 0; led < NO_OF_LEDS; led++)
  {
    pinMode(ledPins[led], OUTPUT);
    digitalWrite(ledPins[led], HIGH); //start with all LEDs off
  }
}

void loop()
{
  byte inputs = readInputs(); //get input state
  Serial.print("input pattern : ");
  printBin(inputs);
  Serial.println();
  comparePatterns(inputs);  //check for match with required inputs
  Serial.println();
}

byte readInputs()
{
  byte result = 0;
  for (int input = 0; input < NO_OF_INPUTS; input++)
  {
    bitWrite(result, input, !digitalRead(inputPins[input]));
  }
  return result;
}

void comparePatterns(byte inputValue)
{
  for (int pattern = 0; pattern < NO_OF_PATTERNS; pattern++)  //each pattern
  {
    Serial.print("pattern # : ");
    Serial.print(pattern);
    Serial.print("\ttarget pattern : ");
    printBin(patterns[pattern].targetPattern);
    Serial.println();
    boolean matched = true;
    for (int bit = 0; bit < 8; bit++) //each bit in the pattern
    {
      byte targetBit = bitRead(patterns[pattern].targetPattern, bit);
      byte inputBit = bitRead(inputValue, bit);
      if (targetBit != inputBit)  //bits don't match
      {
        matched = false;
      }
    }
    if (matched)  //if the bits match
    {
      Serial.println("patterns match");
      ledsOff();  //all LEDs off
      ledPattern(pattern);  //turn on LEDs for the matched input pattern
    }
  }
  Serial.println();
}

void ledsOff()
{
  for (int led = 0; led < NO_OF_LEDS; led++)
  {
    digitalWrite(ledPins[led], HIGH); //turn LED off
  }
}

void ledPattern(byte pattern)
{
  for (int led = 0; led < NO_OF_LEDS; led++)  //each LED
  {
    if (patterns[pattern].ledPattern[led] != 99)  //if a valid led
    {
      byte ledIndex = patterns[pattern].ledPattern[led];  //get index to LED pin
      digitalWrite(ledPins[ledIndex], LOW); //turn LED on
    }
  }
}

void printBin(byte value) //print all 8 bits of the byte
{
  for (int bit = 7; bit >= 0; bit--)
  {
    Serial.print(bitRead(value, bit));
  }
}

NOTES
My test system has active LOW inputs and LEDs. Change the logic to suit requirements
The program uses 4 inputs and 4 LEDs as written but change the array of structs to suit
It is quite possible that I have misunderstood the requirements

I was aiming to make this much simpler but I hope that it is fairly easy to understand. It could be made shorter but I chose to use variables with meaningful names instead of calls to functions inside calls to functions in a couple of places