I need a Spin counter expert to examine some code for me PLEASE :)
idbruce
Posts: 6,197
Hello Expert
I have a stepper driver object within the object exchange, and I created it while having very little knowledge of clock speeds or counters, and this is still the case. Regardless of my lack of knowledge in these areas, the driver works really well to a point. I have been pushing the software, stepper motors, and the electronics to find it's breaking point and I finally reached it.
Now I wonder why it is breaking.
Am I exceeding the limit of Spin counters with my parameters and code?
Or is it due to a lack of sufficient voltage in the motor coils, which happens to be 50VDC? I am not looking for a reply to this question.
The following parameter values are the last ones that are successful.
Any effort you may put into deciphering this code and giving me a response will be GREATLY appreciated.
I have the need for speed.
Bruce
I have a stepper driver object within the object exchange, and I created it while having very little knowledge of clock speeds or counters, and this is still the case. Regardless of my lack of knowledge in these areas, the driver works really well to a point. I have been pushing the software, stepper motors, and the electronics to find it's breaking point and I finally reached it.
Now I wonder why it is breaking.
Am I exceeding the limit of Spin counters with my parameters and code?
Or is it due to a lack of sufficient voltage in the motor coils, which happens to be 50VDC? I am not looking for a reply to this question.
The following parameter values are the last ones that are successful.
nMaxFreqDurHZ := 16_000 (If I go below this value the motors fail to run)
nMinFreqDurHZ := 9_000 (If I go below this value the motors fail to run)
nMinPulseWidth := 1_000_000
Here are some global variables that are used:
nMinFreqDurHZ := 9_000 (If I go below this value the motors fail to run)
nMinPulseWidth := 1_000_000
Long nTotalStepsDivByTwo
Long nStepsRemaining
Long nCurrentFrequency
Long nCounterTime
Long nStepPulseWidth
Long nTotalRamps
Long nStepsRemaining
Long nCurrentFrequency
Long nCounterTime
Long nStepPulseWidth
Long nTotalRamps
PUB G251DriveStepper(nMaxFreqDurHZ, nMinFreqDurHZ, nMinPulseWidth, nRampingFreq, nStepPin, nTotalSteps) nCounterTime := cnt nStepPulseWidth := clkfreq / nMinPulseWidth nCurrentFrequency := nMaxFreqDurHZ nTotalStepsDivByTwo := nTotalSteps / 2 nStepsRemaining := nTotalSteps ctra[30..26] := %00100 ' Configure Counter A to NCO ctra[5..0] := nStepPin frqa := 1 dira[nStepPin]~~ repeat while nStepsRemaining > 0 {Ramp Up} if nCurrentFrequency > nMinFreqDurHZ and nStepsRemaining > nTotalStepsDivByTwo nCurrentFrequency := nCurrentFrequency - nRampingFreq nTotalRamps := nTotalSteps - nStepsRemaining {Ramp Down} if nTotalRamps => nStepsRemaining and nCurrentFrequency < nMaxFreqDurHZ nCurrentFrequency := nCurrentFrequency + nRampingFreq nTotalRamps-- nCounterTime += nCurrentFrequency phsa := -nStepPulseWidth waitcnt(nCounterTime) nStepsRemaining--
Any effort you may put into deciphering this code and giving me a response will be GREATLY appreciated.
I have the need for speed.
Bruce
Comments
I'm in no state of mind to read code today - happy new year, ugg... but I wanted to at least make sure you have already seen the application note on counters in case that might help you.
Go to this page and look for appnote, AN001
http://www.parallax.com/tabid/832/Default.aspx
How many rpms is your motor maxing out on? Is it possible it's simply hitting its no load limit? I tried to find a torque-speed curve for the Applied Motion motors which I think you're using (true?) but their website seems bereft of such data.
In your code you have to do "babysitting" of the counter. There are some applications where you can set and forget the counter.
This is not the case with steppermotors as you have to create a certain amount of step-pulses.
So then it can be done much easier without the counters
A simple-repeat-loop that toggles the step-pulse-IO-pin and two waitcnt-command and you are done
To get further help you should specifiy the maximum-frequency you want to create.
You should write if it is important to count every single step or if it doesn't matter to stop a couple hundred steps earlier or later.
best regards
Stefan
Thanks for the response, however, I noticed that you did not answer the question.
In answer to you questions:
- Step counting is crucial for my application
- For a G251 Gecko Drive, the minimum step pulse width is 1us
- For a G251 Gecko Drive, the advertised step pulse rate is 0Hz - 300kHz
I don't understand what you mean by me needing to babysit my counter. I pass the parameters and it works like a charm. That code is a good driver. I just want more speed. I am no expert by any means, but I have been told that counter driven PWM will blow the doors off standard Spin waitcnts like you suggest.As I previously mentioned, the code works and it works well. It can be fully tailored to suit ones particular needs by altering the parameters. Test and you will see.
As a final note, if you look at the code, you will see that you need to scroll to see the last parameter which indicates the number of required step pulses.
## Edited the step pin and required pulses are fully visible as the last two parameters
Bruce
I agree
Bruce
I will make it easier for you. Is this code to fast for a Spin counter?
Bruce
Thanks for responding. You and I posted right at the same time. Did you see the previous post? Do you have a link to that object?
Bruce
Keep in mind that Spin takes time to execute so there may come a point where your inner-loop calculations take more time that your loop wants to use; in this case you will miss the waitcnt target that sets the output frequency of the driver.
Now that was clear, concise, and made a lot of sense, and I guess that is what I was asking, only you summed it up. Cluso99 suggested monitoring the pulse utilizing an object that runs in another cog. I tried to find his object, but then remembered some source code in PEKitLabs Chapter 7 Counter Modules. I just looked at the code, and it appears it will be very easy to alter to do some speed tests, and find out if it is failing in the inner loop calculations as you so elequently stated. I truly believe that is the situation. You are a smart guy
Bruce
A typical and concise statement just for waiting 1ms is waitcnt(clfreq/1000+cnt).
This is obviously a little different from your case, but the utility of it is often overlooked by many.
Happy New Year
I tried both of your samples using a scope. Your first sample actually functioned with lower values than you noted. Your 2nd sample also functioned, I had to increase the repeat value to see it though. Sounds like your pushing your hardware beyond their limits.
agfa
Not according to PEKitLabs-v1.2
Bruce
WOW! That is just too cool! I truly appreciate you taking the time test the code on your scope. That is nice to know. I am just curious how far you pushed the first piece of code. Okay, so now it is determined that the inner loop is not slowing it down in my case, but I am certain that it will reach a breaking point as JonnyMac so nicely stated. I guess I will have to live with the results and go forward. I am assuming at this point that it is due to insufficient voltage for more speed. In the future, I will have to get a larger power supply. I truly thought that 16A 50VDC would be enough for my needs, but I was wrong :frown:
Thanks Again agfa
Bruce
nMaxFreqDurHZ down to 13,000
& nMinFreqDurHZ to 7000
agfa
Once again thanks for responding back, like I said just way too cool. 7000 and 13000, at least I know those numbers are good. Actually the machines move fairly fast already, I was just hoping for better production.
Thanks
Bruce
Before getting a different power supply, I would check how your stepper motors are reacting to such high speeds. It seems to me that you are more likely encountering a speed limit caused by the induction of the motor. The coils can charge and discharge only so fast. Beyond that, you can whip her all you want, but the donkey she no go no more.
I have some torque speed curves from Applied Motion around here somewhere. I think they were achieving around 10 rps with about 50 volts. The G251, has 10 uSteps per full step. Like I said, I am not that good with counters, so I am really uncertain how many pulses I am sending per second. If I were to compare it to Applied Motions torque speed curves, to obtain the 10 revs per second I would have to actually be sending 20,000 pulses per second. I do not know exactly how fast they are turning, but it is pretty fast.
Bruce
the specs of your steper-card says MINIMUM-length of step-pulses 1 microsecond
to make it work reliably I would increase the pulse-length.
Your way to use a counter in NCO-mode means you set the counter and do some changes to the frequency but the counter is free running.
Your code has no EXACTLY control about how many step-pulses were created.
So if you want to control the amount of steps EXACTLY you have to "babysit" the counter
how many pulses where created. Therefore the speed of your loop has to be faster
than the pulse-frequency. And if this is the case you can do it without the counters.
I measured the frequency with a scope and it is 8-9 kHz.
I include a code-example where an EXACT amount of step-pulses is created at a maximum-frequency of 19.5 kHz without using the counters.
Steppermotors loose torque with increasing rpm. And it will drop down to ZERO if the speed is just high enough.
So if you need really high rpms I suggest that you write what you want to to in the end.
I have seen it so many times. If it is clear what you want to do in the end often other solutions that work much better can be found.
best regards
Stefan
I did with the scope because it was easier for me to add five lines of code switch on the scope and connect the probe.
(takes a minute)
I estimate if I do it myself it will take 4-5 hours to implement it. (maybe I'm wrong) but this estimation keeps me away from
writing the code myself.
If you could provide a democode that shows how to implement this code into another I would use it.
Do you have the code handy and would not mind taking 10 minutes to add comments?
best regards
Stefan
There is an example in PEKitLab1.2 that includes a test for two pins, however it could be altered for just one. Here are the necessary files.
Bruce
Hi Stefan,
I think MagicIO2's comment about scopes was aimed at Bruce, not you. Based on Bruce's previous comments, it sounds like he doesn't really know what his output has been maybe because he doesn't have a scope, so I think MagicIO2 was suggesting Bruce use the Propeller counters for getting some idea of rpm, etc. It's awesome that you guys have gone through all the trouble to help Bruce with your scopes, etc.
In addition to JonnyMac's comment about the importance of using a scope for things like this, Stefan's point about putting a load on the motor is also excellent: Bruce can set up his system so it runs beautifully in the "no load" condition, but once a load is put on the motor, he might not really get what he expects.
I will be adding test code here very shortly for the G251DriveStepper object
Bruce
Bruce,
just be aware that if you're operating on the hairy edge of what a stepper motor can do, then it might skip steps if it encounters a transient load for some reason, and if it skips steps, then it won't be where you think it is. This is why some people add encoders to steppers, just to be safe. A cheaper but perhaps more risky method to keep track of the stepper is to have it periodically "re-zero" itself by having it move its "whatever-its-actuating" over to a homing switch or limit switch of some kind. Because loads can be unpredictable, your safe operational envelope might be difficult to discern without thorough testing.
Jazzed: The timing loop you give above will NOT execute in the specified 10000/80MHz time (or 125uS). It'll execute in something more like 10500/80MHz time (or 131uS) because the "repeat", "future := 10000" and about half of the "future += CNT" is outside of the precisely timed code block. Precise timing can be restored by measuring this overhead and compensating for it, but it's just easier to roll the overhead into the precisely timed code. This second technique is what IDbruce is using. My favorite way of doing this is summarized in the code snip-it below
Lawson
I've also used this counter trick a lot. It lets me generate a precise pulse from 1 to ~2^30 clocks long with a single instruction while my code continues on doing other stuff. I agree that you do have to keep setting the counter (or stop it when you are done) but this is rarely a problem since the counter will take 2^31 clock cycles to roll over and set the output. (~25.8 seconds at 80MHz) Even then it will take the counter another 2^31 clock cycles to clear the output.
With regards to speed, I've had Spin loops using WAITCNT running at up to 64KHz. BUT, this loop did almost nothing. I.e. like the code fragment below. So if you want to get up to the 300KHz maximum pulse rate of the Geko drives you'll need to use assembly. (though configuring one counter for edge counting and another as a 0-300KHz NCO might be made to work from Spin)
Lawson
From your code, are you saying that spin loops are faster than code that uses a counter? This is how I have interpreted what you said.
By the way, thanks for your input, I have been reading it.
Bruce