Best method for generating stepper motor clock

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Best method for generating stepper motor clock

4,079 Views
philliproth
Contributor I

It's a simple thing I've done on other processor families but seems there are are many ways to generate a simple stepper motor clock to control accell/cruise and decell on the 52259. This is just a simple stepper clock and not phase control but don't want to hack something in when there's a simple way to do it.

Accell and decell profiles are fixed so ideally I'd generate a table of timer values, interrupt on each clock output to track position, then output the next timer value to accell or decell or just let the output run to maintain cruise, kinda stepper motor control 101.

Thought PWM would be the best but now thinking about using a timer output and interrupting on falling edge to have ample time to load a new value for the next leading edge but it's not double buffered and I'd have to subtract the current value from the target value to avoid clock jitter caused by ISR latency, etc..etc..etc.which sounds like a mess.

Pretty sure this has been done at least a few hundred times before and just want to leverage some knowledge, possibly some code

Thanks

0 Kudos
9 Replies

3,273 Views
TomE
Specialist II

There's nothing specific to driving stepper motors in this, but there might be some useful low level driver code in here:

https://www.nxp.com/downloads/en/snippets-boot-code-headers-monitors/MCF5225x_SAMPLE_CODE.zip

Here's a Robot with four stepper motors, but since that might be more than the MCF5225x can drive, it might be using external motor controller chips. There might be some useful code associated with this:

https://www.nxp.com/products/sensors/motion-sensors/accelerometers-for-iot/nxp-mechatronics-robot:FS...

Here's a Video telling you how to use NXP/Freescale products that might have some references:

https://www.nxp.com/video/motor-control-application-overview:WBNR-FTF2008-MOTORCTRL-PART1-VID

Here's an old set of Fact Sheets that mentions Stepper Motors, but only for the ETPU in the MCF523x:

https://www.nxp.com/docs/en/brochure/COLDFIREECPAK.pdf

Here's information on the Motor Control units in the Tower System, and how to use them with Kintetis CPUs. Not much use - it uses a separate SPI-connected motor controller chip:

https://www.nxp.com/support/developer-resources/hardware-development-tools/tower-development-boards/...

Here's all the Motor Control stuff, but nothing remaining there for Coldfire:

https://www.nxp.com/applications/solutions/internet-of-things/smart-things/motion-and-motor-control:...

Here's the equivalent page from 2011 when the Motor Control section details Coldfire. The links to the specific pages don't work from this link, but you might be able to find something useful on archive.org:

https://web.archive.org/web/20110607132532/http://www.freescale.com/webapp/sps/site/homepage.jsp?cod...

Tom

0 Kudos

3,273 Views
philliproth
Contributor I

Hi Tom,

Thanks for the tip and links but none of that will help generating a simple step clock. Looks like I can use a GPT output and have it pulse the output pin when the timer reaches a compare register value, and will also generate an interrupt which I can change the compare value to the next value in the accell/decell table. Just not sure if the output pulse will be long enough to step the motor driver which is on a remote board and connected through a ribbon cable.  It's probably only pulsed for 1 clock period and will be too short and I might be able to toggle the output pin rather than pulse it which will certainty have enough pulse width.

So the plan would be:

  • Have a table of compare values that control the accell rate of the motor. (slope & linearity)
  • Setup for auto-reset of the timer after it reaches the compare (if that's possible)
  • Load the compare with the 1st table entry, enable the timer and wait for the interrupt meaning it expired and toggled the output.
  • On the ISR, read the current contents of the timer and subtract that from the next table entry (to eliminate jitter on the output step)
  • Keep going until it's time to decell, them work the table backwards.

Thanks again,

Phil

0 Kudos

3,273 Views
TomE
Specialist II

> Thought PWM would be the best

it is very useful when you want fine control of the stepper motor current, and/or want to "microstep" the motor. You can also drive the windings with a sinusoidal waveform, or even better, one pre-corrected with the motor "harmonics" which gets you very linear and quiet operation. Which isn't what you're doing.

The Reference Manual tells you what registers are there without telling you what to do with them. I last say manuals with this sort of useful content when these chips were branded "Motorola".

The PWM in that chip has 8 channels which can all run locked together, generating 8 different pulse trains. These are 8-bit counters, usually good enough resolution for most things, but they can be connected in pairs to give you 4 16-bit counters if needed. They even have a "Centre Mode".

There should be lots of App Note and example code showing you how to use the counters to perform the tasks you need. I suspect these WERE available 10 years ago when these parts were new, but I can't find anything now. There are very few App Notes linked from any of the Coldfire web pages.

Motorola/Freescale/NXP have a bunch of different peripherals that they re-use in different families of chips. You can find the same controller in use in an HC08, Coldfire and ARM Kinetis. Some of them turn up in the PPC line and elsewhere. So if you can find this particular PWM module being used in a chip with better documentation, support and software you might be able to read THAT documentation.

The easiest way to find which families use which modules is to type an unusual register name into Google and see what it matches. For instance Google finds some interesting articles for "PWMPRCLK" in the MC9S12.

It also found this, which is someone asking how to drive stepper motors from the MC9S12 in 2007, with answers and references:

https://community.nxp.com/thread/33828

Here's someone using the DMA Timer to control a stepper motor:

https://community.nxp.com/message/79422

Other interesting but not specifically useful links:

http://wwwold.ece.utep.edu/courses/web3376/PWM%20Intro.html

Tom

0 Kudos

3,273 Views
TomE
Specialist II

This chip has four main timer peripherals (ignoring watchdogs).

There's the PIT, which has an annoying appropriate name; see the "Bear PIT" section in this to see all the things wrong with it:

https://community.nxp.com/message/71442?commentID=71442#comment-71442

They're fine for generating interrupts at fixed intervals, but not so good when you need to change the period. They're also "set and forget". They don't have any I/O pins, so they're only good for generating interrupts for software.

There are the four DMA Timers, which are great for generating four separate and independent interrupts or pulse trains with a very high resolution (as they're 32-bits), but not so good when you want multiple outputs with controlled phase relationships.

There are the 8 8-bit or 4 16-bit PWM timers. 'nuff said.

The best timers are the "GPT" ones. You don't realise how great the architecture is until you see it used properly. It is unusual in that they aren't "timers" or "counters" as such. There ONE counter that you have to set up with an appropriate frequency for all the timers, which are all COMPARATORS on that one counter. They can be set up to capture the counter on input transitions, which gets you four channels that can give microsecond (or better) timestamps of external signals, but you need the outputs.

You set up the comparators with values that correspond to the offsets in time that you want. For instance if you want four outputs spaced at 100 "ticks", then load them with 100, 200, 300, 400 and set then to toggle on output compare. Then when each one interrupts, just add "400" to the comparison register. Note you don't read the counter to add anything to it - just increment/adjust the comparison register.

The only hard bit is that the counter can only run at Fsys/2, which is 40MHz or 32MHz, or 1/2^n of that, with the slowest rate being 1/128. So the slowest is 80/128 MHz or  625 kHz. That means the counter wraps in 104ms, so that's the largest period you can have the hardware generate automatically without having to handle overflows in software.

What you really want is a 32-bit GPT. You can almost make the DMA Timers do that, but the problem is that you can't start them all at the same time. But you can probably set them up and then start them "close enough" (within a few microseconds) of each other, and then let them "free run" and manipulate the comparison registers on interrupts the same way you'd do with the GPT.

Remember you can always do everything in software, taking PIT, DMA or GPT interrupts and then just toggle GPIO pins yourself. You'll have to worry about interrupt latency as that will affect the timing that way.

Tom

0 Kudos

3,273 Views
philliproth
Contributor I

@Remember you can always do everything in software, taking PIT, DMA or GPT interrupts and then just toggle GPIO pins yourself. You'll have to worry about interrupt latency as that will affect the timing that way.

Trouble is you can determine the latency, but the damage is already done and the step clock will be delivered late. IMO, the hardware must control the step clock

@Thought PWM would be the best.

I can see PWM working for velocity control and acceleration but don't understand how I can track position which is most critical. Guess I can take the PWM output and connect it to a counter but then I'll only know the position without being able to control it.

@What you really want is a 32-bit GPT.

Silly me, thought they already were. Fsys/2, and 16bit hasn't the range nor resolution so that gets kicked to the curb. Glad you mentioned it before I spend a day or 2 trying to code that in.

@Here's someone using the DMA Timer to control a stepper motor:

This looks promising. Looks like there is an output which can be triggered when a 32 bit timer expires which gets me the dynamic range I need and the ability to track position and execute functions on every ISR which is also needed.

What I'm doing is taking 20+ years of previous designs based on Intel 80C186, 8051, 80196 and coming up with a single replacement board before I retire. Had a crew of 8 guys doing hardware/firmware development before they shut the company down and moved it overseas and left all the grunt work to me, thus the reason I'm 10+ years behind the curve. Raised on Intel, I avoided Motorola like Chevy vs. Ford but now find myself digging into 68k stuff. Should have went ARM but at this stage of my career I'd rather focus on "other" things and let my kids have all the fun with new technology.

Appreciate your effort gathering this, saved me a lot of time. I'll look into the DMA timers after I get these SPI IO expanders going. The hardware is coming along and I might have a shot of actually running a machine with the 1st cut of these proto boards.

Hopefully you'll be around if I still can't figure it out.

Phil

0 Kudos

3,273 Views
TomE
Specialist II

> Trouble is you can determine the latency, but the damage is already done

On the normal and primitive processors you've probably been working with (and I include every ARM and Intel CPU in that list) that might be the case. But the Coldfire inherits a 6 level priority interrupt structure from the M68k, so it your code never totally disables interrupts (just raise to level 6 for locking and synchronisation) and you run the stepper motor timer interrupt at IPL6 then the latency should be less than a microsecond.

> don't understand how I can track position

Whatever time you're using will interrupt you on a step. So you track the position in an interrupt. if you want to know where it is in a cycle, then read the counter register that is controlling the timer.

> Fsys/2, and 16bit hasn't the range nor resolution

At maximum range the resolution is 80MHz/128, or 1.6us. That's got to be fine enough! If it isn't fine enough then you "dither" between values using a standard "dither accumulator".

At maximum range the step time is 104ms. It is trivially simple to go beyond that. Your code would generate "timing tables" for the steps, and the interrupt would load "the next step", by adding the next step to the comparator. If "the next step" is less than 64k (104ms) you simply add it. if it is greater then you DISABLE the output toggle and add some fraction less than 64k. Rinse and repeat. The only trick is to add steps that make sure the first or last one isn't less than the interrupt latency plus a safety margin.

> now find myself digging into 68k stuff

But it is old and nearing EOL. Whoever you're leaving it to might curse you for the short life before they have to replace it with something else which will be ARM. You really should have gone ARM if starting a new project. Or if the code runs on all that old primitive stuff and doesn't need huge numbers of megahertz, Arduino.

> Hopefully you'll be around if I still can't figure it out.

No intention of leaving. Been on these forums since at least 1997 with the MC68302 and MPC860. This forum is my happy nerd equivalent for Facebook.

Tom

0 Kudos

3,273 Views
philroth
Contributor III

I was hoping you were going to say "Good choice going with DMA timers" but seems there are many ways to skin this cat.

Probably ponder it over the weekend and try a few things early next week.  Just blew 3 days trying to figure out a Microchip IO expander that had jinglish for documentation, finally figured out CS had to remain active throughout the entire 3 byte transfer sequence....not possible with the 259's QSPI controller which raises CS after each transfer so I'll just work CS as GPIO.

As for getting cursed for not going ARM, I would have gone that way if I was 10 years younger but I'm getting ready to turn the page after working here 35 years and still doing all the EE design and firmware. Did a few 5272 and 5213 designs a few years back for other products and like the architecture so pretty comfortable with the 259. There's also 2 million lines of C code that ports right over, just need to redo the lower layers.

Our product line is unique in that it's low volume (<100 per year) and costs close to $1,000,000 USD each and needs to be sold and supported thru 2028. Just the opposite of some router or cellphone that changes every year, requiring a new spin. I thought any ARM based processor wouldn't have the shelf life and I'd be doing it over every 2-3 years for the next newest processor.

When the 259 gets phased out, we'll just buy 1000 pieces to hold us over. I'm also doing a complete redesign of the motion control and communication system which can easily be reused should the next guy go with ARM.

Phil

0 Kudos

3,273 Views
TomE
Specialist II

> finally figured out CS had to remain active throughout the entire 3 byte transfer sequence.

> ...not possible with the 259's QSPI controller which raises CS after each transfer

I've got an MCF5329 QSPI doing exactly that for the last 5 years, controlling three Microchip MCP2515s, which need CS to remain asserted, as well as talking to a TI ADC controller that needs weird delays and 16-bit transfers. The MCF52259 QSPI is identical. Also an MCF5235 QSPI hitting multiple multi-channel ADCs very hard. But I digress...

I suggest you have a close look at the "CONT" bit in the QCR RAM registers in section "27.3.7 Command RAM Registers (QCR0–QCR15)".

Familiarity and code base stands for a lot. And the switch from big-endian to little-endian always shows problems.

I suggest you buy those chips NOW unless you trust your distributor to get the notification to someone who'll take notice before it is too late.

Tom

0 Kudos

3,273 Views
philliproth
Contributor I

@I suggest you have a close look at the "CONT" bit in the QCR RAM registers in section "27.3.7 Command RAM Registers (QCR0–QCR15)".

I just glossed over the QCR description and only set the appropriate CS values....assumed CONT was to continuously transmit the entire buffer, not hold CS active during the entire transmission.  Works good now  :-)

DMA timers were easier than I thought and up running with the ISR now loading new compare values and stepping my state machine. Tables going to consume too much ROM though if I need to step 16x and will need to compute timer values on the fly. Could never do it with an 8 bitter.

Thanks again Tom, much appreciated

Phil

0 Kudos