RunDaStepperMotor
idbruce
Posts: 6,197
Hello Everyone
My previous stepper driver, PulseTheStepPin was quite difficult to understand, even for the guy who wrote it So out of necessity for a specific requirement, and to create an easier to understand stepper driver, I have written a new driver for everyone to play with. It is full of documentation and comments to help assist in understanding the code and how it can be altered to obtain various ramping profiles.
I hope you enjoy it.
Bruce
My previous stepper driver, PulseTheStepPin was quite difficult to understand, even for the guy who wrote it So out of necessity for a specific requirement, and to create an easier to understand stepper driver, I have written a new driver for everyone to play with. It is full of documentation and comments to help assist in understanding the code and how it can be altered to obtain various ramping profiles.
{ Copyright 2011. Bruce Drummond. You may use and modify this software without any restriction. Please note that the following settings are for a GeckoDrive G251X microstepping driver in combination with an Applied Motion HT23-400 high torque stepper motor. You may have to alter these settings to suit your particular driver, motor, and needs. The main settings for affecting motor operation are: START_STOP_SPEED and RAMP By altering these two settings, a person can achieve many different ramping profiles. So go ahead and experiment a little and have some fun. With a little creativitiy, this software can be modified to run for a specified number of steps and with a specified direction of rotation. If you create a full blown stepper driver from this sample code, it is recommended to set up constants for all your pins and settings. Additionally, if you create some useful code with this sample, please share it in the forum or OBEX. } CON 'Multiply the external frequency by 16. _CLKMODE = XTAL1 + PLL16X 'External crystal of 5MHz. _XINFREQ = 5_000_000 'Establish the clock frequency so that a couple constants may 'be declared in the CON block. CLK_FREQ = ((_CLKMODE - XTAL1) >> 6) * _XINFREQ 'The GeckoDrive G251X microstepping driver requires a minimal 'pulse width of 1us, so establish this setting. HIGH_PULSE_WIDTH = CLK_FREQ / 1_000_000 'The code needs a certain amount of time to operate, so set 'this. Additonally, this setting can be used to control the 'maximum speed of the motor. Just remember that the maximum 'execution speed takes priority over maximum speed of the 'motor, otherwise the code will falter. MAX_EXE_MOTOR_SPEED = CLK_FREQ / 20_000 'Set the pin number for the pushbutton PUSHBUTTON_PIN = 7 'Set the pin numbers for the step, direction, and disable pins 'for the stepper driver. DIRECTION_PIN = 3 STEP_PIN = 4 DISABLE_PIN = 5 'This setting is the starting and stopping speed of the 'motor. Please note that the RAMP will be subtracted from 'this setting during the first loop. Higher settings decrease 'initial startup speed. START_STOP_SPEED = 50_000 'This setting is the ramp incrementor/decrementor, and it will 'affect just how fast the motor ramps up to top speed and 'ramps down until the motor stops. RAMP = 25 PUB Main 'Set the direction of the pushbutton pin as an input. DIRA[PUSHBUTTON_PIN]~ 'Set the directions of the direction, step, and disable pins 'for the stepper driver as outputs. DIRA[STEP_PIN]~~ DIRA[DIRECTION_PIN]~~ DIRA[DISABLE_PIN]~~ 'Enable the motor. OUTA[DISABLE_PIN]~~ 'Set the direction of rotation. OUTA[DIRECTION_PIN]~ 'Loop until there is input on the PUSHBUTTON_PIN and then stop the iteration. REPEAT IF INA[PUSHBUTTON_PIN] QUIT 'Start motor operation. RunDaStepperMotor(STEP_PIN, START_STOP_SPEED, MAX_EXE_MOTOR_SPEED, RAMP) PUB RunDaStepperMotor(StepPin, CycleOffset, MaxExeMotorSpeed, RampIncDec) | Ramps, Counter 'Set up the CTRMODE of Counter A for NCO/PWM single-ended. CTRA[30..26] := %00100 'Set the output pin for Counter A. CTRA[5..0] := StepPin 'Set the value to be added to PHSA with every clock cycle. FRQA := 1 'Set APIN as an output. DIRA[StepPin]~~ 'Get the current System Counter value. Counter := CNT 'Ramp up motor speed REPEAT WHILE CycleOffset => MaxExeMotorSpeed 'Send out a high pulse on the step pin for the desired duration. PHSA := -HIGH_PULSE_WIDTH 'Wait for a specified period of time before send sending another 'high pulse to the step pin. WAITCNT(Counter += CycleOffset -= RampIncDec) Ramps++ 'Please note that the pushbutton will be retained to start stepper 'operation, however, the pushbutton used in the following loop will 'be changed to a detent switch at a later point in time to permit a 'more automated process. 'Run the motor at full speed until we get contrary input and then 'stop this iteration. REPEAT WHILE NOT INA[PUSHBUTTON_PIN] 'Send out a high pulse on the step pin for the desired duration. PHSA := -HIGH_PULSE_WIDTH 'Wait for a specified period of time before send sending another 'high pulse to the step pin. WAITCNT(Counter += CycleOffset) 'Ramp down the motor and come to a stop. REPEAT Ramps 'Send out a high pulse on the step pin for the desired duration. PHSA := -HIGH_PULSE_WIDTH 'Wait for a specified period of time before send sending another 'high pulse to the step pin. WAITCNT(Counter += CycleOffset += RampIncDec) 'Return to the Main function and wait for a button press to start 'the process all over again. Main
I hope you enjoy it.
Bruce
Comments
You are welcome, thanks for saying thank you. I am sure you will have to modify the settings a little to work with that driver, but the basic building blocks are in that code. If you have any problems, just let me know.
Bruce
Additionally, this version has just a few more notes added to clairfy some of the settings.
Bruce
It implements step/direction in software and could run multiple steppers in 1 COG with a proper motion controller manager.
To be able to achieve higher speeds with stepper motors, you must have some type of ramping system. Just a piece of advice.
Bruce
Here is a new version that adds a different twist to the program.
This program runs on my new machine, and on this machine, I always want the stepper motor to return to it's starting position. In my case, this is actually quite simple, since the motor's intended purpose is to repeatedly rotate a cam a 360 degrees. This version simply ensures that the motor stops on a completed revolution.
It is noteworthy to mention, that the added expressions and comparisons made it necessary to lengthen the execution speed of the program. However, this was a trait that I needed for my machine, so the speed of the machine must suffer. I am adding this version just in case someone else might have a similar application for this driver.
Bruce
Thanks for the GREAT work on this controller. I'm very new to spin, but I must say this was very easy to work with and understand. I'm developing an application that will let me control holiday props from DMX signals. In my application, I have a variable distance that I'd like to control with DMX. For some functions, I may do cyclical motions and others might simply move in one direction of variable length and speed. I'm using your driver as the basis. I'm essentially modifying the ramp rate as a factor of both speed and calculated distance to travel. This gives me a nice smooth acceleration profile that meets the other movement constraints.
While testing, I found that a fixed speed with a fixed ramp rate would yield a different speed as the movement distance changed. For example, if I allowed the motor to operate over a very wide range, I would get one speed. If I shortened the range of movement allowed, the speed would increase rather dramatically.
The code has three steps that control the ramping of the motor. The problem code is in the steady-state portion. Specifically the waitcnt does not account for the RampIncDec that is accounted for in both of the ramp up and ramp down phases of the motor speed profile. I have modified the waitcnt to read:
WAITCNT(Counter += (CycleOffset+RampIncDec))
This seems to provide a less noticeable jump to the steady-state condition as well as a steady speed profile across a wide range of travel distances.
Again, I'm VERY new to this as well as motor control, so if I've overlooked something or if I'm out of line, don't hesitate to let me know! Thank you so much for sharing this code. Once I get my object a little more refined, I'll post an update / object for DMX controlled stepper motors.
This stepper is an offshoot of another stepper driver named PulseTheStepPin. In it's current state, PulseTheStepPin is very hard to understand, and I was going to rewrite it to be more in line with this driver for easier comprehension. However, since I never got around to rewriting it, you may want to read this thread also.
http://forums.parallax.com/showthread.php?132373-PulseTheStepPin-revisted-Questions-answers-problems-solutions
Thanks for the post. It is nice to know that someone is putting it to good use.
Bruce
Your post came right after an update from me, so you may also want to look at Post #11.
Thank you as well for the thanks.
Bruce
Since you guys are messing around with stepper drivers, I put together a real world example of settings and calls to the PulseTheStepPin driver, as shown below and attached.
For the last several hours, I have been working on the culmination of my stepper drivers. PulseTheStepPin has been simplified to be more comprehensive and more in line with RunDaStepperMotor. The documention has been altered to provide a more complete understanding. Needless to say that there have been quite a few modifcations to the software itself as well as the documentation.
The most recent version of my work should be released approximately 12:00 PM, Feb. 28, 2012 within the Propeller forum, providing it is fully functional at that time. It will be entitled StepperDriveErz. You may want to keep an eye open for this posting to obtain the latest release.
Bruce