|
Ping Pong Levitation Project |
|
|
Search
this site:
|
Introduction
We had to implement a 68HC11 based micro-controller to control the position of a ping pong ball in a tube. Our control algorithm was designed to allow the user to position the ball at any of the sensors mounted on the air tube. We also had to include a manual mode that allowed operation of the fan over 100% of its operating range.
Hardware
Our project board consisted of the following hardware components.
· Motorola 68HC11 micro-processor · Motorola 27C64 8K EEPROM · Motorola 6264 8K RAM · AMD 74HC138 · AMD 74HC00 · AMD 74HC373 TTL Latch · AMD 74HC14 TTL Inverter · Maxim RS232 Converter
We used a power MOSFET for the control of the fan. We also had numerous other support components and sockets.
Design Philosophy We adopted the example 10-51 from the HC11 reference book in our routine to set the time that PA6 (OC2) pin is high or low. This routine is also the same one as used in Lab 7.
The sensors are checked every 4.10 msec through the use of the RTI. Upon entering the interrupt service routine for the RTI the sensors are read and their position is stored in a variable. Depending on the position and the desired input position the routine will set the speed of the fan accordingly. The control of the fan is done on every interrupt given by the RTI. Upon entering the control routine a counter variable is incremented and control is only done when there is a match between the variable and the desired count. Therefore the fan speed is not updated at such a fast rate.
The mainline routine of our program polls continuously for an input on the keyboard. A ‘m’, ‘M’ or ‘a’, ‘A’ will change the mode from manual to automatic and the number keys will increase or decrease the fan speed. During this polled routine the system status is outputted to the hyperterminal one time per routine execution.
User Interface Our user interface is outputted continuously through the use of the SCI. Since our mainline routine is polled continuously and the inputs are changing continuously the up will send out the system status to the hyperterminal approximately 125 times a second.
Our user interface displays an introduction and displays current fan speed, mode of operation, current ball position and desired ball position.
Figure 1 User Interface --------------------------------------------------------- ENEL 387 FINAL PROJECT Advanced Ping Pong Levitation Exercise Written by Don Kopeck and Ahsan Upal ---------------------------------------------------------
Mode: Automatic Position: 08 Desired Position: 07 Fan Speed: 77%
Summary Our program worked well because we used an interrupt rate of 4.10 msec to check the ball position. Our control algorithm would increase or decrease the speed of the ball by 0.04% if the desired position of the sensors was different from the actual position. Using this rate of increase or decrease we sacrificed a little bit of response time in order to get good stability for the ball. The response time of the ball to get from the bottom of the tube to the top sensor was still under 40 seconds.
Appendix A – Project Code
;**************************************************************************** ;* TITLE: Advanced Ping Pong Levitation Exercise ;* ;* CLASS: ENEL 387 ;* ;* Authors: Don Kopeck ;* Ahsan Upal ;* ;**************************************************************************** SCSR .CEQU $102E ; SCI status register SCDR .CEQU $102F ; SCI data register BAUD .CEQU $102B ; BAUD rate register SCCR1 .CEQU $102C ; SCI control register #1 SCCR2 .CEQU $102D ; SCI control register #2 TCTL1 .CEQU $1020 ; timer control TFLG1 .CEQU $1023 ; timer flag TMSK1 .CEQU $1022 ; timer mask TOC2 .CEQU $1018 ; timer output capture 2 TMSK2 .CEQU $1024 ; timer mask register 2 TFLG2 .CEQU $1025 ; timer flag register 2 PORTA .CEQU $1000 ; Port A PORTE .CEQU $100A ; Port E PORTD .CEQU $1008
.ORG $E000 START: LDS #$DFFF ; set stack pointer JSR INITIALIZE_INTS JSR INITIALIZE_VARS JSR INTRO JMP GET_INPUTS
;**************************************************************************** ;* Initialize the interrupts and setup the SCI register ;**************************************************************************** INITIALIZE_INTS: LDAA #$30 ; 9600 baud STAA BAUD LDAA #$00 ; 1 start, 8 data, 1 stop STAA SCCR1 LDAA #$0C ; enable transmitter & receiver STAA SCCR2 LDAA #$00 STAA TCTL1 ; toggle oc2 on compare LDAA #$40 STAA TFLG1 ; clear oc2 flag STAA TMSK1 ; enable oc2 interrupt LDAA TMSK2 ; enable real time interrupt ORAA #$40 STAA TMSK2 LDAA #$40 ; clear OC2 interrupt STAA TFLG2
; LDAA #$7E ; STAA TOC2_PS ; LDD #TOC2_ISR ; STD TOC2_PS+1
; LDAA #$7E ; STAA RTI_PS ; LDD #ISR_RTI ; STD RTI_PS+1
RTS
;**************************************************************************** ;* Initialize variables ;**************************************************************************** INITIALIZE_VARS: CLR contrller_delay CLR fan_speed CLR fan_speed+1 LDD #7000 STD fan_speed STD high_time LDD #10000 SUBD high_time STD low_time CLR mode CLR position ; position at start(0) LDAA #8 ; automatic set point = 8 STAA set_point RTS
;**************************************************************************** ;* Display introduction screen ;**************************************************************************** INTRO: LDX #INTRO1 ; display introduction JSR OUT_STRING CLI RTS
;**************************************************************************** ;* This is the mainline of my program. It controls the manual and automatic ;* mode of the interface. In manual mode it will accept different keys that ;* will increase or decrease the fan speed. In automatic mode it will accept ;* an '8' to increase the desired level and a '2' to decrease the desired ;* level. ;**************************************************************************** GET_INPUTS: JSR SYSTEM_STATUS ; display current system status JSR GET_CHAR ; poll for a key from the user BEQ GET_INPUTS ; branch back if nothing pressed CMPB #$6D ; m pressed BEQ MANUAL CMPB #$4D ; M pressed BEQ MANUAL CMPB #$61 ; a pressed BEQ AUTO CMPB #$41 ; A pressed BEQ AUTO BNE INC_POS
TOGGLE_MODE: LDAA mode ; change the mode bit EORA #$01 STAA mode JMP GET_INPUTS ; get another key
MANUAL: LDAA mode CMPA #0 BEQ RETURN_2 JMP TOGGLE_MODE
AUTO: LDAA mode CMPA #1 BEQ RETURN_2 JMP TOGGLE_MODE
RETURN_2: JMP GET_INPUTS
INC_POS: CMPB #$38 ; '8' pressed BNE DEC_POS LDAB mode BEQ INC_FAN_SPEED ; if mode = 0, increase fan speed LDAA set_point CMPA #16 ; inc. if set point < 16 BEQ GET_INPUTS INC set_point JMP GET_INPUTS
INC_FAN_SPEED: LDD #100 JSR SET_FAN_SPEED ; increase fan speed by 10% JMP GET_INPUTS
DEC_POS: CMPB #$32 ; '2' pressed BNE INC_or_DEC ; different key pressed LDAB mode BEQ DEC_FAN_SPEED LDAA set_point BEQ GET_INPUTS DEC set_point JMP GET_INPUTS
DEC_FAN_SPEED: LDD #-100 JSR SET_FAN_SPEED JMP GET_INPUTS
INC_or_DEC: LDAA mode BNE GET_INPUTS
ONE: CMPB #$31 BNE SEVEN LDD #-500 JSR SET_FAN_SPEED JMP GET_INPUTS
SEVEN: CMPB #$37 BNE NINE LDD #500 JSR SET_FAN_SPEED JMP GET_INPUTS
NINE: CMPB #$39 BNE THREE LDD #5 JSR SET_FAN_SPEED JMP GET_INPUTS
THREE: CMPB #$33 BNE RETURN_1 LDD #-5 JSR SET_FAN_SPEED
RETURN_1: JMP GET_INPUTS
;**************************************************************** ;* ISR for the Timer Output Compare (PA6) ;* Parts were taken from the Motorola HC11 reference manual ;* page 10-51 ;* ;* Description: This routine loads the desired fan speed needed ;* and will set PORT A bit 6 depending on the high_time variable ;* which is set in the SET_SPEED routine. This routine will also ;* take a 100% duty cycle and a 0% duty cycle. This is done by ;* simply writing a '1' or a '0' to PA6. ;**************************************************************** TOC2_ISR: LDD fan_speed CPD #9900 BHS DUTY_100 CPD #100 BLS DUTY_0 LDAA PORTA ; is output high or low ANDA #$40 BEQ LOW LDD low_time ADDD TOC2 ; update the output capture register STD TOC2 ; to prepare for next transition LDAA PORTA ANDA #$BF ; clear bit 6 (PA6) STAA PORTA LDAA #$40 ; clear OC2 flag STAA TFLG1 RTI
LOW: LDD high_time ADDD TOC2 STD TOC2 LDAA PORTA ORAA #$40 ; set bit 6 (PA6) STAA PORTA LDAA #$40 ; clear OC2 flag STAA TFLG1 RTI
DUTY_100: ; 100% duty cycle LDAA PORTA ; set bit 6 (PA6) ORAA #$40 STAA PORTA LDAA #$40 STAA TFLG1 ; clear OC2 flag RTI
DUTY_0: ; 0% duty cycle LDAA PORTA ANDA #$BF ; clear bit 6 (PA6) STAA PORTA LDAA #$40 STAA TFLG1 ; clear OC2 flag RTI
;******************************************************************* ;* Interrupt service routine for RTI interrupt ;* Description: This routine will execute every 4.10ms which is ;* the default interrupt time for the RTI. It will read the sensors ;* and control the speed of the fan at a rate of approx. 150 Hz ;******************************************************************* RTI_ISR: LDAA PORTE ANDA #$FE STAA sensor_reading LDAA PORTA ANDA #$02 LSRA ORAA sensor_reading STAA sensor_reading LDX #POSITION_TABLE LDAB sensor_reading ABX LDAA $00, X STAA sensor_reading CMPA #100 BEQ ERROR ; ERROR reading sensors CMPA #$00 ; ball read by sensor BNE POSITION_OF_BALL JMP BALL_TOP_BOTTOM
ERROR: LDX #POSITION_TABLE LDAB sensor_reading ABX LDAA $00, X STAA sensor_reading CMPA #100 BEQ POSITION_OF_BALL ; return from interrupt
RETURN1: RTI
BALL_TOP_BOTTOM: LDAA position CMPA #$08 BGE BALL_TOP LDAA #$00 STAA position JMP CONTROL_FAN
BALL_TOP: LDAA #$10 STAA position JMP CONTROL_FAN
POSITION_OF_BALL: STAA position JMP CONTROL_FAN CONTROL_FAN: LDAA contrller_delay CMPA #$BF BEQ NEXT CLR contrller_delay LDAA position CMPA #16 BEQ CONTROL_DEC CMPA #00 BEQ CONTROL_INC LDAB set_point SUBB position ADDB #16 LSLB LDX #SPEED_TABLE ABX LDD $00, X JSR SET_FAN_SPEED JMP NEXT
CONTROL_DEC: LDD #0004 JSR SET_FAN_SPEED JMP NEXT
CONTROL_INC: LDD #-$0004 JSR SET_FAN_SPEED JMP NEXT
NEXT: INC contrller_delay LDAA #$40 STAA TFLG2 RTI
;************************************************************ ;* SET_FAN_SPEED: This will set the high_time and low_time ;* variables which is used by the TOC2_ISR to set the PWM ;* delay times. ;************************************************************ SET_FAN_SPEED: ADDD fan_speed BMI ZERO CPD #10000 BGT HUNDRED JMP SET_PWM
ZERO: LDD #0 JMP SET_PWM
HUNDRED: LDD #10000
SET_PWM: STD fan_speed STD high_time LDD #10000 SUBD high_time STD low_time RTS
;*************************************************** ;* SYSTEM_STATUS: Displays the current system status ;* in the form: ;* ;* Mode: ;* Position: ;* Desired Set Point: ;* Fan Speed: ;*************************************************** SYSTEM_STATUS: LDX #MODE_TEXT JSR OUT_STRING LDAA mode BEQ MANUAL_READOUT LDX #AUTO_TEXT JMP POSITION_READOUT
MANUAL_READOUT: LDX #MANUAL_TEXT
POSITION_READOUT: JSR OUT_STRING LDX #POS_TEXT JSR OUT_STRING LDAB position JSR PRINT_POSITION LDX #SET_TEXT JSR OUT_STRING LDAB mode BEQ BLANK_READOUT LDAB set_point JSR PRINT_POSITION JMP FAN_SPEED_READOUT
BLANK_READOUT: LDX #BLANK JSR OUT_STRING
FAN_SPEED_READOUT: LDX #FAN_TEXT JSR OUT_STRING LDD fan_speed LDX #100 ; divide fan_speed to get decimal % IDIV XGDX JSR PRINT_CURRENT_SPEED
LDX #CR ; print % and go back to beginning of line JSR OUT_STRING
LDAA #$1B ; returns the cursor to start position JSR OUT_CHAR LDAA #$5B JSR OUT_CHAR LDAA #$41 JSR OUT_CHAR LDAA #$1B JSR OUT_CHAR LDAA #$5B JSR OUT_CHAR LDAA #$41 JSR OUT_CHAR LDAA #$1B JSR OUT_CHAR LDAA #$5B JSR OUT_CHAR LDAA #$41 JSR OUT_CHAR LDAA #$1B JSR OUT_CHAR LDAA #$5B JSR OUT_CHAR LDAA #$41 JSR OUT_CHAR
RTS
;******************************************************** ;* OUT_STRING: Prints a string to the SCI. ;******************************************************** OUT_STRING: LDAA $00, X CMPA #$00 BEQ OUT_STRING_DONE JSR OUT_CHAR INX JMP OUT_STRING
OUT_STRING_DONE: RTS
;********************************************************* ;* OUT_CHAR: Prints a single character ;********************************************************* OUT_CHAR: LDAB SCSR ANDB #$80 ; check TDRE bit BEQ OUT_CHAR STAA SCDR RTS
;******************************************************** ;* GET_CHAR: Checks the SCI for a received character. If ;* empty, returns $00. ;******************************************************** GET_CHAR: LDAB SCSR ANDB #$20 BEQ NO_KEY LDAB SCDR RTS
NO_KEY: CLRB RTS
;********************************************************* ;* PRINT_POSITION: Prints the current position of the ball ;********************************************************* PRINT_POSITION: CMPB #10 BHS PRINT_10 TBA JMP PRINT_1
PRINT_10: LDX #10 ; divide by 10 CLRA ; clear upper 8 bits of D IDIV ; divide, quotient -> X, remainder -> D PSHB ; save the remainder from lower 8 bits of D XGDX ; put quotient in D TBA ; copy lower 8 bits of D to upper 8 bits ORAA #$30 ; convert to ASCII JSR OUT_CHAR ; output lower 8 bits of D (A) - quotient PULA ; restore remainder to A ORAA #$30 ; convert to ASCII JSR OUT_CHAR ; output the remainder RTS
PRINT_1: LDAA #$30 JSR OUT_CHAR TBA ORAA #$30 ; convert to ASCII JSR OUT_CHAR ; output the remainder RTS
;********************************************************* ;* PRINT_CURRENT_SPEED: Prints a 2 OR 3 digit number to the ;* SCI. (3 digit for the 100% case) ;********************************************************* PRINT_CURRENT_SPEED: CMPB #100 BHS PRINT_HUNDREDS CMPB #10 BHS PRINT_TENS TBA JMP PRINT_ONES
PRINT_HUNDREDS: LDX #100 CLRA IDIV PSHB XGDX TBA ORAA #$30 JSR OUT_CHAR PULA TAB
PRINT_TENS: LDX #10 ; divide by 10 CLRA ; clear upper 8 bits of D IDIV ; divide, quotient -> X, remainder -> D PSHB ; save the remainder from lower 8 bits of D XGDX ; put quotient in D TBA ; copy lower 8 bits of D to upper 8 bits ORAA #$30 ; convert to ASCII JSR OUT_CHAR ; output lower 8 bits of D (A) - quotient PULA ; restore remainder to A
PRINT_ONES: ORAA #$30 ; convert to ASCII JSR OUT_CHAR ; output the remainder RTS
;***************************************************************** ;* Tables and variable declaration section ;***************************************************************** MODE_TEXT: .db "\r\n Mode: \0" POS_TEXT: .db "\r\n Position: \0" SET_TEXT: .db "\r\n Desired Position: \0" FAN_TEXT: .db "\r\n Fan speed: \0" AUTO_TEXT: .db "AUTOMATIC \0" MANUAL_TEXT: .db "MANUAL \0" BLANK: .db "--\0" CR: .db "% \r\0"
INTRO1: .db "\r\n\r\n\r\n----------------------------------------------------------------------\r\n" .db "ENEL 387 \r\n" .db "Advanced Ping Pong Levitation Exercise\r\n" .db "Written by Don Kopeck and Ahsan Upal\r\n" .db "---------------------------------------------------------------------\r\n" .db "\r\n\r\n\0"
SPEED_TABLE: .dw -4,-4,-4,-4,-4,-4,-4,-4 .dw -4,-4,-4,-4,-3,-2,-1,0 .dw 0 .dw 0,1,2,3,4,4,4,4 .dw 4,4,4,4,4,4,4,4
POSITION_TABLE: .db 0, 1, 3, 2, 5,100, 4,100, 7,100,100,100, 6,100,100,100 .db 9,100,100,100, 100,100,100,100, 8,100,100,100, 100,100,100,100 .db 11,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 10,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 13,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 12,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 15,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 14,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100 .db 100,100,100,100, 100,100,100,100, 100,100,100,100, 100,100,100,100
.ORG $C000
mode .rs 1 ; 0=manual 1=auto position .rs 1 ; current ball position (0-16) set_point .rs 1 ; desired ball position (0-16) fan_speed .rs 2 ; fan speed high_time .rs 2 ; PA6 on time low_time .rs 2 ; PA6 off time sensor_reading .rs 1 ; sensor reading (0-15) contrller_delay .rs 1 ; delay for control routine
.ORG $FFE6 .DW TOC2_ISR
.ORG $FFF0 .DW RTI_ISR
.ORG $FFFE .DW START
.END |
Home
| Resume
| Transcript | Documents
| My
Life | Resourcess
E-Books |
Code | Greeting
Cards | Galleries | My University | IEEE
© 2002 Upal.ca All rights reserved.