The sensors are connected to Pins 0 through 3 on Port A. This system is set up to poll the sensors for a hit every 30 milliseconds. Once a hit is received it is recorded, but another hit cannot be recorded until the sensor reads 0, no hits, for 1.8s straight. This is necessary so that the passing train does not trigger more than one sensor hit as the breaks between train cars pass.
The motor control unit is set up to interface with the H-bridge control circuit.
Forward and Backward motion is controlled with Pin 6 on Port D. If 1 the train is in forward mode, 0 the train is in backward mode. The setting of this pin is controlled in two ways, by external push buttons attached to Pins 3 and 4 on Port B and over UART.
PortD.6 = 1 => (PortB.3 = 0) or (UART command = “f”)
PortD.6 = 0 => (PortB.4 = 0) or (UART command = “b”)
The speed of the train is controlled with the pulse width modulator (PWM) attached to timer 1. To increase or decrease the speed of the train after it has been set into forward or backward motion use the external push buttons attached to Pins 0 and 1 on Port B. The speed increases in increments of 5% for every .1 seconds that the button is held down. If the speed decrease button is held and the current speed is at 0% the train will switch from forward operation to backward, likewise if the increase button is held and the current speed is at 0% the train will switch from backward operation to forward operation. The control of the pulse width modulator relies in changing the value of the OCR1A register, which is set to interrupt on a match of the lower 10-bits to the timer 1 value. It is loaded with 1024 times the percentage currently given.
Increase OCR1A by 5% => (PortB.0 = 0 for .1s)
Decrease OCR1A by 5% => (PortB.1 = 0 for .1s)
There is also a command to stop the train, controlled by a push button on Pin 2 of Port B or over UART. This command sets both Pin 5 and Pin 6 of Port D to 0 and turns off the pulse width modulator.
PWM turned off
PortD.5 = 0 PortD.6 = 0 => (PortB.2 = 0) or (UART command = “s”)
Speed Control Optimizations
To make the train more realistic we implemented two speed control optimizations.
The first optimization is inertia. This means that when the train starts, stops, or changes direction it must slowly ramp up or down to the desired speed. The model train right out of the box can start, stop, and change directions at will, but a train in real life requires time to slow down because of weight. We decided to simulate this weight by implementing a software loop that ramps the OCR1A register up or down.
The second optimization is slowing the train on curves. Our track is an oval shape, which has straight-aways and curves. It is safe for the train to go at full speed on the straight-aways, but if it exceeds 60% speed on the curves it chances flying off the track. Therefore using the optical sensors we made it so that the train ramps down to 60% speed, if it is over 60%, for the curves and then ramps back to its initial speed when it returns to a straight-away.
Programming the Train
The final implementation decision that we made was to give the user the ability to run short programs on the train through a command in UART. A program statement has the form:
p $# $# $# $# $#
The “p” at the beginning indicates that the system is going to run a program. The program to run is specified by the $# entries. There is a maximum of 5 of these entries, but there is no minimum number for entries. The $ represents either an “f” to tell the train to go forward or a “b” to tell the train to go backward. The # is a number from 0-9 representing the number of laps to do in the specified direction. For example the sequence: p f2 b3 would make a program of 2 forward laps and 3 backward laps.
All programs are run at 100% speed, with all of the speed optimizations enabled. All pushbuttons and UART commands are disabled except for the stop command. A stop command during a program immediately ends the running program and returns to normal functionality.
The LCD output is fairly simple.
The first line of the LCD always reads “B&C’s Super Train” to indicate the title of our project.
The second line of the LCD always reads “Lap Count #”, where # is the number of times that the train has passed by the sensor connected to Pin 0 on Port A.
The third line displays the current operating status of the train, either forward, backward, or stop. Next to that is the current percentage of the velocity.
The fourth line is only used when running a program. When a program is running the fourth line reads “Program”, and next to that it reads “Lap #”. The # is the number of laps left to run for the current direction in the program.