Station Stop Controller

revised 04-07-09

Design considerations:

The train on the main line at the Pittsburgh Children's Hospital layout starts running when a visitor presses a button.  This starts a timer that activates the train for several minutes.  The train runs in a counter clockwise direction and needs to stop at the station platform (seen in the upper left in the diagram below) at the end of each of its timed runs.

A number of circuits were considered to accomplish this task.  The final design uses a combination of relays, diodes and a microcontroller.  At the end of each trip around and around the layout these components decelerate the train as it approaches the station platform, stops it at the station and, when activated again, gradually accelerates it as it leaves the station.

The section of track that is directly in front of the train platform has one rail isolated from the rest of the layout.  That allows us to remove power from it bringing the train to a stop.

Three sections of track on either side of that section are also isolated with the cut rails joined by diodes.  Since each diode wired in series with a DC current drops the voltage a bit the train will decelerate as it nears the station and accelerate as it pulls away. 

The schematic shows the wiring in more detail.


In the schematic the lower rail is cut in 8 places.  The gaps on either side of the section labeled "isolated track" are bridged by one or more diodes.  The diodes are connected in pairs, wired back to back.  This allows the train to run in either direction.  As the train enters the first cut section the diodes drop the voltage to the track.  When it hits the second section it drops again as more diodes are added.  By the time it reaches the last section its speed has decreased significantly.

The train runs normally when the diode relay is not energized as it shorts out the diodes and the second relay applies power to the "isolated track".  When the timer signals the microcontroller that the train is to stop the microcontroller begins monitoring the reed switch.  Once the train crosses the reed switch the relay contacts close putting the diodes into the circuit and removing power from the isolated section of track.  The train slows more as it enters each diode section.  When it gets to the isolated track, where power has been completely removed, it stops. 

When the timer is started the power is first restored to the isolated track.  The train slowly enters the adjoining diode section and speeds up as it passes diodes and receives more and more power from the track.  After 12 seconds the diode relay again shorts out the diodes so that the train operates unobstructed.



'd. bodnar revised 3-12-09
'triggers relays for Station Stop
ansel = 0          'all inputs digital
cmcon0 = 7          
INCLUDE "modedefs.bas" 
ADCON0=0    'analog

Reed        VAR gpio.0       'pin 7
Serial      VAR gpio.1       'pin 6
DeadTrack   VAR gpio.2       'pin 5
'NotUsed    var gpio.3	     'pin 4
TimeUp      VAR gpio.4       'pin 3
Diodes      VAR gpio.5	     'pin 2

gpio = %00010001        '1, 4 inputs other outputs

SEROUT  Serial ,6, ["At Top ",#gpio.0," ",#gpio.4,10,13]
LOW Diodes:LOW DeadTrack

SEROUT  Serial ,6, ["@ Wait0:",10,13]
IF TimeUp=1 THEN Wait0   'Omron shows still running if TimeUp=1, =0 if done

SEROUT  Serial ,6, ["@ Wait2:",10,13]
IF Reed=1 THEN Wait2    'wait till reed switch is hit before stop area (0=hit)

HIGH Diodes
HIGH DeadTrack

SEROUT  Serial ,6, ["@ Wait3:",10,13]
IF TimeUp=0 THEN Wait3  'timer not started

LOW DeadTrack   'start train - keep diodes in line for 12 seconds
PAUSE 12000      'wait till loco clears diodes
LOW Diodes      'all normal running

GOTO Wait0


Prototype Photos


The Station Stop Controller does not include its own internal timer.  An external timer is used.  This allows us to use a variety of timers should the need arise.  The timer we are using initially is based on the BARC auto-reverse controller code.

It works as follows:

  1. On power-up the controller flashes out the set time using its 3 LEDs.  One LED represents 100s of seconds, one 10s and one 1s.  To show 125 seconds, for example, it flashes the 100s LED once, the 10s LED twice and the 1s LED five times.
  2. During this initial period the potentiometer on the timer can be adjusted to change the time.  Each time the pot is changed the new time is flashed out.  If it is allowed to flash the same time 3 times that becomes the new time setting
  3. The unit flashes all 3 LEDs while waiting to start a timing session.  Pressing the button closes the relay and starts the timing.
  4. The three LEDs continuously flash out the remaining time.  Note that every second is not reported as it takes longer than one second to flash out many time reports.
  5. When the time expires the relay opens and the 3 LEDs begin to flash again as the unit waits for another button press

'* Date : 4/13/09
' flashes out time in seconds on 3 LEDs - works well!
'1 Show time & set - range 10 seconds - 255 seconds
'2 Blink lights slowly when waiting
'3 Push button to start timing run
'4 Relay on as time remaining flashes
'5 Relay off at end
'6 repeat from step 2
' Set Debug pin port
DEFINE DEBUG_BIT 4 ' PIN 3 on 16f684
DEFINE DEBUG_MODE 1 ' Set Debug mode: 0 = true, 1 = inverted
LED0 var portc.0 'pin 10
LED1 var portc.1 'pin 9
LED2 var portc.2 'pin 8
Relay var porta.5 'pin 2 'relay to control direction pin 2
TimeAdjuster var porta.2 'pin 11 'pot to read for time delay pin 11
RNDJumper var portc.4 'pin 6 'pull low w/ jumper for random function on
'PWMpin var portc.5 'pin 5 'controls tip101 for speed control
Buttn var portc.3 'pin 7 'button to start deceleration
rndOn var byte
loop var byte
loop2 var byte
loop3 var byte
time var word
time2 var word
timeBU var word
temp var word
temp1 var word
temp2 var word
temp3 var word
temp5 var byte
TimeTemp var word
SubVar1 var word 'temp variable for subroutine
'PauseFlag var bit 'shows if in pause routine
ExitFlag var bit
loop4 var word

dd var word
laps var word
hundreds var byte
tens var byte
ones var byte
ptime var word
ptime2 var word
msFudge var word 'number to adjust timing
adcinlast var word
RNDTime var word
TIP101 con 2 'pin 5 on 14 pin PIC
SpeedCNT var word
DecelTime var word 'when to start deceleration - Button to set
DecelFlag var bit 'shows if decel has happened yet
Dlay var byte
RemainingTime var word
dlay= 140
'ptime= 100
ptime2 = 58
ansel = 0
cmcon0 = 7
trisa.2=1 'make pin input for AD conversion on pin 11
trisa.4=0 'debug an output
trisa.5=0 'make relay pin an output
trisc.0=0 'make led0 output
trisc.1=0 'make led1 output
trisc.2=0 'make led2 output
trisc.4=1 'make random jumper input
trisc.3=1 'buttn for start decel is an input
low relay 'initialize
Define ADC_BITS 8 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 500 ' Set sampling time in uS
ADCON0 = %100001000 ' Set PORTA analog and right justify result
adcin 2, temp1 :temp1=temp1+10
low relay
debug 13,10,13,10,"(C) 2009 - d. bodnar - ver 1.1",13,10,"",13,10
debug 13,10,13,10,"Timer - On / Off",13,10
adcin 2, time:time=time+10

'show time 3 times & check for pot change - after 3 identical move on
for temp=1 to 3
debug " ", dec temp," "
adcin 2, time2:time2=time2+10
debug "time2= ", dec time2, 10,13
if time2 > timebu +2 or time2 < timebu-2 then SawChange:
gosub report
next temp
goto start

debug "@ SawChange", 10,13
goto verytop:

debug "@ Start", 10,13
temp = temp + 1
if temp > 2000 then
toggle led0:toggle led1:toggle led2
temp = 0
if buttn=1 then WaitForButtonPress:
debug "BUTTON PRESSED!", 10,13
high relay
gosub report
if remainingtime>1 then remainingtime=remainingtime-1
if remainingtime=0 then AllDoneTiming
'next few lines adjust for time it takes to flash time out
if dd>1000 then
if remainingtime<>0 then
if dd> 1000 then again2:
pause 900
if remainingtime<>0 then
goto looptop:
low relay
goto Start:

gosub low3leds:
debug "at report - time = ",#subvar1, " ",#dd,10,13
if subvar1=0 or subvar1>65000 then return
ones=subvar1- (hundreds*100)-(tens*10)
if hundreds <>0 then
for loop4= 1 to hundreds
high led2:pause dlay:low led2:pause dlay:dd=dd+(ptime2*2)
next loop4
pause dlay:dd=dd+(ptime2*2)
if tens<>0 then
for loop4= 1 to tens
high led1:pause dlay:low led1:pause dlay:dd=dd+(ptime2*2)
next loop4:dd=dd+(ptime2*2)
pause dlay:dd=dd+(ptime2*2)
if ones <>0 then
for loop4= 1 to ones
high led0:pause dlay:low led0:pause dlay:dd=dd+(ptime2*2)
next loop4:dd=dd+(ptime2*2)
pause dlay:dd=dd+(ptime2*2)

low led0:low led1:low led2