super train controller

34
Super Train Controller Introduction A simple way to keep people interested in learning is to have them work with familiar systems in new and interesting ways. Our idea was to design a project that could be used as an instructional tool for student, away to learn about micro-controllers without the monotony of standard design projects. The train controller allows students to get hands on experience with programming the Atmel 90s8515, while exploring the concepts of analog design, such as isolation of power supplies using inductors and opto-couplers, motor control, sensor design, and signal control. The following sections show how we implemented the train controller. Using inexpensive and readily available parts, we designed a controller for the N-scale Bachman Highballer Chessie train set. The track is a standard Bachman e-z snap together track, and was mounted to a piece of plywood using cable ties and a staple gun. Rubber feet are placed one the bottom of the board to allow wired to be strung for ease of connection. The remaining portion of this report documents how the hardware and software was developed to control the mounted train set, provides detailed schematics and code for

Upload: fahad-sabah

Post on 04-Apr-2015

60 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Super Train Controller

Super Train Controller

Introduction

A simple way to keep people interested in learning is to have them work with familiar systems in new and interesting ways. Our idea was to design a project that could be used as an instructional tool for student, away to learn about micro-controllers without the monotony of standard design projects.  The train controller allows students to get hands on experience with programming the Atmel 90s8515, while exploring the concepts of analog design, such as isolation of power supplies using inductors and opto-couplers, motor control, sensor design, and signal control.

The following sections show how we implemented the train controller.  Using inexpensive and readily available parts, we designed a controller for the N-scale Bachman Highballer Chessie train set.  The track is a standard Bachman e-z snap together track, and was mounted to a piece of plywood using cable ties and a staple gun.  Rubber feet are placed one the bottom of the board to allow wired to be strung for ease of connection.  The remaining portion of this report documents how the hardware and software was developed to control the mounted train set, provides detailed schematics and code for the hardware, explains possible improvements for the future, and shares our concluding remarks.

HardwareSensors

Page 2: Super Train Controller

In order to detect where the train was on the track, optical sensors were placed at four points on the track.  Each of these sensors was an infra-red (IR) emitting diode and photo-transistor pair.  The sensors output a logical 0 when there was no train present and a logical 1 while the train was breaking the beam.  This was accomplished because the LED constantly emitted a beam into the optical base of the photo-transistor, so the transistor was on except while the beam was being broken.  The output of the transistor was buffered using a Burr-Brown OPA2350 op-amp, and then connected to both the port pin on the Atmel 90s8515 (PORTA[0..4}) and to 4 green LED's to allow us to visibly ensure the sensors were working properly..  Schematics showing the wiring for the LED's and photo-transistors are shown in figure 1 below.

Figure 1: Diagram of Sensors for the Train

 

Page 3: Super Train Controller

AC Motor Control

Controlling the speed of the train us the 90s8515 was accomplished through the use of an h-bridge scheme of transistors.  This indicates the AC motor is controlled by four transistors, with only two opposite ones turned on at any time.  One must be careful to not turn on two transistors on the same side, else some components may be blown due to excessive current.  The discrete logic shown in figure 2 was used in order to ensure only proper signals could be sent to the H-bridge.  The F/R control allows for one pin to control the direction of the train, 1 for forward and a 0 for reverse.  The PWM input is the output from the pulse width modulator (PWM) from the 90s8515.  This allows control of the train using only two pins.  The outputs from the logic are the inputs indicated on the H-bridge in figure 3.

Figure 2: H-Bridge Controller

In order to get an appropriate gain out of the TIP31 and TIP32 power transistors, a Darlington pair was assembled using 2n3904 and 2n3906 transistors and show in figure 3 below.  To ensure no noise could feedback from the noisy train 17V power supply, 4n35 opto-couplers were used, and the grounds were separated with an inductor (not shown) and a 50 micro-farad capacitor (not shown) was placed across the terminals of the trains power supply to reduce the noise emitted.

Page 4: Super Train Controller

Figure 3: H-Bridge

Attaching all of the parts to the 90s8515 completes the hardware design.  In figure 4, the pins for the motor control and sensors are shown.  Pushbuttons are added to manually control the train as it moves around the track. Not shown on this schematic is the UART control, which is from PORTD[0..1].  This is where the train will receive programs and instructions from the computer.  Also, the programmer for the chip is not shown.  This is a 10 pin header connected to pins on the 8515 for on-board programming. 

Page 5: Super Train Controller

Figure 4: Atmel 8515 Connections

The LCD (not shown) is connected to PORT C of the 8515, and the connections are listed in table 1:

Table 1: LCD connections

8515 Pin LCD pin Functionality

Ground 1 Ground

Vcc 2 Power

N/C 3 Contrast

PC0 4 RS

PC1 5 RD

PC2 6 Enable

PC3 11 D4

PC5 12 D5

PC6 13 D6

PC7 14 D7

Software

Page 6: Super Train Controller

Sensor Inputs

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.

Motor Control

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.

                Forward

PortD.6 = 1 =>     (PortB.3 = 0)         or                 (UART command = “f”)

Backward

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 Speed

Increase OCR1A by 5%                => (PortB.0 = 0 for .1s)

                 Decrease Speed

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.

Page 7: Super Train Controller

                 Stop

                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.

LCD Output

Page 8: Super Train Controller

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.

ResultsOnce all of the hardware was assembled and the software was programmed, the system worked well.  We had control of the train so that we could control its speed and direction, program the train so that it would do a certain number of laps forward and backward, and count the laps as the train went around.  In addition, ramping the speed of the train allowed us to make sure the train did not derail itself as it switched direction.  Also, the speed control as the train went into the curves kept the whole train on the track and did not allow for high speeds around the curves.

A few minor unfixed bugs (due to time constraints) were:

Train would not stay below 60 when passing sensors due to dynamic speed control.

Directions would get confused if changing directions on curve.

Below, are pictures of the circuitry that was actually built.

Page 9: Super Train Controller

                        Figure 5: Complete train controller brought to life with all parts labeled

Page 10: Super Train Controller

Figure 6: output on 4X20 LCD screen showing details about the train                Figure 7: H-bridge and Controller

Figure 8: Sensor power and push buttons with sensor 4 light lit                   Figure 9: Connections to the UART and programmer

Page 11: Super Train Controller

Looking AheadSome functionality had to be left out due to time restrictions.  Possible improvements include:

Use of dynamic sensor control:  We would have like to have more control over the train starting and stopping positions using all four sensors as starting and stopping points.

Better speed optimization:  A few bugs in the code cause the train to speed up to over 60%, regardless of the previous speed.  More time in debugging code would have eliminated this error.

More programming options:  When programming the train, control of the speed and more dynamic positioning so it could be stopped at any sensor.

Different track styles and shapes:  Using the micro-controller it would have been possible to control different shapes of track, such as a figure 8 or other complicated shapes.

More trains at once:  Further development in hardware would have allowed for more than one train to be running and collisions avoidance would have been interesting.

ConclusionThis project helped understanding about:

Power circuitry and isolation of power supplies and reduction of noise Sensors and converting from analog sensing to digital output Precision control of an AC motor Comparison between UART control and push button control Using an LCD to print information

Overall the project brought much personal satisfaction due to the interesting nature of the project.  It allows one to learn about a variety of topics important in today's industries that are not taught at Universities due to their practical nature. One learns many important lessons without realizing they are ding so because they are having so much fun but are kept engaged by complexity of the circuitry.

Appendix I

C-Code Listing/*Chad PotockyBallard Smith

Page 12: Super Train Controller

EE476 Spring 2001Final Project: Train Controller

This is the code for a train controller which runs a train motor that is connected to an H bridge. The train is run at different speeds using the PWM on timer 1. There are also optical sensors used to indicate the position of the train on the track for speed optimization and lap counting. Finally the output is to a 4x20 LCD panel connected to PORTC.

*/ #include <90s8515.h> #include <stdio.h> #include <string.h> //For UART comparisons #include <math.h> //Needed the abs function#include <delay.h> //Needed delay_ms for ramping

#define t1 60 

#define begin {#define end }

/* Use an 4x20 alphanumeric LCD connectedto PORTC as follows:

[LCD] [AT90S8515 DIP40]1 GND- 20 GND2 +5V- 40 VCC3 VLC 10k trimpot wiper (trimpot ends go to +5 and gnd) 4 RS - 21 PC05 RD - 22 PC16 EN - 23 PC211 D4 - 25 PC412 D5 - 26 PC513 D6 - 27 PC614 D7 - 28 PC7 */

#asm.equ __lcd_port=0x15#endasm #include <lcd.h> // LCD driver routines

//timer 1 constants #define prescale1 1 // Sets the timer 1 prescalar to 8#define t2 20 // Timeout constant for polling the push buttons

Page 13: Super Train Controller

#define t3 30 // Timeout constant for polling the sensors#define ptime 100 // Amount of time the button must be pressed before changing velocity, in ms#define senseDelay 60 // Amount of time to wait for sensor debouncing = senseDelay * t3

//the subroutinesvoid task1(void); //test for a UART command, and decode itvoid gets_int(void); //starts command from serial linevoid initialize(void); //setup the whole processvoid press(void); //check for a button pressvoid velChange(void); //change the velocityvoid checkSensor(void); //check if the train has crossed a sensorvoid runProg(void); //run a program given over UARTvoid rampup(void); //ramp the train up to speedvoid rampdown(void); //ramp the train down to 0void rampupcorner(void); //after a corner ramp back up to speed before the cornervoid rampdowncorner(void); //save speed and ramp down to 60

char lcd_buffer[17]; //Output to the LCDunsigned char last_forward; //Flag if the train was last going forwardunsigned char last_backward; //Flag if the train was last going backwardunsigned char senseDone; //Flag if sensor 0 is done sensingunsigned char senseDone1; //Flag if sensor 1 is done sensingunsigned char senseDone2; //Flag if sensor 2 is done sensingunsigned char senseDone3; //Flag if sensor 3 is done sensingunsigned char program; //Flag if a program is being rununsigned char curr_prog; //Index into prog_bufferunsigned char prog_lap; //Laps left in programunsigned char prog_buffer[16];//Buffer of commands from a UART programunsigned char doneLap; //Flag if the train has completed a lap at sensor 0unsigned char doneLap1; //Flag if the train has completed a lap at sensor 1unsigned char doneLap2; //Flag if the train has completed a lap at sensor 2unsigned char doneLap3; //Flag if the train has completed a lap at sensor 3unsigned char lapCount; //Total lap count since last resetunsigned char addin; //Flag to add or subtract from velocityunsigned char pressed; //Flag if the button is still pressedunsigned char presstime; //Counter to see how long a button was pressedint velocity; //Percentage of 1024 to place into OCR1Aint velsave; //Saved velocity when ramped down on curvesint vel; //Used in rampup functionint vel2; //Used in rampupcorner function

Page 14: Super Train Controller

unsigned char reload; //timer 0 reload to set 1 mSecunsigned char time1; //UART command decode timerunsigned char time2; //Button poll timer unsigned char time3; //Sensor poll timer //RXC ISR variables unsigned char r_busy; //recieve ISR is runningunsigned char r_index; //current string indexunsigned char r_buffer[16]; //input stringunsigned char r_ready; //flag for receive doneunsigned char r_char; //current character

//**********************************************************//timer 0 overflow ISRinterrupt [TIM0_OVF] void timer0_overflow(void)begin 

//reload to force 1 mSec overflowTCNT0=reload;

//Decrement the three times if they are not already zeroif (time1>0) --time1; if (time2>0) --time2; if (time3>0) --time3;if ((pressed == 1) && (presstime > 0)) {--presstime; }

end 

//**********************************************************//UART character-ready ISRinterrupt [UART_RXC] void uart_rec(void)beginr_char=UDR; //get a charUDR=r_char; //then print it//build the input stringif (r_char != '\r') r_buffer[r_index++]=r_char;elsebeginputchar('\n'); //use putchar to aoid overwriter_buffer[r_index]=0x00; //zero terminater_busy=0; //and clean upr_ready=1; //signal cmd processorUCR.7=0; //stop rec ISRendend

Page 15: Super Train Controller

//********************************************************** //Entry point and task scheduler loopvoid main(void)begin initialize();

//main task scheduler loop -- never exits!while(1)begin if (time1==0) task1(); //Check UART for a command if (time2==0) press(); //Check for a button pressif (time3==0) checkSensor(); //Check for a sensor hitif (senseDone == 0) doneLap = 1; //If the sensor is done, 1.8s of 0, then the next hit is a lapif (senseDone1 == 0) doneLap1 = 1; //If the sensor is done, 1.8s of 0, then the next hit is a lapif (senseDone2 == 0) doneLap2 = 1; //If the sensor is done, 1.8s of 0, then the next hit is a lapif (senseDone3 == 0) doneLap3 = 1; //If the sensor is done, 1.8s of 0, then the next hit is a lapif (presstime==0) velChange(); //If button pressed for .1s change velocityif ((program == 1) && (prog_lap == 0)) runProg(); //If running a program and the lap is 0 run the next commandif (program == 1) { //Output program info if running onelcd_gotoxy(10,3);lcd_putsf("Lap ");sprintf(lcd_buffer,"%-i",prog_lap);lcd_puts(lcd_buffer);} //Output info to LCD, name of project, lap count, and train direction with speedlcd_gotoxy(0,0);lcd_putsf("B&C's Super Train");lcd_gotoxy(0,1);lcd_putsf("Lap Count");lcd_gotoxy(10,1);sprintf(lcd_buffer,"%-i",lapCount);lcd_puts(lcd_buffer); lcd_gotoxy(10,2);lcd_putsf("V = "); if ((abs(velocity/100)) == 1) {sprintf(lcd_buffer,"%-i",abs(velocity));lcd_puts(lcd_buffer);}else if ((abs(velocity/10)) >= 1) {lcd_putsf(" ");

Page 16: Super Train Controller

sprintf(lcd_buffer,"%-i",abs(velocity));lcd_puts(lcd_buffer);}else {lcd_putsf(" ");sprintf(lcd_buffer,"%-i",abs(velocity));lcd_puts(lcd_buffer);}end end 

/*Reduces the velocity of the train to 60% before a corner*/void rampdowncorner(void){vel2 = 10.24 * 60;while (OCR1A > vel2) {OCR1A--;}} 

/*Increases the velocity of the train after a corner to thevelocity it was before the rampdowncorner*/void rampupcorner(void){vel2 = 10.24*(abs(velsave));while (OCR1A < vel2) {OCR1A--;}}

/*Slowly decreases the velocity of the train to 0,gives the train intertia*/void rampdown(void) {while (OCR1A > 0) {OCR1A--; delay_ms(1.5);}} 

/*Slowly increases the velocity of the train to the desired velocity,gives the train intertia*/

Page 17: Super Train Controller

void rampup() { vel = 10.24 * abs(velocity);while (OCR1A < vel) {OCR1A++; delay_ms(1.5);}}

/**************************************************** Run the given program*/ void runProg(void) { //program is doneif (curr_prog >= 16)program = 0; //program is done so stopelse if (prog_buffer[curr_prog] == 0) {program = 0;rampdown(); lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Stop"); lcd_gotoxy(0,3);lcd_putsf(" ");TCCR1A = 0x00; //Set PWM on and to toggle OC1A pinTCCR1B = 0x00;OCR1A = 0;velocity = 0;curr_prog = 0;last_backward = 0;last_forward = 0;//program says to go forward}else if ((char)prog_buffer[curr_prog] == 'f') {lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Forward"); if (last_backward == 1) rampdown();PORTD.6 = 1;TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03;prog_lap = prog_buffer[curr_prog + 1] - 48;velocity = 100; rampup(); OCR1A = 10.24 * abs(velocity);

Page 18: Super Train Controller

velsave = 100;rampdowncorner();velocity = 60;curr_prog = curr_prog + 3;last_backward = 0;last_forward = 1;} //program says to go backwardelse if ((char)prog_buffer[curr_prog] == 'b') {lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Backward");if (last_forward == 1) rampdown();PORTD.6 = 0;TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03;prog_lap = prog_buffer[curr_prog + 1] - 48; velocity = -100; rampup();OCR1A = 10.24 * abs(velocity);velsave = -100;rampdowncorner();velocity = -60;curr_prog = curr_prog + 3;last_backward = 1;last_forward = 0;}}

//********************************************************** //Task 1 -- detect a pusbuttonvoid task1(void) beginint i;time1=t1; //reset the task timer //PORTD.5 = PWM, PORTD.6=F/R //train is going backwardif ((program == 0) && r_ready && (strcmpf(r_buffer,"f")==0))begin lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Forward"); if (last_backward == 1) rampdown();PORTD.6 = 1;

Page 19: Super Train Controller

TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03; rampup();last_backward = 0;last_forward = 1; velocity = abs(velocity);end 

//train is going backwardif ((program == 0) && r_ready && (strcmpf(r_buffer,"b")==0)) beginlcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Backward");if (last_forward == 1) rampdown();PORTD.6 = 0;TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03; rampup();last_backward = 1;last_forward = 0; velocity = -abs(velocity);end 

//Stop the train, turn off PWMif (r_ready && (strcmpf(r_buffer,"s")==0)) beginlcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Stop"); rampdown();PORTD.6 = 0;PORTD.5 = 0; TCCR1A = 0x00;TCCR1B = 0x00;program = 0; velocity = 0; last_backward = 0;last_forward = 0;end 

//Detect a given program, set the program flags and fill the program bufferif ((program == 0) && r_ready && ((char)r_buffer[0] == 'p')) {lcd_gotoxy(0,3); 

Page 20: Super Train Controller

lcd_putsf(" ");lcd_gotoxy(0,3); lcd_putsf("Program");for (i = 0; i<=13; i++) {

prog_buffer[i] = r_buffer[i+2];}PORTD.6 = 0;PORTD.5 = 0;program = 1; prog_lap = 0; curr_prog = 0;}

//get another serial cmd if (r_ready ){gets_int(); }end 

//********************************************************** //Detect a button push on the input and set the button numbervoid press(void) {time2 = t2; if (program == 0) { if ((PINB.0 == 0) && (pressed == 0)) { //Detect button 0 press to increase velocity pressed = 1; addin = 1; presstime = ptime;}else if ((PINB.1 == 0) && (pressed == 0)) { //Detect button 1 press to decrease velocitypressed = 1;addin = 0; presstime = ptime;}else if (PINB.2 == 0){ //Detect button 2 press to stoppressed = 0;lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Stop"); rampdown();PORTD.6 = 0;PORTD.5 = 0; TCCR1A = 0x00;TCCR1B = 0x00;

Page 21: Super Train Controller

program = 0; velocity = 0; last_backward = 0;last_forward = 0;}else if (PINB.3 == 0){ //Detect button 3 press to go forwardpressed == 0;lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Forward"); if (last_backward == 1) rampdown();PORTD.6 = 1;TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03; rampup();last_backward = 0;last_forward = 1; velocity = abs(velocity); }else if (PINB.4 == 0){ //Detect button 4 press to go backwardpressed == 0;lcd_gotoxy(0,2); lcd_putsf(" ");lcd_gotoxy(0,2); lcd_putsf("Backward"); if (last_forward == 1) rampdown();PORTD.6 = 0;TCCR1A = 0x83; //Set PWM on and to toggle OC1A pinTCCR1B = 0x03; rampup();last_backward = 1;last_forward = 0; velocity = -abs(velocity); } else if ((PINB.0 == 1) && (PINB.1 == 1)) pressed = 0; //If button 0 and 1 are not pressed reset pressed flag} }/*************************************************************** Check if the sensors are being hit*/ void checkSensor(void) {time3 = t3; if ((PINA.0 == 1) && (doneLap == 1)) { //Sensor 0 being hit and counting lap lapCount++; if (program == 1) prog_lap--;if ((last_forward == 1) && (abs(velocity) > 60)) {velsave = velocity;

Page 22: Super Train Controller

rampdowncorner(); velocity = 60;}else if ((last_backward == 1) && (abs(velsave) > 60)){rampupcorner(); velocity = velsave;}doneLap = 0; senseDone = senseDelay;}else if (PINA.0 == 1) //Sensor 0 being hit within 1.8s of another sensor hitsenseDone = senseDelay;else if ((PINA.0 == 0) && (senseDone > 0)) //Sensor 0 not being hit, decrement senseTimesenseDone--;

if ((PINA.1 == 1) && (doneLap1 == 1)) { //Sensor 1 being hit and counting lapif ((last_forward == 1) && (abs(velsave) > 60)) {rampupcorner();velocity = velsave;}else if ((last_backward == 1) && (abs(velocity) > 60)){velsave = velocity;rampdowncorner(); velocity = -60;}doneLap1 = 0; senseDone1 = senseDelay;}else if (PINA.1 == 1) //Sensor 1 being hit within 1.8s of another sensor hitsenseDone1 = senseDelay;else if ((PINA.1 == 0) && (senseDone1 > 0)) //Sensor 1 not being hit, decrement senseTimesenseDone1--;

if ((PINA.2 == 1) && (doneLap2 == 1)) { //Sensor 2 being hit and counting lapif ((last_forward == 1) && (abs(velocity) > 60)){velsave = velocity;rampdowncorner(); velocity = 60;}else if ((last_backward == 1) && (abs(velsave) > 60)) {rampupcorner(); velocity = velsave;}doneLap2 = 0; senseDone2 = senseDelay;}else if (PINA.2 == 1) //Sensor 2 being hit within 1.8s of another sensor hitsenseDone2 = senseDelay;

Page 23: Super Train Controller

else if ((PINA.2 == 0) && (senseDone2 > 0)) //Sensor 2 not being hit, decrement senseTimesenseDone2--;

if ((PINA.3 == 1) && (doneLap3 == 1)) { //Sensor 3 being hit and counting lap if ((last_forward == 1) && (abs(velsave) > 60)){rampupcorner(); velocity = velsave;}else if ((last_backward == 1) && (abs(velocity) > 60)) {velsave = velocity;rampdowncorner(); velocity = -60;}doneLap3 = 0; senseDone3 = senseDelay; //Sensor 3 being hit within 1.8s of another sensor hit}else if (PINA.3 == 1)senseDone3 = senseDelay;else if ((PINA.3 == 0) && (senseDone3 > 0)) //Sensor 3 being hit and counting lapsenseDone3--;

}

//********************************************************** // Button 0 was pressedvoid velChange(void) {int temp;presstime = ptime; if ((addin == 1) && (velocity < 100))velocity = velocity + 5;else if ((addin == 0) && (velocity > -100))velocity = velocity - 5; //Increment or Decrement the set speed

lcd_gotoxy(0,2);

//If the velocity has changed positive to negative, or negative to positive//switch directions on the trainif (velocity < 0) {lcd_putsf("Backward");PORTD.6 = 0;}else{ lcd_putsf("Forward");PORTD.6 = 1;}

OCR1A = 10.24 * abs(velocity);

Page 24: Super Train Controller

//********************************************************** // -- non-blocking keyboard check initializes ISR-driven// receive. This routine merely sets up the ISR, which then//does all the work of getting a command.void gets_int(void) begin int x;for (x = 0; x<16; x++)r_buffer[x] = 0;r_busy=1; r_ready=0;r_index=0;UCR.7=1;end

//********************************************************** //Set it all upvoid initialize(void)begin //set up the portsDDRA=0xf0; // PORT A is an input for sensorsPORTA = 0xff;DDRD=0xe7; // PORT D is motor control PORTD = 0xff;DDRC=0xff; // PORT C is an ouput DDRB=0x00; //PORT B is an output for ledsPORTB = 0xff;PORTC=0; PORTB=0xf2; //all LEDs off and transistors off

//serial setup for commands. UCR = 0x18 ;UBRR = 25 ; 

//set up timer 0 //62.5 x (64x.25) microSec = 1.0 mSec, so prescale 64, and count 62 times.reload=256-62; //value for 1 Msec TCNT0=reload; //preload timer 1 so that is interrupts after 1 mSec.TCCR0=3; //prescalar to 64TIMSK=2; //turn on timer 0 overflow ISR 

//set up timer 1OCR1A = 512; //disable timer 1 until song starts velocity = 0;

Page 25: Super Train Controller

TCNT1 = 0; //and zero the timer TCCR1A = 0x00; //Turn off timer 1 until neededTCCR1B = 0x00;PORTD.5 = 0; //Turn train off PORTD.6 = 0; //Turn train offOCR1A = 0; //zero compare register

//initialize button press variables pressed = 0; presstime = ptime; 

//initialize lap count and sensor variableslapCount = 0;senseDone = 0;doneLap = 0; senseDone1 = 0;doneLap1 = 0;senseDone2 = 0;doneLap2 = 0;senseDone3 = 0;doneLap3 = 0;

//initialize program variablesprogram = 0;prog_lap = 0; curr_prog = 0;

//init the task timerstime1=t1; time2=t2; time3 = t3;

putsf("\r\nStart\r\n"); 

// initialize the LCD for 16 char widelcd_init(20); // clear itlcd_clear(); lcd_gotoxy(0,2); //Initially in the stop state.lcd_putsf("Stop");//crank up the ISRs#asmsei#endasm 

Page 26: Super Train Controller

gets_int();end

Appendix II

SchematicsFor a detailed description of what each circuit, please visit the Hardware page.

Figure 10: Top level Design showing the Atmel 90s8515 and pin connections

Figure 11: Control logic for the H-Bridge

Page 27: Super Train Controller

Figure 12: H-bridge Motor controller

Page 28: Super Train Controller

Figure 13: Optical Sensors using IR LED's and Photo-transistors