View Full Version : Need more speed on steppers
02-07-2007, 04:09 PM
I have a Propeller driving 4 sets of step/direction off 4 cogs. The loops are constantly reading a position variable, comparing against the current positioin while in motion, changing accel and decel values in the waitcnt. There are 4 if/then decisions that handle ramping, stopping and going in the opposite direction etc, all done in Spin. The motor is 200 step resolution at 1/16 steps, so 3200 steps per rev. In each pass of the loop there are variables being added to or subtracted to for accel/decel purposes. Here is the essence of the motion, less the decisions being made each pass and leabing out quite a bit of info:
Pulsewidth := 400
Run := Position - Current position
dira[MDir] := 1
outa[Mstep] := 1
waitcnt[Pulsewidth + cnt]
outa[Mstep] := 0
waitcnt[accel + cnt]
accel := accel - aRate #> 400
Since the waitcnt value can't less than 400, the speeds are a somewhat too slow after all the calculations and decisions are made. Is assembly the only option to get higher speeds? Doubling what I am getting now would be good. 1/4, 1/2, and whole speeds are very noisy for the application, 1/16 is perfect.
Post Edited (originator) : 2/8/2007 10:44:51 AM GMT
02-07-2007, 05:27 PM
I am afraid that the only option will be to resort to assembly.
Personally played with the Propeller alot and tried various mehtods of getting max speed of pulses
and smooth ramping... SPIN lets me down on speed ..
Have not had the time personally to get it going in assembly ... but have seen a customer here in
OZ doing stuff with a stepper amplifier and the PROP that tells me anyhting is possible.
Now this customer is an engineer and he is very protective about his code and he is not going to share
it with me and he is also not happy that he can't protect his intellectual property simply by setting a protect fuse bit.
But from what I have seen the Propeller can do at least 3-4 axis and also possibly read feedback encoders as well.
Chip Gracey has indicated to me that A B phase type signal encoders can be sampled up to 1MHZ easy with ASM code.
Now sorry I can't help you with the code but it seems to me that there are alot of people that wish to do stuff like this.
Personally snowned under with jobs as it is..
Is there anybody out there in this wonderfull forum that we can all collectively reward for a task ... money money ..
Seriously guy's and girls is there somebody out there willing to take on the task on and get paid by people that wish to have this developed.. I know at least 3 people here in Australia that would be interested possibly in doing that as a joint venture.
Any takers or people interested in doing some serious development work.
If somebody in Australia is interested we would supply all the necessarry Propeller gear free of charge.
Ronald Nollet Australia
02-07-2007, 05:49 PM
For the ultimate in performance I think assembly along with the counters is the best bet. I had a stepper actuator going at a amazing speeds and could produce pulse rates much higher than it could handle and no doubt into the Mhz. I started a thread on this topic some time back. It is something I would like to finish doing but time is something I do not have a lot of. The main problem was not the basic algorithm but doing the pre-motion calculations which I never got around to mastering.
BTW Using counters two steppers per cog is probably feasible.
02-07-2007, 07:03 PM
Yep that's what I figured, 2 axis per cog.
I'm busy trying to learn assembly, lots of late night reading.
I think with assembly one cog could do 4 axis.
My need is for G-code running which can be done mostly one line at a time.
For multi axis robot control it gets a bit harder, just found out about the log, antilog tables and wondering if I could use them in the maths.
Been reading up on motion coding but the cog is a little bit different, trying to use it's unique features instead of copy everyone else's methods.
Hey Ron do I get a refund if I figure it out?
Good thing is once it is done as an object anyone can use it.
Got even less time these days as I now have a day job:)
02-07-2007, 07:38 PM
The good thing about using the counters is that you can do acceleration so easily. Normally you have to cheat or spend time working out the desired pulse rate for the next step in the ramp. As f is 1/T that means a division however because the counters take a frequency directly you just have to increment that on each step of the ramp by the same amount. The counters also take the overhead for pulse production away from the code, you have a fixed length loop running, on each loop you just modify the positon counter and update the FRQ register. If you set your loop at a rate of 1khz it gives you loads of time to do other things if required such as circular interpulation etc.
02-08-2007, 03:55 PM
Ok I think there could be some improvement if a few assembly lines can be inserted. Honestly I have no idea how assembly works, I'd be glad to study it if there were some systematic way to go about it. I have a few questions maybe someone with assembly experience can answer.
Can bits and pieces of assembly be intermingled with Spin? An example might be to replace the waitcnt[x+ cnt] code with something in assemly that could allow a shorter wait than 400? If a shorter wait for both step pin On and Off could happen that could buy a little time.
Post Edited (originator) : 3/13/2007 8:43:00 AM GMT
02-08-2007, 05:46 PM
Heres a simple bit of assembly I've written for a project I'm doing. It drives a 4 pin bipolar stepper motor, though it should also work with unipolar motors as I believe the switching sequence is the same. The code uses 4 pins connected to the inputs on an L293D motor driver chip. It can do either full step (always two coils on at any moment), or half step (alternates between 2 and 1 coils). Obviously with half step I get twice the resolution (800 steps per rev vs. 400 steps for my motors), but lower torque. Speed is fixed, and is controlled by the variable "wait_count". Anyway, heres the code :
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
' Assembly program
asm_entry mov output_pins,output_mask ' Set four pins, starting at base_pin
shl output_pins,base_pin ' for output. No error checking
mov count,cnt 'prepare for WAITCNT loop
:loop waitcnt count,wait_count 'wait for next CNT value (timing is determinant after WAITCNT)
base_pin long 2 ' First pin the motor is driven from
wait_count long 100000 ' NEVER go below 65000
output_mask long $0000000F ' 4 least significant bits
'drive_seq long $956A956A ' binary seq. 1001 0101 0110 1010 repeated twice - Full step mode
drive_seq long $915462A8 ' binary seq. 1001 0001 0101 0100 0110 0010 1010 1000 - Half step mode
count res 1
output_pins res 1
Edit: The line that says "NEVER go below 65000" is purely for my benefit. Any lower and my driver chip switches so quickly that the motor does not have enough time to move.
Post Edited (big_mark) : 2/8/2007 1:35:54 PM GMT
02-08-2007, 06:00 PM
Don't fear assembly, once you start to remember the commands and get to grips with the methods it is very enjoyable and soon you become addicted to the speed! The multi-core nature of the propeller makes assembly much easier on the prop than most processors.
Check out my first ever assembly program:
All it does is produce pulses with a set on and off time but it is quite well commented and also shows how you can pass data to the assembly program and get data from an assembly cog.
Assembly cannot be mixed with spin, it is all or nothing but you can have a core assembly cog doing the business getting directions from other cogs.
02-08-2007, 06:43 PM
I am open to learning it, but have yet to see a starting point for doing so. I actually just use step and direction and use a bi-polar driver by Allegro called the A3986. It has settings for 1, 1/2, 1/4 and 1/16, so the functionality of the loops are quite simple compared to Marks(Thanks Mark, I'll study that). It would be great if there were an assembly object that did the following from Spin commands, or was flexible to accommodate it. Maybe someone could suggest how easy or complex this is for a complete beginner to figure out. For CNC users this may not be suitable, as this is designed to run 4 steppers off a GUI sending out independant positions only. Graham, I'll study that pulse on off as well, that should be a great start from what I can tell. I am posting the Spin code that worksw great for the role, except for the speed.
1. Accept a fixed number of Steps to move and a Direction
2. Accept an Accel starting time parameter (for simplicity, think waitcnt[AccelTime + cnt], that establishes the time to wait prior to the off-state of Step)
3. Accept an AccelRate of change parameter (Accel = Accel - AccelRate - Motion starts at a fixed speed of Accel, and increases speed as Accel is reduced by AccelRate)
4. Accept a Decel parameter
5. Accept a DecelRate
6. Constantly look at the Position/Direction to see if it has changed. If direction has changed, decel by X steps(Reverse Steps parameter), based on Decel and DecelRate, then Reverse startin with Ramp based on Accel and AccelRate. If Direction is same, and Position has changed to farther position, add travel to the loop. If Position is changed to shorter, and Direction is same, then decel earlier
7. Accept a parameter for off state Pulsewidth, I use the waitcnt for the on the Step of state as a fixed value, and use the on state time to adjust speed.
Post Edited (originator) : 2/8/2007 11:01:27 AM GMT
02-09-2007, 12:01 AM
Let me first clear something up. You cannot mix and match assembly and spin but you can have an object that contains both. The asm gets loaded into a new cog by itself, the spin functions are run in the cog that calls them. Check out mouse.spin it is an excellent example.
Essentially you could have a spin function to load parameters into the hub memory. The assembly program could sit waiting for one of the global variables to change, signalling that it should actually do something, at that point it would load the parameters such as distance etc and start producing the steps until complete. It looks like you want it to be able to reverse direction mid move, that's OK, just make sure it checks the state of the direction variable on a regular basis (every step is not necessary).
Once a move was complete it could reset the "go flag" so your main program can see that it has finished. If you want the main program to be able to plot the progress properly then you just make the position a global variable.
I notice you just decrement the wait time to cause the ramping acceleration, this actually gives you non linear acceleration, not a problem as long as you don't have too many steps in the ramp. Otherwise it will tend to start really slow and then get exponentially faster up to the maximum.
1-How much speed do you need from the stepper ?
2-Do you really need 3200 steps / revolution ? (It's a relative high resolution for a stepper project).
3-It's difficult for me o understand your code, but, I can't see a piece of it, where you leave the stepper running at a fixed speed. (it seems to be, that all the time is accelerating and decelerating).
4-The problem is not the waitcnt command, at a value of "500 + cnt" you could have about 160_000 Hz without considering the time wasted by the rest of the rutine, that is a high speed for the stepper (still in 3200 steps/rev).
5-My suggest, is that you must try to debug the code as possible, to get it faster. What you do in that way, will produce what you need.
6-Let's see my stepper code again, I can get 1500 RPM in 200 steps/rev with that, and with a minimal effort.
7-Check the maximun frequency that you could get with spin, doing a simple loop (without accel and decel) at a fixed value of "xxxx + cnt" and repeat it.
02-24-2007, 02:43 PM
Could you use the output of a par in serial out shift register to drive your motors?