frequency to timeperiod conversion in assembly
Graham Stabler
Posts: 2,510
I am writing a 3-axis motion object for stepper motors that will run in a single cog. Things were going well after some initial confusion when using test and cmp until I started to play with the acceleration part.
I want the frequency of the pulses sent to the stepper motors to ramp up, I'm using a fixed length loop (fixed using waitcnt) and essentially I need to decrease the number of these loops that occur between a pin being toggled. I started by just decrementing the timeperiod (in loops) between pulses but then realized my mistake, the time period is the reciprocal of the frequency and so it not a linear function. Essentially I need to be able to take a frequency and reciprocate it to get a time period.
But how can I do this in assembly?
An initial thought I had would be to define the max frequency as some number and then divide twice this number by the requested frequency. So for example if I set the max frequency to be 255 and then set the requested frequency to 255 I would get (255*2)/255 = 2 and that would probably be the min time period (one loop for the pulse and one for the gap). There would then be a max time period of 255*2. Obviously more bits gives a greater range.
So if the above is not a brain fart do I just need to do binary long division in assembly or am I missing something completely??
Thanks
Graham
I want the frequency of the pulses sent to the stepper motors to ramp up, I'm using a fixed length loop (fixed using waitcnt) and essentially I need to decrease the number of these loops that occur between a pin being toggled. I started by just decrementing the timeperiod (in loops) between pulses but then realized my mistake, the time period is the reciprocal of the frequency and so it not a linear function. Essentially I need to be able to take a frequency and reciprocate it to get a time period.
But how can I do this in assembly?
An initial thought I had would be to define the max frequency as some number and then divide twice this number by the requested frequency. So for example if I set the max frequency to be 255 and then set the requested frequency to 255 I would get (255*2)/255 = 2 and that would probably be the min time period (one loop for the pulse and one for the gap). There would then be a max time period of 255*2. Obviously more bits gives a greater range.
So if the above is not a brain fart do I just need to do binary long division in assembly or am I missing something completely??
Thanks
Graham
Comments
I went back and looked at a 2-axis stepper driver I did for the SX to see how I did it. (It's been a few years ago.) For the ramping, I just used a lookup table. The advantages are no computing reciprocals on the fly, and you can tailor the ramp profile to any shape you want that's appropriate for the motors you're using. Plus, if you switch motors, all you have to change is the lookup table.
OTOH, it may not even be necessary for the velocity ramp to be linear, and you could just linearly decrease the time intervals instead of increasing the velocity.
-Phil
If you linearly increase the time period (which I was doing before I realized) you end up a VERY low frequency to begin with followed by an exponential increase in frequency. It was quite fun to watch on a flashing LED but totally unsuitable for my applications as it will increase the amount of time it takes to get up to the max speed by a large factor.
Graham
You could have the software generate a lookup table at startup, based on the user's data. That way you retain the flexibility of a parametric system without the necessity of realtime computation. Plus, the table can be generated in Spin before starting the assembly cog.
-Phil
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Tracy,
The first issue is working out how to do the long division, that comes down to me being a bit rusty but that's not such a problem but yes because my pulse production method has a timing resolution of one loop, the less I have to do in the loop the better. I am always suprised by tricks that can be played with binary so thought it might be worth asking. If I have to do much more than I am doing in the loops then the whole thing is a non starter, I want pulse frequencies of at least 20khz. I should probably try and put some numbers on the resolution I want, it will depend on the amount of staircasing in velocity I am prepared to accept as well as some other stuff, still thinking and sketching oh and learning spin/asm.
Graham
a 32 bit dividend with a 16 bit divisor to get a 16 bit quotient and remainder.
This one uses a 32 bit dividend and a 32 bit divisor to get a 32 bit quotient and
remainder. This is useful when you need to use a divisor more than 16 bits or
expect a quotient more than 16 bits.
It's about 170 instruction times or 680 clock cycles (under 8.5us at 80MHz)
Post Edited (Mike Green) : 8/13/2006 12:45:18 AM GMT
Graham
(the Propeller uses base-2 exponents, aka·Log2(x) and 2^x·so if you need say Log10(x) it takes a another lookup and a division)
ok the formula from my cheet sheet· Log2(M/N) = Log2(M) - Log2(N).· {also Log2(M*N) = Log2(M) + Log2(N), and Log2(M^P) = P*Log2(M) }
so·· M/N = 2^[noparse][[/noparse] log2(M) - Log2(N) ]
so 3 table lookups, a subtraction, and some bit twiddling and you've got the division you need.· (at a reduced precision) The details of how to use these lookup tables is located·from page 13 to 15·of the·"Propeller Guts.pdf" that's floating arround of this forum.· (i've also attached it)·
Helpfull yes?
Marty
As the tables are in the ROM and this is shared I'll have to wait to get access to it, this might slow things down a little too much but I need to make comparisons and there is always the possibilty of downloading the bits I need before a move.
I think I definately need to decide on the frequency resolution I need, from that I can work out the best way of doing this given the selection of possibilities I now have.
Graham