Clear all

Model Railroad Control Panel

3 Posts
2 Users
Joined: 3 years ago
Posts: 2
Topic starter  

I am a new member since the weekend and seek help for the control panel project I am working on.

My control panel will eventually have 12 routes, each with a button and a LED, although for training I am only concerned with 5 routes. I need to keep the buttons and LEDs on desperate "pins" and for space reasons I wish to use a Nano which leaves me short of available pins. Therefore I have tried to adapt the sketch for the tutorial on using shift registers to expand ports.

In operation the panel will be one of three identical panels placed on the three sides of my junction module for ease of access. The three panels will be interconnected with LocoNet and also to a Tam Valley device to drive servos for the turnouts. When a button is pressed I want to message to the other panels and to the TV equipment that a button has been pushed for a specific route. For this training exercise I am only interested in making one panel work, ignoring the messaging to and from other devices.

When a button is pushed I got so far that the correct LED will light for each of the 5 route buttons in the test. The shortcoming is that there are situations on some routes where more than one LED may be lighted. I'm not sure that is clear but think of having route A, B, and C as main routes and D and E as sidings. In one case, A is selected then B, C, and E must be dark but E could be lighted or not depending on previous selections.

Here is the sketch so far:

74HC595 & 74HC165 Shift Register Demonstration 2
Input from 8 pushbuttons using 74HC165
Output to 8 LEDs using 74HC595

Select LED pattern using pushbuttons

DroneBot Workshop 2020
// Define Connections to 74HC165

// PL pin 1
int load = 7;
// CE pin 15
int clockEnablePin = 4;
// Q7 pin 7
int dataIn = 5;
// CP pin 2
int clockIn = 6;

// Define Connections to 74HC595

// ST_CP pin 12
const int latchPin = 10;
// SH_CP pin 11
const int clockPin = 11;
// DS pin 14
const int dataPin = 12;

// Define data array
int datArray[8];

// Define Route Data

byte lastincoming = B11111111;
byte currentdisp = 00000000;
void setup () {

// Setup Serial Monitor

// 74HC165 pins
pinMode(load, OUTPUT);
pinMode(clockEnablePin, OUTPUT);
pinMode(clockIn, OUTPUT);
pinMode(dataIn, INPUT);

// 74HC595 pins
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);



void loop() {

// Read Switches

// Write pulse to load pin
digitalWrite(load, LOW);
digitalWrite(load, HIGH);

// Get data from 74HC165
digitalWrite(clockIn, HIGH);
digitalWrite(clockEnablePin, LOW);
byte incoming = shiftIn(dataIn, clockIn, LSBFIRST);
digitalWrite(clockEnablePin, HIGH);

// Print to serial monitor
Serial.print("Pin States:\r\n");
Serial.println(incoming, BIN);

// Wait for button push

if (incoming != lastincoming) { // Part of device to allow operation only
// if a new button has been pushed
// Setup array for LED pattern

switch (incoming) {

case B11110111:

datArray[0] = B00001000; //Route50


case B11101111:

datArray[0] = B00010000; //Route49


case B11011111:

datArray[0] = B00100000; //Route48


case B10111111:

datArray[0] = B01000000; //Route467


case B01111111: // Read in from 165, the push button register

// byte route46[8];
// route46 = B10022222;
// int currstate[] = lastincoming;
// for (int rs = 0;rs <7;rs ++){
// if (route46[rs] = 1) currstate[rs] = 1;
// if (route46[rs] = 0) currstate[rs] = 0;
// }
datArray[0] = B10000000; //Route46





// Write to LEDs

// Count from 0 to 7
for (int num = 0; num < 8; num++)
// ST_CP LOW to keep LEDs from changing while reading serial data
digitalWrite(latchPin, LOW);

// Shift out the bits
shiftOut(dataPin, clockPin, LSBFIRST, datArray[num]); // Changed from MSBFIRST to allign
// with LED layout on test board.
// Copy route data into holding reg to represent current lighted leds
currentdisp = datArray[num];

// ST_CP HIGH change LEDs
digitalWrite(latchPin, HIGH);

delay(2); // Reduced from 200 to eliminate flashing of LEDsS

lastincoming = incoming; // Used to check that a button has been pushed


This works for the simple case but not for the case where other routes may also be active.

May have suggestions please? As you can see I tried to take lastincoming which eventually would show all the active/inactive routes and manipulate it in the case statement for route 64 and failed miserably.


Joined: 5 years ago
Posts: 2035

Joined: 3 years ago
Posts: 2
Topic starter  


Thanks for cleaning that up! What is a sticky note?