The trains are moved about the track by issuing commands which
the engines receive. Each train engine has an address and a set
of commands which it has built into its chip. I used a
function which Jeremy Vosters created last year. MyDCC_motor
(ID, Dir, Speed) is the command that I used to get the trains
moving. Getting the trains to move was pretty easy once I was
able to figure out the libraries and what .dll files needed to be
included. ccr.dll,
dp.lib, dcc.lib were
the .dll and .lib files I needed to include. In addition to
these, I used the MyDcc.cpp and .h files Jeremy created last
year and his ResourceManager.h. These files make interfacing with the train
possible. The first thing I did was to make a program
which simply moved the train.
Until I figured out the allocation
and the count of the photocells I didn't try to move the train
backwards. I simply needed a way of knowing what the train was
doing. Plus, if I am to allocate cells, I also need to
de-allocate them. Other wise, when I try to grab it again (on
a circular path for example), I would be unable to do so.
I used a text file as a batch. This allowed the train to
get another instruction when it accomplished it's goal. The
file has 4 fields, photocell requested, speed, direction and
instruction. So, a command of 3 4 1 0 would be translated into
request photocell 3 at speed 4 going clockwise around the
track and it's a normal command. The 0 at the end means it's
not a special command. If that number is a 2 the train should
perform a decoupling when it reaches the photocell requested.
If that number is a 3, the train should perform a coupling when
reaching the requested photocell. The direction flag, 0 is
counterclockwise, and 1 is clockwise. A sample file can be
found here.
I needed a way to know which photocells
were connected to which. I decided to use a 2 dimensional
array which would work like a linked list. The index of this
array represents the specific photocell. When a photocell is
requested, the program checks the array for the cell it currently
has and sees which photocells are Connected to the current
photocell. The
first 2 columns of the array represent possible photocells. The third
column represents turnouts that are in-between the two cells.
If the photocell requested is found in the first column then the turnout
must be turned to on. If the photocell requested is found in
the second column, then the turnout must be turned off. The
off and on of a turnout is simple a way of turning the turnout one
direction or another. The turnouts are not all set up
uniformly, I think some of them were put on backwards. This
is the reason for the data structure. The data file which
stores this track layout is found here.
The first se of data is for a clockwise direction around the
track. The second set of data is for a counter-clockwise
direction around the track.
2 -1 1
-1 2 1
7 -1 -1
1 -1 0
6 -1 -1
4 -1 -1
12 5 -1
15 -1 2
0 -1 -1
3 -1 -1
-1 1 0
6 -1 -1
-1 15 2
9 8 4
11 -1 -1
14 13 3 |
If the train just hit
photocell 15(the 16th row of data) and the batch file
requested to go to photocell 13, the program would search the
array and find that cell 15 is connected to 13 and turnout 3
needs to be turned to the off position to reach the
cell. Upon reaching cell 13, the batch requests cell
8. Again a search of the data structure find the cell 8
can be reached by turning turnout 4 off. At cell 8, cell
cell 0 is requested. Searching the data structure again
cell 0 can be gotten to by turning turnout -1 to on and so on.
-1
in the turnout column means there is no turnout between those
two cells. This is checked for in the code.
A -1 in the photocell columns means there is only one possible
cell to go to. The tracks here are converging rather
than splitting. It is still important to make sure the
turnout is turned correctly. Here is a layout
which may help visualize the setup of the track.
|
Backing up proved to be somewhat of a problem. I think I got
caught up in trying to make the train move forward properly and did
not think about the needs of switching directions. I needed to
be able to upon switching directions make the system think the train
was always going in that direction. The main problem with this
was making the count as if the train had been going in that
direction. There were two possibilities for a cell's
count. If the train was covered, the count would equal
(train's length +1)- current count. If the cell was not
covered, the count would switch to train's length - Current count.
|
|
Upon backing up the state changes to this. |
|
|
|
Upon backing up the state changes to this. |
|
When I reversed the train, rather than simply switching the
direction the motor was spinning at, I stopped the train for about a
second or so. This allowed the motor to come to a rest.
The hope here is to increases the motor's life by not causing strain
on it.
The movement of the trains is approximate. When a
command is given for the train to move at a speed of 4, the train
moves about 4. This is due to several conditions: the track's dirtiness,
the motor's dirtiness, the power on the track, and the wheel
friction on the track all change. This means that on one
section of the track a speed of 4 is a bit slower than on
another. The only problem I had with this was when I was going
to uncouple and couple the cars. This only became a problem
because I had to stop the train over a magnet in the track that is
about 2 inches long. This has to happen consistently. On
the coupling of the cars, I have to make sure that the car parks
over this magnet without the couplers being over the magnet
itself. Errors in this positioning, can cause the train to fail on
either of these tasks.