[In my application] 5.25" floppy drive steppers are connected at each linistep driver. They run at 130 mA current each. I have used 10k pulldown resistors at the input instead of the 390 ohm resistors. The motors run smootly at about 2 rpm with 100uF ramping capacitors. I am working at an overvoltage circuit (30V,0.7A) to get more than 6 revs/sec. It is for use of a dual axis telescope drive (1:3000 gear ratio). I have modified the firmware to support only the microstepping mode and your special halfstepping mode [for use with Mel Bartels scope.exe^] Microstepping is very accurate and what is more important, there are absolutely NO vibrations, which can be even more distracting than rough step sizes.
Here is the source code of the mod. I have also included a ready made hex file for burning on a 16F84A.
The differences between the original and the modified firmware are as follows:
When you switch from the microstep mode to the halfstep mode, it always starts at the position between the fullsteps, because both coil A and B are on. Depending on where we have left the microstep position, we gain or lose one step. This has no great effect on the application here, because we only switch after long slews. Beside this, there is a gear of 1:3000 at the stepper shaft in this application. So there is no great loss. However, users should be generally aware of this.
I have [also] made a standalone controller based on the 16F84. It runs at 12 Mhz. It will drive an alt-azimuth nicely. It has quite a lot of features:
Kind regards,
Kai Ries
linistpv1.asm
;****************************************************************************** ; ; LiniStepper v1.1s ; ; PIC 16F84A code ; ; Copyright Aug 2002 Roman Black www.romanblack.com ; ; PIC assembler code for the LiniStepper stepper motor driver board. ; 400/3600 steps ; ; v1.0 Seems to be working ok for now, few minor things need improving; ; * touch up phase switching for direction -> 0 ; * table system is messy, can reduce in size a LOT if needed ; * low-power mode doesn't microstep, only halfstep ; * no easy way to step motor from within PIC software ; ; (set mplab TABS to 5 for best viewing this .asm file) ; ; ; v1.1s Modifications for use with Mel Bartels scope.exe or the LiniStar controller ; ; v1.1 has been slightly modified to meet minimal telescope driving requirements, that is ; a fast quarterstepmode and a 18th microstepmode. The two mode inputs can be used for ; general purposes. ; General overview of program loop: ; move_motor-->power variable check-->high/low power PCL-table--->pwm--->new_inputs-->move_motor---| ; |-- <--| | ; |<--- <--- ; In the routine "move_motor" the PCL 'jump variable' steptemp is calculated and the corresponding ; phase variable. The "pwm" routine has been left, when an input change has been detected. It´s timing ; is critical, since he currents are modulated this way. ;============================================================================== ; 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 <p16f84A.inc> ; processor config IFDEF __16F84A __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ENDIF ;============================================================================== ; Variables here ;------------------------------------------------- IFDEF __16F84A #define RAM_START 0x0C #define RAM_END RAM_START+d'68' ; 16F84 has only 68 ram ENDIF ;------------------------------------------------- CBLOCK RAM_START status_temp ; used for int servicing w_temp ; used for int servicing step ; (0-71) ustep position! steptemp ; for calcs steplp ; (0-3) half step position! phase ; stores the 4 motor phase pins 0000xxxx current1 ; for current tween pwm current2 ; for current tween pwm inputs ; stores new input pins inputs_last ; stores last states of input pins ENDC ;------------------------------------------------- ; PIC input pins for porta, these are the bits numbers #define STEP 0 ; / = move 1 step, \=do nothing #define DIR 1 ; lo= cw, hi=ccw #define POWER 2 ; lo=low power, hi=full power #define INDEX 3 ; index signal ;------------------------------------------------- ; Custom instructions! #define skpwne skpnz ; after subxx, uses zero #define skpweq skpz ; after subxx, uses zero #define skpwle skpc ; after subxx, uses carry #define skpwgt skpnc ; after subxx, uses carry ;============================================================================== ; CODE GOES HERE org 0x0000 ; Set program memory base at reset vector 0x00 reset goto main ; ;============================================================================== move_motor ; goto label ; find which of the 4 ranges we are in movf step,w ; get step movwf steptemp ; store as working temp movf steptemp,w ; sublw d'35' ; sub to test skpwle ; goto half_hi ; wgt, steptemp is 36-71 (upper half) ;------------------------- half_low ; wle, steptemp is 0-35 movf steptemp,w ; sublw d'17' ; sub to test skpwle ; goto range1 ; wgt range0 ; wle movlw b'00000101' ; 0101 = A+ B+ goto phase_done ; range1 movlw b'00001001' ; 1001 = A- B+ goto phase_done ; ;------------------------- half_hi ; steptemp is 36-71 ; NOTE! must subtract 36 from steptemp, so it ; will become 0-35 and ok with table later! movlw d'36' ; subtract 36 from steptemp, subwf steptemp,f ; (now steptemp is 0-35) ; now find the range movf steptemp,w ; sublw d'17' ; sub to test skpwle ; goto range3 ; wgt range2 ; wle movlw b'00001010' ; 1010 = A- B- goto phase_done ; range3 movlw b'00000110' ; 0110 = A+ B- phase_done ; note! steptemp is always 0-35 by here movwf phase ; store phase values ;------------------------------------------------- btfss inputs,POWER ; select table to use, check input here goto table_lowpower ; skip this if POWER pin is high ;------------------------------------------------- ; HIGH POWER TABLE ; the PCL table is used, we should make sure that a valid value is sent to the PCL counter, otherwise ; it jumps in arbitrarily place in the program ;------------------------------------------------- table_highpower ; movf steptemp,w ; add steptemp to the PCL addwf PCL,f ; ; here are the 36 possible values; ;------------------------- goto st00 ; * (hardware 6th steps) goto st01 ; (pwm tween steps) goto st02 ; (pwm tween steps) goto st03 ; * goto st04 ; goto st05 ; goto st06 ; * goto st07 ; goto st08 ; goto st09 ; * goto st10 ; goto st11 ; goto st12 ; * goto st13 ; goto st14 ; goto st15 ; * goto st16 ; goto st17 ; goto st18 ; * goto st19 ; goto st20 ; goto st21 ; * goto st22 ; goto st23 ; goto st24 ; * goto st25 ; goto st26 ; goto st27 ; * goto st28 ; goto st29 ; goto st30 ; * goto st31 ; goto st32 ; goto st33 ; * goto st34 ; goto st35 ; table_lowpower ; movf steplp,w ; add this step variable to the PCL addwf PCL,f ; ; here are the 4 possible values; goto lp00 ; 55,25 (100,45) current low (high) goto lp09 ; 25,55 (45,100) goto lp18 ; 25,55 (45,100) goto lp27 ; 55,25 (100,45) st00 ; (6th step) movf phase,w ; get coil phasing (is 0000xxxx) iorlw b'11000000' ; set currents; 100,0 movwf current2 ; movwf current1 ; goto pwm ; st01 movf phase,w ; get coil phasing iorlw b'11000000' ; set 100,0 movwf current2 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current1 ; goto pwm ; st02 movf phase,w ; get coil phasing iorlw b'11010000' ; set 100,25 movwf current2 ; movf phase,w ; iorlw b'11000000' ; set 100,0 movwf current1 ; goto pwm ; ;------------------------- st03 ; (6th step) movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current2 ; movwf current1 ; goto pwm ; st04 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current2 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current1 ; goto pwm ; st05 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current1 ; goto pwm ; ;------------------------- st06 ; (6th step) movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movwf current1 ; goto pwm ; st07 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current1 ; goto pwm ; st08 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current1 ; goto pwm ; ;------------------------- st09 ; (6th step) movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movwf current1 ; goto pwm ; st10 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current1 ; goto pwm ; st11 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current1 ; goto pwm ; ;------------------------- st12 ; (6th step) movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movwf current1 ; goto pwm ; st13 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current1 ; goto pwm ; st14 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current1 ; goto pwm ; ;------------------------- st15 ; (6th step) movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movwf current1 ; goto pwm ; st16 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movf phase,w ; iorlw b'00110000' ; set 0,100 movwf current1 ; goto pwm ; st17 ; movf phase,w ; iorlw b'00110000' ; set 0,100 movwf current2 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current1 ; goto pwm ; ;------------------------- ;------------------------- st18 ; (6th step) movf phase,w ; iorlw b'00110000' ; set 0,100 movwf current2 ; movwf current1 ; goto pwm ; st19 ; movf phase,w ; iorlw b'00110000' ; set 0,100 movwf current2 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current1 ; goto pwm ; st20 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movf phase,w ; iorlw b'00110000' ; set 0,100 movwf current1 ; goto pwm ; ;------------------------- st21 ; (6th step) movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movwf current1 ; goto pwm ; st22 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current2 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current1 ; goto pwm ; st23 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movf phase,w ; iorlw b'01110000' ; set 25,100 movwf current1 ; goto pwm ; ;------------------------- st24 ; (6th step) movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movwf current1 ; goto pwm ; st25 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current2 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current1 ; goto pwm ; st26 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movf phase,w ; iorlw b'10110000' ; set 55,100 movwf current1 ; goto pwm ; ;------------------------- st27 ; (6th step) movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movwf current1 ; goto pwm ; st28 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current2 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current1 ; goto pwm ; st29 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movf phase,w ; iorlw b'11110000' ; set 100,100 movwf current1 ; goto pwm ; ;------------------------- st30 ; (6th step) movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movwf current1 ; goto pwm ; st31 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current2 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current1 ; goto pwm ; st32 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current2 ; movf phase,w ; iorlw b'11100000' ; set 100,55 movwf current1 ; goto pwm ; ;------------------------- st33 ; (6th step) movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current2 ; movwf current1 ; goto pwm ; st34 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current2 ; movf phase,w ; iorlw b'11000000' ; set 100,0 movwf current1 ; goto pwm ; st35 ; movf phase,w ; iorlw b'11000000' ; set 100,0 movwf current2 ; movf phase,w ; iorlw b'11010000' ; set 100,25 movwf current1 ; goto pwm ; ; high power table done! ;------------------------------------------------- ; next are the 4 code fragments for the low power table. ;------------------------------------------------- lp00 ; movlw b'10010101' ; movwf current2 ; movwf current1 ; goto pwm ; lp09 ; movlw b'01101001' ; movwf current2 ; movwf current1 ; goto pwm ; lp18 ; movlw b'01101010' ; movwf current2 ; movwf current1 ; goto pwm ; lp27 ; movlw b'10010110' ; movwf current2 ; movwf current1 ; goto pwm ; ;------------------------------------------------- ;------------------------------------------------------------------------------ ;****************************************************************************** ; Main ;****************************************************************************** ; ;------------------ main ; goto label ;------------------ ;--------------------------------------------- ; do initial setup for ports and ints and stuff call setup ; this is our only proper call... ; it is called only once, and does not really need ; to be a function. ;--------------------------------------------- ; main operating loop is here. ;--------------------------------------------- goto move_motor ; will set the motor to step 0, ; and loop permanently from there ;--------------------------------------------- goto main ; safe loop, should never get here anyway. ;****************************************************************************** ; NEW INPUTS input change was detected ;****************************************************************************** ; ;------------------ new_inputs ; goto tag ;------------------ ;------------------------------------------------- ; when we enter here: ; * one or more PORTA inputs have just changed ; * inputs_last contains last PORTA inputs values ; * inputs contains new PORTA inputs values ;------------------------------------------------- ; must first detect which input pins changed. ; ---x---- RA4 *future use ; ----x--- RA3 *future use ; -----x-- RA2 * power, low=hi torque half stepping, hi=3600 mode ; ------x- RA1 * direction ; -------x RA0 * step ; if step went hi, we move the step (step++ or step--) ; if step went low: ; ignore change in direction pin ; ignore change in power pin ; (all pins besides step are handled automatically in move_motor) ;------------------------------------------------- movf inputs,w ; xor to compare new inputs with last values xorwf inputs_last,f ; now inputs_last has the diff. btfss inputs_last,STEP ; test if step input changed goto ni_end ; ; step input changed! btfss inputs,STEP ; test if change was lo-hi or hi-lo goto ni_end ; hi-lo, so ignore btfss inputs,POWER ; test power mode bit goto mode_lo ; ; 3600 mode (72/1) ; each step is 1 btfss inputs,DIR ; test direction input goto m36_up ; m36_down decf step,f ; step-- btfss step,7 ; test for roll under <0 goto ni_end ; ok ; rolled under! movlw d'71' ; force to top step (72-1) movwf step ; goto ni_end ; m36_up incf step,f ; step++ movf step,w ; test for roll over >71 sublw d'71' ; sub to test skpwle ; clrf step ; wgt, rolled over so force to step 0 goto ni_end ; ;------------------------------------------------- ;For low power mode there are 4 entries only, so this is easy mode_lo btfss inputs,DIR ; test direction input goto m40_up m40_down decf steplp,f ; steplp-- btfss steplp,7 ; test for roll under <0 goto ni_end ; ok ; rolled under! movlw d'3' ; force to top step (4-1) movwf steplp ; goto ni_end ; m40_up incf steplp,f ; steplp++ movf steplp,w ; test for roll over >3 sublw d'3' ; sub to test skpwle ; clrf steplp ; wgt, rolled over so force to step 0 goto ni_end ; ni_end movf inputs,w ; save a copy of the inputs movwf inputs_last ; goto move_motor ; go and make it all happen ;------------------------------------------------------------------------------ ;****************************************************************************** ; PWM is the fast pwm loop ;****************************************************************************** pwm_loop ; first output current1 to motor movf current1,w ; get currents and phase switching movwf PORTB ; send to motor! nop ; timing delay nop ; ; (4 cycles) ;------------------------- pwm ; main entry! ; better to enter at current2 for motor power. ; now output current2 movf current2,w ; movwf PORTB ; send to motor! nop ; safe wait 250nS ; now test input pins movf PORTA,w ; get pin values from port xorwf inputs_last,w ; xor to compare new inputs with last values skpnz goto pwm_loop ; z, inputs not changed, so keep looping ; (8 cycles) ;------------------------------------------------- ; nz, one or more input pins have changed! xorwf inputs_last,w ; restore xored value back to the orig inputs value movwf inputs ; goto new_inputs ; ;------------------------------------------------- ;------------------------------------------------------------------------------ ;****************************************************************************** ; SETUP sets port directions and interrupt stuff etc, ;****************************************************************************** ; NOTE!! is the only proper funtion, is done before other activity ;------------------ setup ; routine tag ;------------------ ; OPTION setup movlw b'10000010' ; banksel OPTION_REG ; go proper reg bank movwf OPTION_REG ; load data into OPTION_REG banksel 0 ; ;------------------------------------------------- ; PORTB pins direction setup ; 1=input, 0=output clrf PORTB ; ; movlw b'00000000' ; all 8 portb are outputs ; banksel TRISB ; go proper reg bank movwf TRISB ; send mask to portb banksel 0 ; ;------------------------------------------------- ; PORTA pins direction setup ; 1=input, 0=output clrf PORTA ; ; NOTE!! only three PORTA pins are used as inputs now movlw b'00000111' ; ; ---x---- ; RA4 ; ----x--- ; RA3 ; -----x-- ; RA2 POWER ; ------x- ; RA1 DIRECTION ; -------x ; RA0 STEP banksel TRISA ; go proper reg bank movwf TRISA ; send mask to porta banksel 0 ; ;------------------------------------------------- movlw 0x00 ; set up PCLATH for all jump tables on page 0 movwf PCLATH ; (all tables are in move_motor) ;------------------------------------------------- ; CLEAR RAM! for lower bank movlw RAM_START ; first byte of ram movwf FSR ; load pointer ram_clear_loop clrf INDF ; clear the ram we pointed to incf FSR,f ; inc pointer to next ram byte movf FSR,w ; get copy of pointer to w sublw RAM_END ; test if PAST the last byte now skpweq ; goto ram_clear_loop ; ;------------------------------------------------- ; here we can set the user variables and output pins movlw 0x00 ; for step 0 of 0-71 movwf step ; loaded ready for jump table movf PORTA,w ; get initial value for inputs movwf inputs ; movwf inputs_last ; ;------------------------------------------------- ; set up INTCON register last movlw b'00000000' ; set the bit value ; x------- ; bit7 GIE global int enable, 1=enabled ; -x------ ; bit6 EE write complete enable, 1=en ; --x----- ; bit5 TMR0 overflow int enable, 1=en ; ---x---- ; bit4 RB0/INT enable, 1=en ; ----x--- ; bit3 RB port change int enable, 1=en ; -----x-- ; bit2 TMR0 int flag bit, 1=did overflow and get int ; ------x- ; bit1 RB0/INT flag bit, 1=did get int ; -------x ; bit0 RB port int flag bit, 1=did get int movwf INTCON ; put in INTCON register ;------------------------------------------------- return ; ;------------------------------------------------------------------------------ end
file: /Techref/io/stepper/linistep/mod-maxries.htm, 23KB, , updated: 2007/4/24 16:29, local time: 2024/12/26 22:55,
13.58.221.124: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://linistepper.com/Techref/io/stepper/linistep/mod-maxries.htm"> Linistepper, Open Source Stepper Controller Modifications, Stepper motor, Kai Ries</A> |
Did you find what you needed? |