; ****************************************************************************** ; ; 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 14:21, local time: 2024/8/14 22:16,
3.23.102.99:LOG IN
|
©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://piclist.com/Techref/io/stepper/linistep/Lini1826v031.asm"> io stepper linistep Lini1826v031</A> |
Did you find what you needed? |
![]() o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. |
Welcome to piclist.com! |
.