Ping Pong Levitation Project

Home
My Life
Resume
Transcript
Documents
Galleries
Code
E-Books
Resources
Greeting Cards
My University
IEEE

Pakistan Pics

 

 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
In our control algorithm we used a Pulse Width Modulation (PWM) signal to control the speed of the fan. Depending on user inputs and if in automatic or manual mode, the fan speed would be increased or decreased within its full range of operation. The full duty cycle for the fan was 10,000 cycles therefore the amount of control given was at a rate of 1 every 10 msec or 100 Hz.

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.