After reading almost every forum, I still haven't figured out what to do. my brains burned..
The code below works as follows.
The position is 0 when first started. The motor goes to the desired position with the frequency and position value I entered. If I enter a value lower than the previous value, the motor returns and waits in the position until a new position comes. So far everything is as I wanted.
The only problem: If I change the frequency in this code that I'm generating. It changes in position. And it doesn't come to the desired position anymore. Because the number of steps changes according to the entered frequency value.
The situation I want to create is exactly as follows: If I send it to 1000 locations with 30 KHz it should reach 1000 and wait. If I change the frequency to 50 KHz, it should wait at 1000 until the new location arrives. If I write 2000 locations this time, I want it to reach the 2000 location quickly (50KHz). In other words, only 1000 values are added to its location.
To briefly explain the code I want to create. I want to control both the position where the
engine should go (forward-backward) and its Speed.
Is there a way to do this? Is this possible.
Any opinion given is worthy of respect.
Solved! Go to Solution.
My guess, if you actuate the stepper faster than it can rotate, it just skips steps.
For example, if the stepper can respond to only 1000 steps/s and you supply 5000 steps/s, it will not work. The only way to overcome this is to have a feedback mechanism of the current position and target position like an encoder.
No matter how many steps I give the motor, it works but that's not the problem. The problem is I can't synchronize the frequency and step. For example
if I give 1000 steps at 100KHz 1000÷0.0025(nanosecond) =400.000 motor will run. If I give 2000 steps at 100KHz without changing the frequency, it will still work.
If I change the frequency, set it to 200KHz and go 3000 steps again, it returns half as much because the code I wrote works as "step÷frequency".
What would be the method to find a solution to this?
I can connect an encoder to the engine. If I add the encoder, what changes do I need to make in the code?
The motor's encoder needs to send pulses continuously until it is not equal to the value I entered. It sends pulses and reads the position, but does not compare.
Currently I want to use the encoder as feedback, but I have such a problem.
Please someone tell me where I went wrong.
Thank you for including your code, especially the FPGA. You are using a myRIO (with which I have some experience), and are connecting it to a "stepper motor" (whose specifications I don't know, but will ask, shortly).
Here are some "didactic points" that took me a few days to wrap my head around. The myRIO FPGA runs on a 40 MHz clock -- this means it takes 1/(40 x 10^6 reciprocal-sec) = 25 ns per FPGA "Tick", so the shortest pulse an FPGA can generate is a 25 ns pulse, and the fastest pulse rate is the time for a H + L pulse, or 20 MHz. If your Stepper motor will "step" when given a 25 ns Pulse, then (in principle) you can make it step every 2, 3, 4, ... n Ticks.
So here's where you need to put in the Stepper Motor specs. How narrow can a single TTL Pulse be to get the Stepper to step? Since it is a mechanical "thing", I'm guessing it wants at least 10's of µs, which puts the stepping "speed" (10 µs Stepper Pulse width = 20 µs peak pulse frequency = 50K) at a maximum of 50K steps/sec. If course, you can go as slow as you want, since you can follow a 10µs Pulse with 99999 x 10 µs of low, for one step/sec.
So now to the FPGA. You do not need/want a Timed Loop -- an ordinary "Do Forever" While loop will run at ... 40 MHz! But do you want it to run that fast? I'd say, "Probably not -- it should run at the Stepping Speed of the Stepper Motor", which I assumed was 20 µs (10 µs High + 10 µs Low). How do you do that? Put a Loop Timer of 20 µs in there (wire the Loop Timer in units of µs, and use an 8-bit counter -- why waste precious FPGA silicon?
What controls do you need? You need one for Step Speed (how many Steps/sec, which you supply as a U16, max 65535, which means as long as you are doing > 1 Step/sec, you are covered (and you guarantee this in your Top-Level Host LabVIEW code, where you have all the power of "regular LabVIEW", including Floating Point arithmetic to help you out). You need one for Direction -- since direction is either Forward or Backward, a simple "Boolean" will do. You probably should have one for "Total Distance", which should also be an unsigned Integer -- I'd suggest a U32, as you are unlikely to make 4 billion steps in one movement. And you need one more Boolean for "Go!".
So put a Case structure inside the While Loop. From outside While Loop, wire a False through a Shift Register to the Case selector. Inside the Case structure, put the "Go!" control and bring it to the Shift Register on the right edge of the While Loop. The False case is where you read Direction, Step Speed, and Total Distance, and save them in additional Shift Registers. As long as you are not moving, you can update these Controls and they will be "ready when you are".
The "True" case is where you do your movement. You need a multi-frame Sequence in here. The first Sequence gets the Loop Timer, which "clocks" the entire True case. The next one decrements Total Distance, sets the appropriate DIO to High, and has a 10 µs Wait. The last Frame brings the DIO down to Low. It also asks if Total Distance is 0, and wires this Test to the Shift Register controlling the Case.
Do you see what this does? I didn't explicitly treat moving forward or backward, largely because I don't know anything about your motor, but you should be able to do the rest, yourself. I apologize if I left a step out, but I hope the ideas are clear enough that when you start to put them down in LabVIEW code, you will have several "Ah, ha!" moments.
Thanks for your answer, I am trying the below code on your suggestion. But I think there is a problem. Because sometimes the countdown reaches a number like 4101354534 and I cannot change the frequency as I want.
What I want to do is actually increase or decrease its speed while the engine is in motion, even if I change the speed, I want it to be written.
Considering your suggestion, I made some changes. I tried this, the result is good. But what I want to create is both faster and if I type 0 position, it should return to zero position no matter what position it went to. What is the way to do this.
Also, in the example below, the problem sometimes occurs. Value 4152121 returns something.With the method below, each pulse corresponds to one value of the encoder.
Get out a piece of paper and a pencil. You need to draw some things because your logic makes no sense, and doesn't follow what I outlined for you. Part of the problem is probably my fault, as I do not understand how your actuator works (I'm assuming that a "positive pulse", which (to me) means a DIO line that is initially False (or Low) goes High for some period of time (the Pulse Width, say 10 ms, or whatever the motor or control circuitry wants) and then goes low (and stays low until you want another Pulse).
There are two (and only two) times needed in this FPGA. One is the Pulse Width (which I made up as 10 ms, above), and the other is the Pulse Interval (which should probably be at least 2 times longer than the Pulse Width). So if the actuator needs a 10 ms Pulse to move, then the maximum Pulse Rate is 1/(2 x 10 ms) = 50 Pulses/sec, or 50 Hz. I think you are talking about much faster movements, so your Pulse Width might be in µs, and Pulse Rate is still at most 1/(2 x Pulse Width).
Write (on paper, not in a Block Diagram) how you would generate a Pulse of a given Width at a given Rate. Presumably, if you connect it to the right DIO Port, the motor will turn in a particular direction. What do you have to do to make the motor turn in the opposite direction? Is there a different DIO Port that moves the motor in the other direction?
What is the condition to start the Motor moving? What variables need to be set before you start the Motor? What governs when you stop the Motor? Is it "I've moved the proper number of steps"? Is it "I've given the proper number of Pulses"? What happens if either of these "proper numbers" is 0 when you start?
It will help you to use "logical" names for variables. "Count(uSec)" is less intuitive than "Pulse Interval (µs)". If I am correct that the DIO is low except when producing a Pulse, then the control "LOW" is more logically-named "Pulse Width (µs)". When you push "Go", you need to check that both Pulse Interval and Pulse Width have "reasonable" values, and decide what to do if this is not the case. When dealing with an FPGA, you want to be sure that all Variables, including Connectors, are initialized. If you weren't looking at your Block Diagram, what do you think would happen if you pushed a Boolean labeled "Button"?
This gets a C+/B-, but I'm a tough grader (particularly when I try to spell out the logical way to approach the problem).
It is necessary to explain the working logic of my actuator more accurately. Sorry, I guess I didn't explain well.
Features of the actuator:
The maximum Hertz required for the actuator to reach maximum speed is 2.2 megahertz.
The actuator needs 2 DIO pins to operate.
Pin 1 is for pulse reading, pin 2 is for actuator rotation direction. If the LOW actuator rotates to the right, the HIGH actuator rotates to the left.
How the engine works:
The actuator is initially in the 0 position.
2- If the 2ndPIN is LOW, when I start giving Pulse to the 1stPine, it will move immediately. If I give 1000 blows, it will move +1000 steps and stop. If I give another 1000 beats again, it will advance +1000 steps and stop. It will have +2000 steps in total. It moves +2000 steps away from the 0 position.
3- Actuator is now +2000 steps away from "0" position. If we want to return it to the 0 position. As soon as pin 2 starts to pulse HIGH and pin 1 starts to pulse, the actuator moves. If I give 1000 pulses it moves -1000 steps and stops. If I give 1000 pulses again, it moves -1000 steps and stops. It will advance a total of -2000 steps and the motor reaches position 0.
I want the motor to come to the entered position.
Thanks for your opinion. I'm still struggling.
Just a side comment as I'm no use at all for any detailed FPGA talk:
2 MHz for a stepper motor sounds absolutely *insane* to me! I can only assume you have some extreme level of microstepping going on. But have you ever actually looked into the accuracy and repeatability of these microsteps?
I have. Decades ago. As I recall, for a raw motor with only a modest additional inertial load, the repeatability error bands were roughly the size of a 1/8 or 1/16 size microstep. We consequently opted *out* of microstepping entirely because the gains were not worth the cost. At the time. (The gains probably haven't changed much but the cost may have changed quite a bit since then.)
In any event, I think it's *extremely* unlikely that you're realizing *ANY* benefit whatsoever from 2 MHz microstepping that you couldn't get from a coarser microstep in the 10's of kHz. The mechanics of the motor and the system it drives simply won't have the bandwidth to know the difference.
Kevin_Price thanks for your answer. At the moment, the engine can fully respond to such sensitivity. I edited the code as follows. It answers exactly what I want. The engine goes to the desired location and waits.
I'll just try to create a smoother stop when it's approaching its target while it's spinning at great speeds right now.I know I should use PID for soft starting and stopping of the motor but I don't know how to use it in FPGA.
Sample code is below.