Code:
'****************************************************************
'* Name : Joystick-StepDir.BAS *
'* Author : Mark A.Rokus *
'* Notice : Copyright (c) 2010 Controlled Surroundings Inc. *
'* : All Rights Reserved *
'* Date : 10/31/2010 *
'* Version : 1.0 *
'* Notes : *
'* Needs : Button routine and decel near limits *
'****************************************************************
' Read joystick and buttons and control Step/Direction drives.
' On power up, Beep and drive HOME, check centering of X & Y pots before
' enabling output. After ok, double beep, measure deflection, determine
' direction, and increase pulses.
' Z (trim) analog input modifies the timer preload to control speed
'*********************************************************************
' PC Joystick port. DB15
' 1: 5v
' 2: B1
' 3: X1 (0-100k)
' 4: GndB1
' 5: GndB2
' 6: Y1 (0-100k)
' 7: B2
' 8: 5v
' 9: 5v
' 10: B4
' 11: X2 (0-100k)
' 12: Gnd
' 13: Y2 (0-100k)
' 14: B3
' 15: 5v
' 18F4331/18F4431
' -------------------u------------------
' Vpp -1 |MCLR/vpp/RE3 RB7/KBI3/PGD|40- PGD
' X1 -2 |RA0/AN0 RB6/KBI2/PGC|39- PGC
' Y1 -3 |RA1/AN1 RB5/KBI1/PWM4/PGM|38- Man Enc B in
' Y2 -4 |RA2/AN2/Vr-/CAP1/Indx RB4/KBI0/PWM5|37- Man Enc A in
' Trav EncA in -5 |RA3/AN3/Vr+/CAP2/QEA RB3/PWM3|36- S4 Thumb
' Trav EncB in -6 |RA4/AN4/CAP3/QEB RB2/PWM2|35- S3 Down
' Beeper -7 |RA5/AN5/LVDIN RB1/PWM1|34- S2 Up
' Cut -8 |RE0/AN6 RB0/PWM0|33- S1 Trigger
' Pack -9 |RE1/AN7 Vdd+|32 +
' Stroke -10|RE2/AN8 Vss-|31- -
' + -11|AVdd RD7/PWM7 |30- Adir
' - -12|AVss RD6/PWM6 |29- Astep
' -13|OSC1/CLK1/RA7 RD5/PWM4 |28- Zdir
' -14|OSC2/CLK0/RA6 RD4/FLTA3 |27- Zstep
' Xlim+ -15|RC0/T1OSO/T1CKI RC7/RX/DT/SDO|26- RX
' Xlim- -16|RC1/T1OSI/CCP2/FLTA RC6/TX/CK/SS|25- TX
' Ylim+ -17|RC2/CCP1/FLTB RC5/INT2/SCK/SCL|24- Zlim-
' Ylim- -18|RC3/T0CKI/T5CKI/Int0 RC4/INT1/SDI/SDA|23- Zlim+
' Xstep -19|RD0/T0CKI/T5CKI RD3/SCK/SCL|22- Ydir
' Xdir -20|RD1/SDO RD2/SDI/SDA|21- Ystep
' |_____________________________________|
DEFINE OSC 40
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 173 ' 57600 Baud @ 40MHz, -0.22%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
clear
beeper var PORTA.5
SwTrig var PORTB.0
SwUp var PORTB.1
SwDwn var PORTB.2
SwTmb var PORTB.3
XlimFar var PORTC.0
XlimNear var PORTC.1
YlimFar var PORTC.2
YlimNear var PORTC.3
ZlimFar var PORTC.4
ZlimNear var PORTC.5
Xs_out var PORTD.0 ' Step PULSE output to motor, Active LOW
Xd_out var PORTD.1 ' LEVEL output for direction
Ys_out var PORTD.2 ' Step PULSE output to motor, Active LOW
Yd_out var PORTD.3 ' LEVEL output for direction
Zs_out var PORTD.4 ' LEVEL output for direction
Zd_out var PORTD.5 ' Step PULSE output to motor, Active LOW
Ad_out var PORTD.6 ' LEVEL output for direction
As_out var PORTD.7 ' Step PULSE output to motor, Active LOW
Cut VAR PORTE.0
Pack var PORTE.1
Stroke var PORTE.2
Dir VAR byte ' Direction
Xdir var Dir.0
Ydir var dir.1
Zdir var Dir.2
Adir var Dir.3
Xch VAR WORD 'channels for A/D
Ych VAR WORD
Zch VAR WORD
Ach VAR WORD
Xspd var word
Yspd var word
IntCnt var word[2]
Holdoff var word[2]
Xpos var word ' counter for X position
Ypos var word ' counter for Y position
INCLUDE "DT_INTS-18.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts
'OPTION_REG = %00000000 ' Pull-up Enabled
T0CON = %10001000 ' no PS, PL65535 = .8uS, PL0 = 6.55mS
TRISA = %00011111
TRISB = $FF
TRISC = %10111111
TRISD = %00000000
TRISE = %00000000
PORTD = $00 ' start out HI. Moves on LOW pulse
'**** Analog setup ****
' Single shot, multi-channel, simultaneous Mode2, Groups A+B, then C+D
ADCON0 = %00011101
ADCON1 = %00010000 ' Set +/- Vref to AVdd/AVss, FIFO buffer enabled
ADCON2 = %11111111 ' Right justified, 64 Tad, Frc
ADCON3 = 0 ' Disable all triggers
ADCHS = %11000000 ' Channel select for AN0,1,2
ANSEL0 = %00000111 ' AN0,1,2 analog input, rest digital
'*********
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, _PulseCk, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
goto Start
'============= SUBS ================================
'******** SUB: Get A/D readings *************************
GetAD:
ADCON0.1 = 1 ' Start conversion (Bruce t=6768)
WHILE ADCON0.1=1 ' Wait for it to complete (all 3channels)
WEND
Xch.HighByte = ADRESH ' get result from AN0
Xch.LowByte = ADRESL ' Increment buffer pointer
Ych.HighByte = ADRESH ' get result from AN1
Ych.LowByte = ADRESL ' Increment buffer pointer
Zch.HighByte = ADRESH ' get result fron AN2
Zch.LowByte = ADRESL ' Increment buffer pointer
Return
'******* SUB: Direction / Speed Check ***********************************
DirChk: 'get direction
if Xch > 513 then ' Above center
Xdir = 1
if Xch < 529 then ' below NULL,
Xspd = 0 ' No output
else
Xspd = Xch - 528 ' 528 TO 1028 - 528 = 0 TO 500
endif
endif
if Xch < 514 then
Xdir = 0
if Xch > 499 then
Xspd = 0
else
Xspd = 500 - Xch ' 500 - 499 TO 0 = 0 TO 500
endif
endif
if Ych > 513 then
Ydir = 1
if Ych < 529 then
Yspd = 0
else
Yspd = Ych - 528 ' 528 TO 1028 - 528 = 0 TO 500
endif
endif
if Ych < 514 then
Ydir = 0
if Ych > 499 then
Yspd = 0
else
Yspd = 500 - Ych ' 500 - 499 TO 0 = 0 TO 500
endif
endif
RETURN
'******* SUB: Home Routine ************************************
Home:
Xdir = 0 ' set home and clear Xpos and Ypos
Ydir = 0
TMR0H = 0 ' Set pulses @ 6.5mS (65535 preload)
TMR0L = 0
HomeX:
WHILE XlimNear = 0 ' Drive to Home X slowly
Xs_out = 0 ' drive a step pulse active
pauseus 3 ' delay to meet minimum time for drive
Xs_out = 1 ' return the pulse to inactive
wend
while XlimNear = 1
Xs_out = 0 ' drive a step pulse active
pauseus 3 ' delay to meet minimum time for drive
Xs_out = 1 ' return the pulse to inactive
wend
Xpos = 0 ' clear the counter to keep track of location
HomeY:
WHILE YlimNear =0 ' Drive to Home X slowly
Ys_out = 0 ' drive a step pulse active
pauseus 3 ' delay to meet minimum time for drive
Ys_out = 1 ' return the pulse to inactive
wend
while YlimNear = 1
Ys_out = 0 ' drive a step pulse active
pauseus 3 ' delay to meet minimum time for drive
Ys_out = 1 ' return the pulse to inactive
wend
Ypos = 0 ' clear the counter to keep track of location
return
'***** Initial setup ****************************************
Start:
while SwTmb =0
wend
beeper = 1 ' sound horn to warn of movement
pause 1000
beeper = 0
pause 1000
call Home ' initial homing & zeroing of position counters
ZeroStick:
call GetAD ' check 0 readings on joystick
while (Xch < 500) or (Xch > 527)or (Ych < 500) or (Ych > 527)
wend
beeper = 1 ' sound horn Done
pause 500
beeper = 0
pause 500
beeper = 1
pause 500
beeper = 0
pause 500
@ INT_ENABLE TMR0_INT ; enable Timer 0
'******* MAIN ***********************************************
Main:
call GetAD
TMR0H = Zch.HighByte ' setup speed by getting Z as preload
TMR0L = Zch.LowByte ' to Timer 0
call DirChk ' sets direction, speed, and null
' show results
hserout ["A/D X = ",DEC Xch," A/D Y = ",DEC Ych," A/D Speed = ",DEC Zch,13,10]
hserout ["Position X= ",DEC Xpos,", Y= ",dec Ypos,13,10]
GOTO Main
'******** Interrupt *******************************
PulseCk:
Holdoff[0] = (Xspd*12) ' 12 = approx step/bit ratio
if IntCnt[0] = Holdoff[0] then
goto PulseX
else
goto ChkY
endif
PulseX:
Xs_out = 0 ' drive a step pulse active
if Xdir = 1 then
Xpos = Xpos + 1
else
Xpos = Xpos - 1
Xs_out = 1 ' return the pulse to inactive
endif
IntCnt[0] = 0 ' clear count of interrupts
ChkY:
Holdoff[1] = Yspd*12
if IntCnt[1] = Holdoff[1] then
goto PulseY
else
goto NoPulse
endif
PulseY:
Ys_out = 0 ' drive a step pulse active
if Ydir =1 then
Ypos = Ypos + 1
else
Ypos = Ypos - 1
Ys_out = 1 ' return the pulse to inactive
endif
IntCnt[1] = 0 ' clear count of interrupts
NoPulse:
IntCnt[0] = IntCnt[0] + 1 ' keep track of times -
IntCnt[1] = IntCnt[1] + 1 ' through the interrupt
@ INT_RETURN '
;********* End of Interrupt **********************
END
The floor is open for comment....
Bookmarks