; ******************************************************************************
;
; LiniStepper v3-vp
; PIC16F1826 by vegipete, November 2014
; Copyright Aug 2002 - Nov 2009 - Roman Black http://www.romanblack.com
;
; PIC assembler code for the LiniStepper stepper motor driver board.
; 200/400/1200/3600 steps
;
; v2.0 New version 2.0; 2nd Nov 2009.
; * modified v1 source to work with new Lini v2 PCB.
; * STEP and DIR are the same, but POWER is now "ENABLE" (active LOW)
; (so the POWER pin function is inverted in Lini v2)
; v2.1 Updated 16th Nov 2010.
; Now incorporates update suggested by Brian D Freeman; improves
; performance by skipping the current calculation on the hi-lo
; transition of the step input.
; v3.0vp Update Nov, 2014
; Changed to PIC16F1826
; internal 32MHz osc
; v3.1vp Update Feb, 2015
; Fixed a majorly hideous phase current table screw-up
;
;******************************************************************************
;
; Pin Usage
;
; RA0 Pin 17 step rising edge = move
; RA1 Pin 18 direction
; RA2 Pin 1 !enable low = motors energized
; RA3 Pin 2 mode 0 \ latch on falling
; RA4 Pin 3 mode 1 / edge of enable
; RA5 Pin 4 !MCLR (Input only)
; RA6 Pin 15 LED - on when low power
; RA7 Pin 16
;
; RB0 Pin 6 !A1 \
; RB1 Pin 7 !A2 \ Phase to
; RB2 Pin 8 !B1 / hold off
; RB3 Pin 9 !B2 /
; RB4 Pin 10 DAC AL
; RB5 Pin 11 DAC AH
; RB6 Pin 12 DAC BL
; RB7 Pin 13 DAC BH
;==============================================================================
; mplab settings
ERRORLEVEL -224 ; suppress annoying message because of option/tris
ERRORLEVEL -302 ; suppress message because of bank select in setup ports
LIST b=5, n=97, t=ON, st=OFF ;
; absolute listing tabs=5, lines=97, trim long lines=ON, symbol table=OFF
;==============================================================================
; processor defined
include <p16f1826.inc>
; processor config ( errlev -303 to hide some weird word size error in config values)
ERRORLEVEL -303
; CONFIG1
; __config 0xEFC4
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_ON
; CONFIG2
; __config 0xFBFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_HI & _LVP_ON
ERRORLEVEL +303
;==============================================================================
; Variables here
CBLOCK 0x70 ; start of common RAM
count:3 ; timeout counter
current13 ; for current tween pwm
current23 ; for current tween pwm
inputs_last ; stores last states of input pins
ENDC
;-------------------------------------------------
; PIC i/o pins for PORTA
#define STEP 0 ; / = move 1 step, \ = do nothing
#define DIR 1 ; lo = one way, hi = the other way
#define ENABLE 2 ; lo = enabled, hi = disable
#define LED_ON bsf PORTA,6
#define LED_OFF bcf PORTA,6
;==============================================================================
; CODE GOES HERE
org 0x0000 ; Set program memory base at reset vector 0x00
reset_vect
goto main ;
;==============================================================================
; INTERRUPT vector here
; The processor saves/restores contex automatically
org 0x0004 ; interrupt routine must start here
interrupt_vect
;-------------------------------------------------
; we get here every 256 timer0 ticks 3900Hz
; int body code here if you want
bcf INTCON,T0IF ; reset the tmr0 interrupt flag
incf count+1,f
;-------------------------------------------------
int_exit
retfie ; return from interrupt
;==============================================================================
; CURRENT INFO.
; hardware requires that we send the entire 8 bits to the motor
; at one time, to keep pwm fast.
;
; ----xxxx, where xxxx is the coils on/off phasing
; xx------, where xx is current for A phase
; --xx----, where xx is current for B phase
;
; hardware currents for 6th stepping have 4 possible values;
; 00 = 0% current
; 01 = 25% current
; 10 = 55% current
; 11 = 100% current
;
;-------------------------------------------------
; PWM INFO.
; Hardware gives us 6th steps, or 1200 steps/rev.
; To get 3600 steps/rev we need TWO more "tween" steps between every
; proper hardware 6th step.
;
; To do this we set 2 currents, current1 and current2.
; Then we do FAST pwm, with 2 time units at current2,
; and 1 time unit at current1.
; This gives a current which is between the two currents,
; proportionally closer to current2. (2/3 obviously)
; This gives the ability to get 2 evenly spaced "tween" currents
; between our hardware 6th step currents, and go from 1200 to 3600.
;-------------------------------------------------
;72 step table
Tab72_Start
dt (Tab72_End - Tab72_Start),0
; 2/3 1/3 Step# Phases
dt b'11000101',b'11000101' ;=100,0 - 100, 0 0 0101
dt b'11000101',b'11010101' ; 100,0 - 100, 25 1
dt b'11010101',b'11000101' ; 100,25 - 100, 0 2
dt b'11010101',b'11010101' ;=100,25 - 100, 25 3
dt b'11010101',b'11100101' ; 100,25 - 100, 55 4
dt b'11100101',b'11010101' ; 100,55 - 100, 25 5
dt b'11100101',b'11100101' ;=100,55 - 100, 55 6
dt b'11100101',b'11110101' ; 100,55 - 100, 100 7
dt b'11110101',b'11100101' ; 100,100 - 100, 55 8
dt b'11110101',b'11110101' ;=100,100 - 100, 100 9
dt b'11110101',b'10110101' ; 100,100 - 55, 100 10
dt b'10110101',b'11110101' ; 55,100 - 100, 100 11
dt b'10110101',b'10110101' ;=55,100 - 55, 100 12
dt b'10110101',b'01110101' ; 55,100 - 25, 100 13
dt b'01110101',b'10110101' ; 25,100 - 55, 100 14
dt b'01110101',b'01110101' ;=25,100 - 25, 100 15
dt b'01110101',b'00110101' ; 25,100 - 0, 100 16
dt b'00110101',b'01110101' ; 0,100 - 25, 100 17
dt b'00111001',b'00111001' ;=0, 100 - 0, 100 18 1001
dt b'00111001',b'01111001' ; 0, 100 - 25, 100 19
dt b'01111001',b'00111001' ; 25, 100 - 0, 100 20
dt b'01111001',b'01111001' ;=25, 100 - 25, 100 21
dt b'01111001',b'10111001' ; 25, 100 - 55, 100 22
dt b'10111001',b'01111001' ; 55, 100 - 25, 100 23
dt b'10111001',b'10111001' ;=55, 100 - 55, 100 24
dt b'10111001',b'11111001' ; 55, 100 - 100, 100 25
dt b'11111001',b'10111001' ; 100, 100 - 55, 100 26
dt b'11111001',b'11111001' ;=100, 100 - 100, 100 27
dt b'11111001',b'11101001' ; 100, 100 - 100, 55 28
dt b'11101001',b'11111001' ; 100, 55 - 100, 100 29
dt b'11101001',b'11101001' ;=100, 55 - 100, 55 30
dt b'11101001',b'11011001' ; 100, 55 - 100, 25 31
dt b'11011001',b'11101001' ; 100, 25 - 100, 55 32
dt b'11011001',b'11011001' ;=100, 25 - 100, 25 33
dt b'11011001',b'11001001' ; 100, 25 - 100, 0 34
dt b'11001001',b'11011001' ; 100, 0 - 100, 25 35
dt b'11001010',b'11001010' ;=100, 0 - 100, 0 36 1010
dt b'11001010',b'11011010' ; 100, 0 - 100, 25 37
dt b'11011010',b'11001010' ; 100, 25 - 100, 0 38
dt b'11011010',b'11011010' ;=100, 25 - 100, 25 39
dt b'11011010',b'11101010' ; 100, 25 - 100, 55 40
dt b'11101010',b'11011010' ; 100, 55 - 100, 25 41
dt b'11101010',b'11101010' ;=100, 55 - 100, 55 42
dt b'11101010',b'11111010' ; 100, 55 - 100, 100 43
dt b'11111010',b'11101010' ; 100, 100 - 100, 55 44
dt b'11111010',b'11111010' ;=100, 100 - 100, 100 45
dt b'11111010',b'10111010' ; 100, 100 - 55, 100 46
dt b'10111010',b'11111010' ; 55, 100 - 100, 100 47
dt b'10111010',b'10111010' ;=55, 100 - 55, 100 48
dt b'10111010',b'01111010' ; 55, 100 - 25, 100 49
dt b'01111010',b'10111010' ; 25, 100 - 55, 100 50
dt b'01111010',b'01111010' ;=25, 100 - 25, 100 51
dt b'01111010',b'00111010' ; 25, 100 - 0, 100 52
dt b'00111010',b'01111010' ; 0, 100 - 25, 100 53
dt b'00110110',b'00110110' ;=0, 100 - 0, 100 54 0110
dt b'00110110',b'01110110' ; 0, 100 - 25, 100 55
dt b'01110110',b'00110110' ; 25, 100 - 0, 100 56
dt b'01110110',b'01110110' ;=25, 100 - 25, 100 57
dt b'01110110',b'10110110' ; 25, 100 - 55, 100 58
dt b'10110110',b'01110110' ; 55, 100 - 25, 100 59
dt b'10110110',b'10110110' ;=55, 100 - 55, 100 60
dt b'10110110',b'11110110' ; 55, 100 - 100, 100 61
dt b'11110110',b'10110110' ; 100, 100 - 55, 100 62
dt b'11110110',b'11110110' ;=100, 100 - 100, 100 63
dt b'11110110',b'11100110' ; 100, 100 - 100, 55 64
dt b'11100110',b'11110110' ; 100, 55 - 100, 100 65
dt b'11100110',b'11100110' ;=100, 55 - 100, 55 66
dt b'11100110',b'11010110' ; 100, 55 - 100, 25 67
dt b'11010110',b'11100110' ; 100, 25 - 100, 55 68
dt b'11010110',b'11010110' ;=100, 25 - 100, 25 69
dt b'11010110',b'11000110' ; 100, 25 - 100, 0 70
dt b'11000110',b'11010110' ; 100, 0 - 100, 25 71
Tab72_End
dt 0,(Tab72_End - Tab72_Start)
;24 step table
;Uses hardware only microstepping
Tab24_Start
dt (Tab24_End - Tab24_Start),0
; 2/3 1/3 Step# Phases
dt b'11000101',b'11000101' ;=100, 0 - 100, 0 0 0101
dt b'11010101',b'11010101' ;=100, 25 - 100, 25 1
dt b'11100101',b'11100101' ;=100, 55 - 100, 55 2
dt b'11110101',b'11110101' ;=100, 100 - 100, 100 3
dt b'10110101',b'10110101' ;=55, 100 - 55, 100 4
dt b'01110101',b'01110101' ;=25, 100 - 25, 100 5
dt b'00111001',b'00111001' ;=0, 100 - 0, 100 6 1001
dt b'01111001',b'01111001' ;=25, 100 - 25, 100 7
dt b'10111001',b'10111001' ;=55, 100 - 55, 100 8
dt b'11111001',b'11111001' ;=100, 100 - 100, 100 9
dt b'11101001',b'11101001' ;=100, 55 - 100, 55 10
dt b'11011001',b'11011001' ;=100, 25 - 100, 25 11
dt b'11001010',b'11001010' ;=100, 0 - 100, 0 12 1010
dt b'11011010',b'11011010' ;=100, 25 - 100, 25 13
dt b'11101010',b'11101010' ;=100, 55 - 100, 55 14
dt b'11111010',b'11111010' ;=100, 100 - 100, 100 15
dt b'10111010',b'10111010' ;=55, 100 - 55, 100 16
dt b'01111010',b'01111010' ;=25, 100 - 25, 100 17
dt b'00110110',b'00110110' ;=0, 100 - 0, 100 18 0110
dt b'01110110',b'01110110' ;=25, 100 - 25, 100 19
dt b'10110110',b'10110110' ;=55, 100 - 55, 100 20
dt b'11110110',b'11110110' ;=100, 100 - 100, 100 21
dt b'11100110',b'11100110' ;=100, 55 - 100, 55 22
dt b'11010110',b'11010110' ;=100, 25 - 100, 25 23
Tab24_End
dt 0,(Tab24_End - Tab24_Start)
;8 step table
;Uses half-stepping
Tab08_Start
dt (Tab08_End - Tab08_Start),0
; 2/3 1/3 Step# Phases
dt b'11000101',b'11000101' ;=100, 0 - 100, 0 0 0101
dt b'11110101',b'11110101' ;=100, 100 - 100, 100 1
dt b'00111001',b'00111001' ;=0, 100 - 0, 100 2 1001
dt b'11111001',b'11111001' ;=100, 100 - 100, 100 3
dt b'11001010',b'11001010' ;=100, 0 - 100, 0 4 1010
dt b'11111010',b'11111010' ;=100, 100 - 100, 100 5
dt b'00110110',b'00110110' ;=0, 100 - 0, 100 6 0110
dt b'11110110',b'11110110' ;=100, 100 - 100, 100 7
Tab08_End
dt 0,(Tab08_End - Tab08_Start)
;4 step table
;Uses twin coil full-stepping
;(Commented lines are single coil full-stepping)
Tab04_Start
dt (Tab04_End - Tab04_Start),0
; 2/3 1/3 Step# Phases
; dt b'11000101',b'11000101' ;=100, 0 - 100, 0 0 0101
dt b'11110101',b'11110101' ;=100, 100 - 100, 100 0 0101
; dt b'11101001',b'11101001' ;=0, 100 - 0, 100 1 1001
dt b'11111001',b'11111001' ;=100, 100 - 100, 100 1 1001
; dt b'11001010',b'11001010' ;=100, 0 - 100, 0 2 1010
dt b'11111010',b'11111010' ;=100, 100 - 100, 100 2 1010
; dt b'11100110',b'11100110' ;=0, 100 - 0, 100 3 0110
dt b'11110110',b'11110110' ;=100, 100 - 100, 100 3 0110
Tab04_End
dt 0,(Tab04_End - Tab04_Start)
;force a flash page break in a known place, should also throw a
;warning if the tables above crossed a page boundary
org 0x100
;step downwards through the table
step_down
moviw --fsr1 ; unlike RETLW, Z set if WREG = 0
btfss STATUS,Z ; check if rolled under table
bra not_rolled_under
moviw --fsr1 ; grab offset to other end of table
addwf FSR1L,f ; shift to top end of table
; If the tables are known to not cross pages, we can ignore the high byte
; movlw 0
; addwfc FSR1H,f ; add possible carry to high byte
moviw --fsr1 ;
not_rolled_under
movwf current13
moviw --fsr1
movwf current23
bra pwm
;step upwards through the table
step_up
moviw ++fsr1 ; get past 2nd byte of current step
moviw ++fsr1 ; unlike RETLW, Z set if WREG = 0
btfss STATUS,Z ; check if rolled over table
bra not_rolled_over
moviw ++fsr1 ; grab offset to other end of table
subwf FSR1L,f ; shift to bottom end of table
; If the tables are known to not cross pages, we can ignore the high byte
; movlw 0
; subwfb FSR1H,f ; subtract possible borrow from high byte
moviw ++fsr1 ;
not_rolled_over
movwf current23
moviw ++fsr1
movwf current13
moviw --fsr1 ; shift back to 1st byte of new step
bra pwm
;******************************************************************************
; Main
;******************************************************************************
main
call setup ; initialize hardware
;---------------------------------------------
; main operating loop is here.
;---------------------------------------------
phase_off
clrf PORTB ; all phases off
bcf T1CON,TMR1ON ; stop the timer
bsf INTCON,GIE ; turn on interrupts for LED blink
enable_wait
LED_ON
btfss count+1,6 ; make LED blink
btfsc count+1,5
LED_OFF
btfsc PORTA,ENABLE ; wait for enable low
bra enable_wait ; not enabled so loop
bcf INTCON,GIE ; turn off interrupts
LED_OFF ; make sure it's off
movlw b'00000111' ; isolate STEP, DIR & ENABLE
andwf PORTA,w ; grab current input pins
movwf inputs_last ; save them
lsrf PORTA,w ; start shifting mode bits RA4 and RA3 (3,2)
lsrf WREG,w ; (2,1)
lsrf WREG,w ; (1,0)
andlw b'00000011' ; now mode # 0-3 in WREG
brw
goto Mode0
goto Mode1
goto Mode2
; goto Mode3
;Mode 3 - 18 microsteps - PWM steps between hardware microsteps
Mode3
movlw low (Tab72_Start+2)
movwf FSR1L
movlw HIGH (Tab72_Start+2) ; assembler knows to set high bit to access flash
movwf FSR1H
goto read_first
;Mode 2 - 6 microsteps - hardware microsteps only
Mode2
movlw low (Tab24_Start+2)
movwf FSR1L
movlw HIGH (Tab24_Start+2) ; high bit set to access flash
movwf FSR1H
goto read_first
;Mode 1 - half steps
Mode1
movlw low (Tab08_Start+2)
movwf FSR1L
movlw HIGH (Tab08_Start+2) ; high bit set to access flash
movwf FSR1H
goto read_first
;Mode 0 - full steps
Mode0
movlw low (Tab04_Start+2)
movwf FSR1L
movlw HIGH (Tab04_Start+2) ; high bit set to access flash
movwf FSR1H
; goto read_first
;read the first table element
read_first
moviw fsr1++ ; read 1st and advance pointer
movwf current23 ; save it
moviw fsr1-- ; read 2nd and reset pointer to start
movwf current13 ; save it
clrf count ; clear the timeout counter
clrf TMR1H ; (bank 0)
bsf T1CON,TMR1ON ; start the timer
bra pwm
;==============================================================================
; There have been no steps for a while so it's time to reduce power.
; - stop the timer
; - calculate reduced phase currents
; 100% -> 55%, 55% -> 25%, 25% -> 0%, 0% unchanged
; The phase currents are determined by 2 bits per phase.
; If the 2 bits are not 00, reduced current = full current - 1
; - return to fast PWM loop
; Next time a STEP occurs, the next phase currents will
; be read to automatically return to full power.
timeout
bcf T1CON,TMR1ON ; stop the timer
clrf count ; clear the timeout counter
lsrf current23,w ; shift each high bit to low bit position
iorwf current23,w ; join the 2 bits per current
andlw b'01010000' ; isolate the result: 01 if phase is 11, 10, or 01
subwf current23,f ; reduce each current iff not 00
lsrf current13,w ; same for other current
iorwf current13,w
andlw b'01010000'
subwf current13,f
LED_ON ; LED on for low power
bra pwm
;==============================================================================
; PWM - the fast pwm loop
;******************************************************************************
; NOTE!! we enter the code in the middle of the loop!
;-------------------------------------------------
; This function spends 2 time units at current23 and 1 time unit at current13.
; These target currents were set in the move_motor code.
; Actual is 6 clocks @ current13, 12 @ current23
; short long total clocks freq @ 32MHz osc
; 6 12 18 444 kHz
; This gives an average pwm current of 2/3 the way between
; current23 and current13.
;
; This code also checks for input changes and inactivity timeout.
; The routine is kept as short as possible to keep pwm frequency high, so it
; is easy to smooth in hardware by the ramping capacitors.
;
; Note: although this chip has LAT registers, PORTB is written to here
; in order to avoid bank switching. The entire port is written in one
; operation so RMW is not an issue. (Could point FSR0 at LATB instead.)
;
; IMPORTANT!
; This is carefully timed cycle accurate code and should not be changed!
;
; The 8/4 code from Roman Black's '16F628 version was supplied by Eric Bohlman
;-------------------------------------------------
pwm_loop
movf current13,w ; grab the 1/3 current and phase switching
movwf PORTB ; send to motor!
;-------------------
btfsc count,3 ; test for timeout
bra timeout
;-------------------
nop
nop
;-------------------
; (6 cycles)
; main entry! Better to enter at current23 for motor power.
pwm
movf current23,w ; grab the 2/3 current and phase switching
movwf PORTB ; send to motor!
;-------------------
; use TMR1 as base for timeout
; The following code expects TMR1IF to be bit 0 of PIR1
; If TMR1IF is set, clear it and increment timeout counter
movlw 1
andwf PIR1,w ; grab and isolate TMR1IF flag
xorwf PIR1,f ; clear flag iff it was set
addwf count,f ; inc count iff flag was set
; ;-------------------
movlw b'00000111' ; isolate STEP, DIR & ENABLE
andwf PORTA,w ; read port to test inputs
xorwf inputs_last,w ; xor to compare new inputs with last values
skpnz
bra pwm_loop ; z, inputs not changed, so keep looping
; (12 cycles)
;******************************************************************************
; NEW INPUTS input change was detected
;******************************************************************************
; when we enter here:
; - one or more PORTA inputs have just changed
; - WREG and inputs_last are part way through a swap (using a triple XOR)
;-------------------------------------------------
; must first swap, then test for interesting bits.
; ---x---- RA4 * mode bit1 ( 00=200 step 01=400 step
; ----x--- RA3 * mode bit0 10=1200 step 11=3600 step )
; -----x-- RA2 * enable (NewLin now 0 = enabled!)
; ------x- RA1 * direction
; -------x RA0 * step
; Only react to change in STEP, DIR or ENABLE (RA0,1,2)
; If ENABLE is high, turn off output drive.
; Otherwise, since something changed, reset the TIMEOUT
; If STEP just went high, we move the step (step++ or step--)
;-------------------------------------------------
xorwf inputs_last,f ; put new inputs into last
xorwf inputs_last,w ; and last into WREG
;test if enable has gone high
btfsc inputs_last,ENABLE ; still enabled? (Remember, active low)
bra phase_off ; nope, disabled, so release motors
;STEP or DIR changed so clear timeout
clrf count ; clear the timeout counter
clrf TMR1H ; (bank 0)
bsf T1CON,TMR1ON ; ensure timer is running
LED_OFF ; LED off for full power
;test for rising edge STEP
btfsc WREG,STEP ; was STEP low before?
bra pwm_loop ; wasn't low before so keep PWMing
btfss inputs_last,STEP
bra pwm_loop ; isn't high now so keep PWMing
;found new STEP so perform STEP++ or STEP--
btfss inputs_last,DIR
bra step_down ; if DIR low, STEP--
bra step_up ; else STEP++
;==============================================================================
; Initialize the hardware
;==============================================================================
setup
banksel LATB ; bank 2
clrf LATB ; ensure phase drive is off
clrf LATA
banksel OSCCON ; bank 1
movlw b'11110000' ; PLL on, 8MHz, Clock det by config
movwf OSCCON
movlw b'00111111'
movwf TRISA ; mostly input
clrf TRISB ; all output
movlw b'00000111' ; TMR0 prescaler 1:256
movwf OPTION_REG
clrf ADCON0 ; ensure ADC is off
clrf ADCON1
banksel ANSELA
clrf ANSELA ; all digital
clrf ANSELB ; all digital
banksel T1GCON ; bank 0
clrf T1GCON ; gate off
movlw b'00110000' ; source Fosc/4, 1:8 prescale, off
movwf T1CON
; banksel 0
movlw b'11000111' ; pu off,/,int,/,ps to T0, 1:256
movwf TMR0
clrf count+1
bsf INTCON,TMR0IE ; enable Timer0 interrupt
return
ERRORLEVEL -303
end
file: /Techref/io/stepper/linistep/Lini1826v031.asm, 21KB, , updated: 2015/11/18 13:21, local time: 2024/11/15 20:28,
|
| ©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/io/stepper/linistep/Lini1826v031.asm"> io stepper linistep Lini1826v031</A> |
Did you find what you needed?
|