; *********************************************
;*
;* PIC based PM motor drive controller
;* Pioneer Microsystems, Inc.
;* Pittsburgh, Pa. (412)-369-9920
;* Christopher Eddy, PE, 4/1/97
;*
;*********************************************
;*
;* Board is based on 16C73A.
;*
;**********************************************
;* configuration switches
;*
TITLE "PM motor speed controller code, rev b by cle/pu"
; chris eddy, 4/1/97
list N=66,C=120,p=16c73A
; __CONFIG _WDT_ON & _CP_OFF & _HS_OSC & _PWRTE_ON
include "p16c73.inc"
FALSE SET 0
TRUE SET 1
;******************************************************************
;*************** DETERMINE OVERCURRENT CUTOUT *************
; 1/4V=1A, 5V=FS, FS=20A. FOR 10A USE 128 DIGITAL
;******************************************************************
#DEFINE OVERCURRENT D'128'
;******************************************************************
;*************** DECIDE IF WE SHOULD RUN PRE-EMPHASIS *************
;******************************************************************
; note, also known as IR compensation.
#DEFINE PREEMPHASIS FALSE
;******************************************************************
;*************** DECIDE IF WE SHOULD RUN DEADBAND *************
;******************************************************************
#DEFINE DEADBAND_ENABLE FALSE
;******************************************************************
;*************** SET THE PWM FREQUENCY *************
;******************************************************************
#DEFINE PWM_FREQUENCY D'163'
;#DEFINE PWM_FREQUENCY D'97' ;100Hz
;#DEFINE PWM_FREQUENCY D'163' ;60Hz
;#DEFINE PWM_FREQUENCY D'255' ;38Hz
;******************************************************************
;*************** DETERMINE ANALOG DEADBAND *************
;******************************************************************
#DEFINE DEADBAND D'10'
;*************** PORT DIRECTION SETUP CONSTANTS **********************
PORTASETUP equ B'11111111'
PORTBSETUP equ B'11111111'
PORTCSETUP equ B'00000001'
;******************************************************************
;***************DECLARE VARIABLES****************************
;******************************************************************
MOTOR_DROP equ H'20'
TEMPORARY equ H'21'
DIFERROR equ H'22'
PROPORTION equ H'23'
INTEGRAL equ H'24'
ATODCHAN equ H'25'
VOLTAGE_INPUT equ H'26'
CURRENT_INPUT equ H'27'
SUPPLY_INPUT equ H'28'
COMMAND_INPUT equ H'29'
RAMP_SPEED EQU H'2A'
UTILITY equ H'2B'
ACCaLO EQU H'2C'
ACCaHI EQU H'2D'
ACCbLO EQU H'2E'
ACCbHI EQU H'2F'
ACCcLO EQU H'30'
ACCcHI EQU H'31'
ACCdLO EQU H'32'
ACCdHI EQU H'33'
temp equ H'34'
sign equ H'35'
RAMP_TIME equ H'36'
TEMPORARY2 equ H'37'
ADWAIT equ H'38'
POT_VR1 equ H'39'
POT_VR2 equ H'3A'
POT_VR3 equ H'3B'
INTEGRAL_TIME equ H'3C'
MY_PWM equ H'3D'
MY_TARGET equ H'3E'
CURRENT_TRIP equ H'3F'
AVERAGE_LO equ H'40'
AVERAGE_HI equ H'41'
VOLTAGE_POINTER equ H'42'
CURRENT_POINTER equ H'43'
SUPPLY_POINTER equ H'44'
COMMAND_POINTER equ H'45'
PWM_DIFF equ H'46'
HOWFAROFF equ H'47'
SIGNED equ FALSE ; Set This To 'TRUE' for signed math
;******* UPPER PAGE VARIABLES used for a digital filter *****************
VOLTAGE_FILTER equ H'D8' ; TO DF
CURRENT_FILTER equ H'E0'
SUPPLY_FILTER equ H'E8'
COMMAND_FILTER equ H'F0'
;******************************************************************
;******* INTERRUPT STORAGE BYTES COVER BOTH PAGES ***********************
;******************************************************************
TEMP_W EQU H'7C' ; AND FC
TEMP_FSR EQU H'7D' ; AND FD
TEMP_STAT EQU H'7E' ; AND FE
TEMP_PCLATH EQU H'7F' ; AND FF
;******************************************************************
;*************** PIC I/O PINS (A PORT) *************************************
;******************************************************************
; see analog input code
;******************************************************************
;*************** PIC I/O PINS (B PORT) *************************************
;******************************************************************
SW0 equ 0 ; bit 0, in
SW1 equ 1 ; bit 1, in
SW2 equ 2 ; bit 2, in
SW3 equ 3 ; bit 3, in
;******************************************************************
;*************** PIC I/O PINS (C PORT) *************************************
;******************************************************************
INHIBIT equ 0 ; bit 0, INPUT
;DIRECT equ 1 ; bit 1, output
PWM equ 2 ; bit 2, output
TESTING equ 3 ; bit 3, output
;_DIRECT equ 4 ; bit 4, output
ADJ1 equ 5 ; bit 5, output
ADJ2 equ 6 ; bit 6, output
ADJ3 equ 7 ; bit 7, output
;******************************************************************
;*************** UTILITY FLAGS **********************
;******************************************************************
CARRYFLAG equ 0
INTEGRAL_NOW equ 1
DELAYED_ANALOG_START EQU 2
SIGN_OF_ERROR EQU 3
P_CONTROL equ 4
I_CONTROL equ 5
IV_CONTROL equ 6
STOP_CONTROL equ 7
;******************************************************************
;*************** CODE POINT DEFINITIONS **********************
;******************************************************************
RESET equ H'0000'
INTERRUPT equ H'0004'
CODEP0 equ H'0005'
CODEP1 equ H'0800'
;*************** MAIN PROGRAM DECLARATIONS *******************
; FOLLOWING CODE IS IN PAGE 0, IN VECTORS AREA
;******************************************************************
org RESET ;RESET VECTOR
goto event_START
goto event_START
goto event_START
goto event_START
org INTERRUPT ;INTERRUPT VECTOR
;*************** INTERUPT SERVICE ROUTINE **************************
; INTERRUPT IS SERVICED BY THE GOTO IN THE ADDRESS VECTOR AT ADDRESS 4.
; interrupts can be caused by the following sources:
; timer0, ad complete, iic,
; in our case, they will be caused by;
; if int on ad capture, get ana conversion, place in mem
; TIMER0 is a timed tick that allows key input monitoring et al.
;******************************************************************
INTERRUPT_SERVICE
; PUSH REGISTERS SEE PG.82
MOVWF TEMP_W
SWAPF STATUS,W
BCF STATUS,RP0
MOVWF TEMP_STAT
MOVF PCLATH,W
MOVWF TEMP_PCLATH
MOVF FSR,W
MOVWF TEMP_FSR
; CHECK FOR A TIMER 0 OVERFLOW
; ONLY CHECK IF INT IS ENABLED
BTFSS INTCON,T0IE
GOTO INT_1
BTFSS INTCON,T0IF
GOTO INT_1
CALL TIMERTICK
INT_1
; CHECK THE PERIPHERAL INTERRUPTS
; ONLY CHECK IF INT IS ENABLED
BTFSS INTCON,PEIE
GOTO INT_2
; CHECK FOR A TIMER 2 OVERFLOW
; ONLY CHECK IF INT IS ENABLED
BSF STATUS,RP0
BTFSS PIE1,TMR2IE
GOTO INT_3
BCF STATUS,RP0
BTFSS PIR1,TMR2IF
GOTO INT_3
CALL TIMER2TICK
INT_3
; ONLY CHECK A/D COMPLETE IF INT IS ENABLED
BSF STATUS,RP0
BTFSS PIE1,ADIE
GOTO INT_2
BCF STATUS,RP0
BTFSC PIR1,ADIF
CALL GETAD
INT_2
; POP REGISTERS SEE PG.82
BCF STATUS,RP0
MOVF TEMP_FSR,W
MOVWF FSR
MOVF TEMP_PCLATH,W
MOVWF PCLATH
SWAPF TEMP_STAT,W
MOVWF STATUS
SWAPF TEMP_W,F
SWAPF TEMP_W,W
INTDNE RETFIE
;*************** CODE PAGE 0 START ********************************
; FOLLOWING CODE IS IN PAGE 0
;******************************************************************
; org CODEP0
include "maths.inc"
event_START
BCF STATUS,RP0
MOVLW H'00'
MOVWF PORTA
BSF STATUS,RP0
MOVLW PORTASETUP
MOVWF TRISA
BCF STATUS,RP0
MOVLW H'00'
MOVWF PORTB
BSF STATUS,RP0
MOVLW PORTBSETUP
MOVWF TRISB
BCF STATUS,RP0
MOVLW H'00'
MOVWF PORTC
BSF STATUS,RP0
MOVLW PORTCSETUP
MOVWF TRISC
; option register
; bit 7 ~rbpu SET TO 0 SO PULLUP IN PORT B READ WORKS
; bit 6 INTEDG.. program as a one
; bit 5 T0CS 1=RC3 PIN, 0=INT CLK FOR TIM0
; bit 4 T0SE 1=HI TO LOW, 0= OPPOSITE EDGE TIM0
; bit 3 PSA assigned to WDT, set to 1
; bit 2 to 0 are prescale setting
; code wdt tmr0
; 000 1:1 1:2
; 001 1:2 1:4
; 010 1:4 1:8
; 011 1:8 1:16
; 100 1:16 1:32
; 101 1:32 1:64
; 110 1:64 1:128
; 111 1:128 1:256
; example WDT, internal clock prescale of 128
; 18mS*128 = 2.304 seconds
BSF STATUS,RP0
MOVLW B'01000010'
MOVWF OPTION_REG ;SET WDT PRESCALER & PULL UPS
; CLEAR THE PIR1 BEFORE ENABLING INTERRUPTS
; PIR1 bit definitions, clear before enabling
; bit 7 PSPIF: PAR SLAVE PORT interrupt status
; bit 6 ADIF: A/D CONV COMPLETE INT
; bit 5 RCIF: SERIAL RX INT FLAG
; bit 4 TXIF: SERIAL TX INT FLAG
; bit 3 SSPIF: SYNC PORT int status
; bit 2 CCP1IF: CAPTURE/COMPARE/PWM INT
; bit 1 TMR2IF: TIMER 2 INT FLAG
; bit 0 TMR1IF: TIMER 1 INT FLAG
BCF STATUS,RP0
MOVLW B'00000000'
MOVWF PIR1
; T1CON bit definitions
; bit 7 NO DEF
; bit 6 NO DEF
; bit 5 T1CKPS1: PRESCALE BITS
; bit 4 T1CKPS0: 0=1,01=2,10=4,11=8
; bit 3 T1OSCEN: 1=OSC EN, 0=OSC DIS
; bit 2 ~T1SYNC: IGNORED FOR INT CLOCK
; bit 1 TMR1CS: 1=EXT, 0=INT CLK
; bit 0 TMR1ON: 1=ENABLE 0=DISABLE TIMER 1
; LEAVE TIMER OFF UNTIL SETUP IS PERFORMED
BCF STATUS,RP0
MOVLW B'00000000'
MOVWF T1CON
; T2CON bit definitions
; bit 7 NO DEF
; bit 6 TOUTPS3: \
; bit 5 TOUTPS2: \ POST SCALE SELECT, SCALE 1 TO 16
; bit 4 TOUTPS1: /
; bit 3 TOUTPS0: /
; bit 2 TMR2ON: 1=ON, 0=OFF
; bit 1 T2CKPS1: \ CLOCK PRESCALER, 00=1, 01=4, 1x=16
; bit 0 T2CKPS0: /
BCF STATUS,RP0
MOVLW B'00000100'
MOVWF T2CON
; CCP1CON bit definitions
; bit 7 NO DEF
; bit 6 NO DEF
; bit 5 CCP1X: \ HIGH TWO BITS ALLOW 10 BIT RESOLUTION ON PWM
; bit 4 CCP1Y: /
; bit 3 TOUTPS3: \
; bit 2 TOUTPS2: \ MODE, SEE BOOK
; bit 1 TOUTPS1: / 11XX MAKES PWM MODE
; bit 0 TOUTPS0: /
BCF STATUS,RP0
MOVLW B'00000000'
MOVWF CCP1CON
; PIE1 bit definitions
; bit 7 PSPIE: PAR SLAVE PORT interrupt status
; bit 6 ADIE: A/D CONV COMPLETE INT
; bit 5 RCIE: SERIAL RX INT ENABLE
; bit 4 TXIE: SERIAL TX INT ENABLE
; bit 3 SSPIE: SYNC PORT int status
; bit 2 CCP1IE: CAPTURE/COMPARE/PWM INT
; bit 1 TMR2IE: TIMER 2 INT FLAG
; bit 0 TMR1IE: TIMER 1 INT FLAG
BSF STATUS,RP0
MOVLW B'01000010'
MOVWF PIE1
; interrupt control register as such;
; bit 7 GIE Global interrupt enable
; bit 6 PEIE peripheral int enable
; bit 5 T0IE tmr0 int enable
; bit 4 INTE INTF ENABLE BIT
; bit 3 RBIE ENABLE INT ON PORT B0:3 CHANGE
; bit 2 T0IF tmr0 overflow prog as any
; bit 1 INTF EXTERNAL INTERRUPT FLAG
; bit 0 RBIF FLAG ON PORT B0:3 CHANGE
BCF STATUS,RP0
movlw B'01100000'
movwf INTCON
; ADCON0 control register as such;
; bit 7 ADCS1 \
; bit 6 ADCS0 -A/D freq select
; 00=fosc/2
; 01=fosc/8
; 10=fosc/32
; 11=rc oscillator
; bit 5 CHS2 \
; bit 4 CHS1 -select channel
; bit 3 CHS0 /
; bit 2 GO/_DONE conversion progress 1=running, 0=complete
; bit 1 reserved
; bit 0 A/D operate 1=on
; note: do not set bit 0 and 2 in the same instruction
BCF STATUS,RP0
MOVLW B'11000001'
MOVWF ADCON0
; ADCON1 control register as such;
; bit 7 reserved
; bit 6 reserved
; bit 5 reserved
; bit 4 reserved
; bit 3 reserved
; bit 2 PCFG2 \
; bit 1 PCFG1 -A/D pin configuration control
; bit 0 PCFG0 /
; see book for combinations
; 101 sets AN0 and AN1 with ref on AN3
; 000 sets ALL with ref FROM VCC
BSF STATUS,RP0
MOVLW B'00000000'
MOVWF ADCON1
; RCSTA control register as such;
; bit 7 SPEN SERIAL PORT ENABLE
; bit 6 RC8/9 1=9 0=8 BIT RECIEVE
; bit 5 SREN DONT CARE IN ASYNCH
; bit 4 CREN 1=ENABLE RECIEVE, 0=DISABLE RECIEVE
; bit 3 NOT IN USE
; bit 2 FERR FRAMING ERROR BIT, 1= ERROR
; bit 1 OERR OVERRUN ERROR BIT 1=OVERRUN
; bit 0 RCD8 9TH BIT OF DATA, CAN BE PARITY
BCF STATUS,RP0
MOVLW B'00000000'
MOVWF RCSTA
; TXSTA control register as such;
; bit 7 CSRC CLOCK SOURCE DONT CARE IN ASYNCH
; bit 6 TX8/9 1=9 BIT TX, 0=8 BIT
; bit 5 TXEN 1= ENABLE TRANSMIT
; bit 4 SYNC 1=SYNCHRONOUS MODE, 0=ASYNCHRONOUS
; bit 3 UNIMPLEMENTED
; bit 2 BRGH 1=HIGH SPEED, 0=LOW SPEED (HIGH SPEED RIFE WITH BUGS)
; bit 1 TRMT 1=TX REG EMPTY, 0= FULL
; bit 0 TXD8 9TH BIT OF DATA, CAN BE PARITY
BSF STATUS,RP0
MOVLW B'00000000'
MOVWF TXSTA
; CLEAR UTILITY FLAGS
BCF STATUS,RP0
clrf UTILITY
clrf ATODCHAN
BSF STATUS,RP0
MOVLW PWM_FREQUENCY
MOVWF PR2
BCF STATUS,RP0
; SETUP INTERRUPTS TO FUNCTION
BSF INTCON,GIE
;******************************************************************
event_BEGIN
;******************************************************************
CLRWDT
;******************************************************************
; configure I/O ports again so we don't lose port directions
;******************************************************************
event_PORT_DIRN
BSF STATUS,RP0
MOVLW PORTASETUP
MOVWF TRISA
MOVLW PORTBSETUP
MOVWF TRISB
MOVLW PORTCSETUP
MOVWF TRISC
BCF STATUS,RP0
;******************************************************************
; GET B PORT AND SORT INTO STATE FLAGS..
;******************************************************************
BTFSS PORTB,SW0
BSF UTILITY,P_CONTROL
BTFSC PORTB,SW0
BCF UTILITY,P_CONTROL
BTFSS PORTB,SW1
BSF UTILITY,I_CONTROL
BTFSC PORTB,SW1
BCF UTILITY,I_CONTROL
BTFSS PORTB,SW2
BSF UTILITY,IV_CONTROL
BTFSC PORTB,SW2
BCF UTILITY,IV_CONTROL
; IF NEITHER P NOR I NOR IV OR INHIBIT, STOP
CLEARINT
BCF INTCON,GIE
BTFSC INTCON,GIE
GOTO CLEARINT
BSF UTILITY,STOP_CONTROL
BTFSC PORTC,INHIBIT
GOTO STATE01
BTFSC UTILITY,P_CONTROL
BCF UTILITY,STOP_CONTROL
BTFSC UTILITY,I_CONTROL
BCF UTILITY,STOP_CONTROL
BTFSC UTILITY,IV_CONTROL
BCF UTILITY,STOP_CONTROL
STATE01
BSF INTCON,GIE
GOTO event_BEGIN
;******************************************************
; GET FINISHED A/D CONVERSION
;******************************************************
GETAD
bcf STATUS,RP0
bcf PIR1,ADIF ;clear flag
; FLAG THE RESULTING CONVERSION FOR PROCESSING
btfss ATODCHAN,0 ;chan 0 (voltage)
GOTO GET01
; PROCESS THE VOLTAGE READING
; PLACE VALUE IN FILTER
INCF VOLTAGE_POINTER,F
; IF HIGH, CLEAR
BTFSC VOLTAGE_POINTER,3
CLRF VOLTAGE_POINTER
; NOW PUT IN MEM
MOVLW VOLTAGE_FILTER
ADDWF VOLTAGE_POINTER,W
MOVWF FSR
MOVFW ADRES
MOVWF VOLTAGE_INPUT
MOVFW ADRES
MOVWF INDF
; AVERAGE THE VALUES IN MEMORY
; MOVLW VOLTAGE_FILTER
; CALL AVERAGE_8
; MOVE RESULT INTO MAIN LOCATION
; MOVWF VOLTAGE_INPUT
GOTO event_PROCESS_END
GET01
btfss ATODCHAN,1 ;chan 1 (current)
GOTO GET02
; PROCESS THE CURRENT READING
MOVFW ADRES
MOVWF CURRENT_INPUT
GOTO event_PROCESS_END
GET02
btfss ATODCHAN,2 ;chan 2 (supply)
GOTO GET03
; PROCESS THE SUPPLY READING
; PLACE VALUE IN FILTER
INCF SUPPLY_POINTER,F
; IF HIGH, CLEAR
BTFSC SUPPLY_POINTER,3
CLRF SUPPLY_POINTER
; NOW PUT IN MEM
MOVLW SUPPLY_FILTER
ADDWF SUPPLY_POINTER,W
MOVWF FSR
MOVFW ADRES
; MOVWF INDF
; AVERAGE THE VALUES IN MEMORY
; MOVLW SUPPLY_FILTER
; CALL AVERAGE_8
; MOVE RESULT INTO MAIN LOCATION
MOVWF SUPPLY_INPUT
GOTO event_PROCESS_END
GET03
btfss ATODCHAN,3 ;chan 3 (command)
GOTO GET04
; PROCESS THE COMMAND READING
; MUST SCALE THIS READING SO THAT 0-255 FROM A/D WILL
; BECOME 0-TARGET DELTA MOTOR READING
; REMEMBER THAT SUPPLY READING FULL SCALE IS 0-80VDC
; LATE ADDITION.. SCALE FURTHER FOR A SUB-SPAN,
; SUCH THAT 0-63% REPRESENTS FULL SPEED (21VDC) (FEEDER)
; AND 0-77% REPRESENTS FULL SPEED (42VDC) (SUPPLY)
; RE-FORMULATED FOR 0-100% CMD,
; FEEDER: 0-100% CMD = 21V*100%/63% OR 0-33.33VDC
; SUPPLY: 0-100% CMD = 42V*100%/77% OR 0-54.54VDC
; FEEDER: MUL BY 100, DIV BY 240.
; SUPPLY: MUL BY 100, DIV BY 146.
; BASE RANGE ON SWITCH 4.
; BUT ALL OF THIS SUBRANGE CAN BE #DEFINED OUT SEE ABOVE
MOVFW ADRES
; CALCULATE SCALED COMMAND AND MOVE RESULT INTO MAIN LOCATION
movwf ACCaLO
movlw 0
movwf ACCaHI
movlw 0
movwf ACCbHI
MOVLW D'100'
MOVWF ACCbLO
call D_mpyF
; RESULT IN B AND C, LSB IN C, IS ALL WE WANT
MOVFW ACCcHI
MOVWF ACCbHI
MOVFW ACCcLO
MOVWF ACCbLO
MOVLW 0
MOVWF ACCaHI
BTFSS PORTB,SW3
movLW D'240'
BTFSC PORTB,SW3
movLW D'146'
movwf ACCaLO
CALL D_divF
MOVFW ACCbLO
MOVWF COMMAND_INPUT
IF PREEMPHASIS==TRUE
; if required, calculate a pre-emphasis on
; the low end to compensate for weak
; performance under load. So, if cmd<15%, and
; current goes up, then boost the command setpoint.
; seems that 15% command is 15/255 to final pwm.
GET03D
MOVLW D'15' ; ANYTHING BELOW 15%
SUBWF COMMAND_INPUT,W
BTFSC STATUS,C
GOTO GET03B
; MOVLW D'3' ; ANYTHING ABOVE 390mA
; CURRENT TRIP.. 5 IS GOOD FOR 12-15%,
; AND 3 IS GOOD FOR 7-12%.
MOVFW COMMAND_INPUT
ADDLW D'20'
; MOVWF CURRENT_TRIP
; BCF STATUS,C
; RRF CURRENT_TRIP,F
; BCF STATUS,C
; RRF CURRENT_TRIP,W
SUBWF CURRENT_INPUT,W
BTFSS STATUS,C
GOTO GET03B
; INCREASE COMMAND BY 10%
; MOVLW D'3'
; ADDWF COMMAND_INPUT,F
BCF STATUS,C
RLF COMMAND_INPUT,F
GET03B
ENDIF
GOTO event_PROCESS_END
GET04
btfss ATODCHAN,4 ;chan 4 (pot)
GOTO GET05
COMF ADRES,W
MOVWF POT_VR1
GOTO event_PROCESS_END
GET05
btfss ATODCHAN,5 ;chan 5 (pot)
GOTO GET06
MOVFW ADRES
MOVWF POT_VR2
GOTO event_PROCESS_END
GET06
btfss ATODCHAN,6 ;chan 6 (pot)
GOTO event_PROCESS_END
MOVFW ADRES
MOVWF POT_VR3
event_PROCESS_END
; SET A FLAG FOR THE MAIN ROUTINE
BSF UTILITY,DELAYED_ANALOG_START
;******************************************************************
event_SETUPAD
;******************************************************************
BTFSS UTILITY,DELAYED_ANALOG_START
GOTO event_ADGET_end
; setup the next A/D conversion
; select the next channel
bcf STATUS,C
rlf ATODCHAN,F
btfsS ATODCHAN,7
GOTO SETUP_A
BCF UTILITY,DELAYED_ANALOG_START
BCF PORTC,TESTING
movlw h'01'
movwf ATODCHAN
GOTO event_ADGET_end
SETUP_A
; if accidentally set to 0
movfw ATODCHAN
btfsc STATUS,Z
incf ATODCHAN,F
; select the right channel in hardware
btfsc ATODCHAN,0 ;VOLTAGE
MOVLW B'10000001'
btfsC ATODCHAN,1 ;CURRENT
MOVLW B'10001001'
btfsC ATODCHAN,2 ;SUPPLY
MOVLW B'10010001'
btfsC ATODCHAN,3 ;COMMAND
MOVLW B'10011001'
btfsC ATODCHAN,4 ;POT VR1
MOVLW B'10100001'
btfsC ATODCHAN,5 ;POT VR2
MOVLW B'10100001'
btfsC ATODCHAN,6 ;POT VR3
MOVLW B'10100001'
MOVWF ADCON0
; SET THE POT MULTIPLEX
BCF PORTC,ADJ1
BCF PORTC,ADJ2
BCF PORTC,ADJ3
btfsC ATODCHAN,4 ;POT VR1
BSF PORTC,ADJ3
btfsC ATODCHAN,5 ;POT VR2
BSF PORTC,ADJ2
btfsC ATODCHAN,6 ;POT VR3
BSF PORTC,ADJ1
; MAKE SURE ONE IS SET
BTFSC PORTC,ADJ1
GOTO event_ADSET_end
BTFSC PORTC,ADJ2
GOTO event_ADSET_end
BTFSC PORTC,ADJ3
GOTO event_ADSET_end
; NONE SET.. SET ONE
BSF PORTC,ADJ3
event_ADSET_end
;******************************************************************
; start a/d converter conversion
; must wait 15uS, then start a/d. @10mhZ, 38CYCLES.
;******************************************************************
MOVLW D'218'
MOVWF ADWAIT
WAITING_1
INCFSZ ADWAIT,F
goto WAITING_1
bsf ADCON0,GO_DONE
event_ADGET_end
RETURN
;******************************************************************
AVERAGE_8
;******************************************************************
; AVERAGE 8 VALUES AS A FILTER FUNCTION
MOVWF FSR
CLRF TEMPORARY
CLRF AVERAGE_LO
CLRF AVERAGE_HI
AVERAGE_1
MOVFW INDF
ADDWF AVERAGE_LO,F
BTFSC STATUS,C
INCF AVERAGE_HI,F
INCF TEMPORARY,F
BTFSS TEMPORARY,3
GOTO AVERAGE_1
RRF AVERAGE_HI,F
RRF AVERAGE_LO,F
RRF AVERAGE_HI,F
RRF AVERAGE_LO,F
RRF AVERAGE_HI,F
RRF AVERAGE_LO,W
return
;******************************************************************
;*************** TIMER SERVICE ROUTINE **************************
;******************************************************************
TIMERTICK
; INT COMES FOSC/4/128/256 (WAS FOSC/4/8/256)
; FOR 10.00M, 13mS (WAS 820uS)
BCF STATUS,RP0
BCF INTCON,T0IF
; ADD AN OPTIONAL RAMP ACCELERATE CONTROL
; ( DECELERATE IS NO BIG DEAL )
; PRETEND WE LOOK AT THE RAMP POT TO MANAGE SPEED.
; FURTHER SAY TYPICAL RAMP ON 0-100D TRANSITION IS FULL
; TRANSIT IN 2 SECONDS. SAY WE MAKE A TIMER HERE THAT
; ROLLS IN 13mS (WAS 802uS) * 16 (WAS 256) OR 200mS.
; MID SCALE ON POT IS 128.
; NEED 2000mS/200mS OR 10 INCREMENTS IN THAT TIME.
; 100 COUNTS / 10 INCREMENTS IS 10 UNITS, POT AT HALF IS
; 128, SHIFT DOWN THREE FOR 16 COUNT, SO WERE IN NEIGHBORHOOD.
INCF RAMP_TIME,F
BTFSS RAMP_TIME,6
GOTO RAMP_01
CLRF RAMP_TIME
; 200mS VISIT.
MOVFW RAMP_SPEED
SUBWF COMMAND_INPUT,W
BTFSS STATUS,C
GOTO RAMP_02
; DIF WAS POSITIVE, COMM>RAMP
MOVWF TEMPORARY
MOVFW POT_VR1
MOVWF TEMPORARY2
BCF STATUS,C
RRF TEMPORARY2,F
BCF STATUS,C
RRF TEMPORARY2,F
BCF STATUS,C
RRF TEMPORARY2,F
BCF STATUS,C
RRF TEMPORARY2,F
INCF TEMPORARY2,F ; ZERO WOULD BE A DISASTER
MOVFW TEMPORARY2
SUBWF TEMPORARY,W
; DID DIFF - MAX FROM POT
; IF POS, LIMIT TO MAX FROM POT
; IF NEG, WRITE COMMAND INTO RAMP
BTFSS STATUS,C
GOTO RAMP_02
MOVFW TEMPORARY2
ADDWF RAMP_SPEED,F
GOTO RAMP_01
RAMP_02
; DIF WAS NEGATIVE, REPLACE RAMP WITH COMMAND
MOVFW COMMAND_INPUT
; MOVFW RAW_CMD
MOVWF RAMP_SPEED
RAMP_01
; INCREMENT INTEGRAL TIME FOR LATER
BCF UTILITY,INTEGRAL_NOW
INCF INTEGRAL_TIME,F
MOVFW INTEGRAL_TIME
SUBWF POT_VR2,W
BTFSC STATUS,C
GOTO INTEGRAL_NOW_END
BSF UTILITY,INTEGRAL_NOW
CLRF INTEGRAL_TIME
INTEGRAL_NOW_END
; NEED TO KNOW SUPPLY MINUS VOLTAGE FOR MOTOR DROP
MOVFW VOLTAGE_INPUT
SUBWF SUPPLY_INPUT,W
MOVWF MOTOR_DROP
; MOTOR NEVER GOES NEGATIVE, IF SLIGHTLY OFF, CLEAR TO ZERO
BTFSS STATUS,C
CLRF MOTOR_DROP
; CALCULATE ERROR MAGNITUDE AND SIGN
MOVFW MOTOR_DROP
SUBWF RAMP_SPEED,W
MOVWF DIFERROR
BTFSC STATUS,C
BSF UTILITY,SIGN_OF_ERROR
BTFSS STATUS,C
BCF UTILITY,SIGN_OF_ERROR
; SPLIT BASED UPON SIGN OF THE ERROR
BTFSS UTILITY,SIGN_OF_ERROR
GOTO ACT_1
; GET HERE IF COMMAND-MOTOR DROP IS POSITIVE
; MUST INCREASE SPEED OF MOTOR
; INTEGRAL COMPONENT
BTFSS UTILITY,INTEGRAL_NOW
GOTO ACT_1B
; MOVFW DIFERROR
; MOVLW D'1'
BCF STATUS,C
RRF DIFERROR,W
ADDWF INTEGRAL,F
; IF CARRY, MAX OUT AT FF
BTFSS STATUS,C
GOTO ACT_1B
MOVLW H'FF'
MOVWF INTEGRAL
ACT_1B
; PROP COMPONENT
; CALCULATE SCALED ERROR AND MOVE RESULT INTO MAIN LOCATION
MOVFW DIFERROR
movwf ACCaLO
movlw 0
movwf ACCaHI
comf POT_VR3,w ; pot is wired backwards
movwf ACCbLO
bcf STATUS,C
rrf ACCbLO,F ; div by two to spread pot
bcf STATUS,C
rrf ACCbLO,F ; div by two to spread pot
movlw 0
movwf ACCbHI
call D_mpyF
; RESULT IN B AND C, LSB IN Clo,
; IF MSB IS SET SEND FF
MOVFW ACCcLO
MOVWF PROPORTION
MOVFW ACCcHI
BTFSC STATUS,Z
GOTO ACT_2
MOVLW H'FF'
MOVWF PROPORTION
GOTO ACT_2
ACT_1 ; GET HERE IF COMMAND-MOTOR DROP IS NEGATIVE
; MUST DECREASE SPEED OF MOTOR
; INTEGRAL COMPONENT
BTFSS UTILITY,INTEGRAL_NOW
GOTO ACT_1D
MOVFW DIFERROR
; MOVLW H'FE'
; BSF STATUS,C
; RRF DIFERROR,W
ADDWF INTEGRAL,F
; IF CARRY, MIN DOWN TO 00
BTFSC STATUS,C
GOTO ACT_1D
MOVLW H'00'
MOVWF INTEGRAL
ACT_1D
; PROP COMPONENT
CLRF PROPORTION
GOTO ACT_2
ACT_2
; IF CMD IS ZERO, CLEAR INTEGRAL
MOVFW COMMAND_INPUT
BTFSC STATUS,Z
CLRF INTEGRAL
; IF SET TO STOP, DO SO
BTFSS UTILITY,STOP_CONTROL
GOTO ACT_2B
CLRF TEMPORARY
; ALSO SET THE RAMP_SPEED TO 0 TO ENABLE ACCEL
CLRF RAMP_SPEED
GOTO ACT_3
ACT_2B
; IF SET TO P_CONTROL, DO SO
BTFSS UTILITY,P_CONTROL
GOTO ACT_2D
MOVFW PROPORTION
MOVWF TEMPORARY
GOTO ACT_3
ACT_2D
; IF SET TO I_CONTROL, DO SO
BTFSS UTILITY,I_CONTROL
GOTO ACT_2E
MOVFW INTEGRAL
MOVWF TEMPORARY
GOTO ACT_3
ACT_2E
; IF SET TO IV_CONTROL, DO SO
BTFSS UTILITY,IV_CONTROL
GOTO ACT_2F
MOVLW H'FF'
MOVWF TEMPORARY
MOVFW INTEGRAL
ADDWF PROPORTION,W
BTFSS STATUS,C
MOVWF TEMPORARY
GOTO ACT_3
ACT_2F
; ERROR, JUST STOP
CLRF TEMPORARY
ACT_3
; LAST SECOND ABORT IN CASE OF OVERCURRENT
; CURRENT_INPUT IS SCALES 0-255=0-10A
MOVLW OVERCURRENT
SUBWF CURRENT_INPUT,W
BTFSC STATUS,C
CLRF TEMPORARY
IF DEADBAND_ENABLE==TRUE
; IMPLEMENT A DEADBAND
MOVFW MY_TARGET
MOVWF PWM_DIFF
MOVFW TEMPORARY
SUBWF PWM_DIFF,F
BTFSS STATUS,C
COMF PWM_DIFF,F
MOVFW PWM_DIFF
SUBLW DEADBAND
BTFSC STATUS,C
GOTO ACT_END
; MOVWF HOWFAROFF
ENDIF
; SAVE TARGET INTO PWM TARGET
MOVFW TEMPORARY
MOVWF MY_TARGET
ACT_END
RETURN
;******************************************************************
;*************** TIMER 2 SERVICE ROUTINE **************************
;******************************************************************
TIMER2TICK
; INT COMES FOSC/4/PR2
; FOR 10.00M & PR2=97, 39uS.
BCF STATUS,RP0
BCF PIR1,TMR2IF
; CREATE MY OWN PWM
INCF MY_PWM,F
MOVLW D'240'
SUBWF MY_PWM,W
BTFSS STATUS,Z
GOTO TMR1_GO
BSF UTILITY,DELAYED_ANALOG_START
BSF PORTC,TESTING
CALL SETUP_A ; A CHEAT TO TRIP THE AD
TMR1_GO
; IF CMD IS ZERO, KILL THE PWM
MOVFW COMMAND_INPUT
BTFSS STATUS,Z
GOTO TMR2_GO
BSF PORTC,PWM
RETURN
TMR2_GO
; IF STOP SET, KILL THE PWM
BTFSS UTILITY,STOP_CONTROL
GOTO TMR3_GO
BSF PORTC,PWM
RETURN
TMR3_GO
; NOT ZERO, GO AHEAD AND DO IT.
MOVFW MY_PWM
SUBWF MY_TARGET,W
BTFSS STATUS,C
BSF PORTC,PWM
BTFSC STATUS,C
BCF PORTC,PWM
RETURN
END
file: /Techref/microchip/io/dev/motor/servob/SERVOB.ASM, 28KB, , updated: 2001/4/6 02:25, local time: 2024/12/26 08:15,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/microchip/io/dev/motor/servob/SERVOB.ASM"> microchip io dev motor servob SERVOB</A> |
Did you find what you needed?
|