From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Controlling a Stepper Motor

Hi everyone,

I have a problem controlling a stepper motor and hope to find some help. First, I want to describe what I am doing:

Within my project, I control the pitch angle of the rotors of a wind turbine model as well as the wind speed of the channel I use to do measurements.

The wind speed is simply controlled by a voltage output, the blade pitch angle I control using a stepper motor.

 

This is how I control the stepper motor.

I have a function that converts the pitch angle of the blade to the shaft angle of the stepper motor. So basically I want to turn the motor X degrees. To be sure this is done correctly, I output a continuous pulse train until the signal I receive from the motor's encounter is >= the desired motor position. So far so good - this works fine for now.

 

In my measurement, I want to measure e.g.. 50 different pitch angles (=50 different shaft angles of the motor) for lets say 10 different wind speeds.

So I create arrays for all my wind speeds and all my angles and pass those values to 2 different for loops like this example:

First, I output a windspeed of x, for this windspeed a alter the pitch from 0 to 50° in steps of 1°. For all 50 setups I do a 10 seconds measurement. Than the pitch should go back to 0, the windspeed increases to the next value and I run the 50 measurements again and so on. So after every windspeed, the stepper motor is supposed to go back to the initial position, also after the last wind speed, which means, that after the whole measurement is done, it is supposed to be at the same position as it was in the beginning. This is where I face the problem: there is a slight offset!! It all seems to work fine, but afterwards, I can be seen that the stepper motor did not go all the way back to the initial position.

When the stepper motor changes to one position, the encounter signal ready the "actual" position of the motor. I use this value as the next "initial angle" of the encounter measurement in the next loop iteration.

While trying to fix the problem, I tried the following: Instead of increasing the angle 50 times and going back to 0 only once during that time, I used 250 random angles (e.g.. Going back and forth). Doing this, the offset was much less. However, this could also have to do that I only used one windspeed e.g.. That I did not pass the shaft angle to the next loop iteration.

 

Here another approach I tried: The stepper motor turns 15° each step. The encoder has a precision of 3° for each pulse I read with the counter. So when the stepper motor is at lets say 15°, the encoder might give me a signal saying it's at 18°. So I tried rounding the encoder signal to the nearest multiple of 15. Nice idea I thought - didn't solve the problem though...

 

 

Here is a stripped down version of the problem without all the measurements, data logging,...

I hope its more or less clear what I try to do, please let me know if any further explanation is required.

0 Kudos
Message 1 of 9
(2,792 Views)

Hi!

 

In your program you only measure the encoder of the stepper motor while changing the motor position. Is it possible that

the position of the motor changes slighlty under load within the 10 seconds of the measurment? 

Another problem might be how the pulse train controlling the motor is stopped. After taking the encoder measurement

you stop the loop and stop the pulse train task. However, between reaching the right position of the shaft, reading the encoder

value, stopping the loop and stopping the encoder task might be a slight delay you would not notice.

 

Maybe you can try monitoring the encoder continuously from the start of the first measurement to the final position of the motor.

You could do that by having a second while loop in your main VI and have the current value of the encoder be written to a notifier

so you can access it from everywher in your main VI. As an alternative to the notifier you could also use a global variable.

 

I would also strongly recommend to use a state machine as the architecture in your program. This will help making your code

more structured and readable.

http://www.ni.com/white-paper/3024/en

 

Regards,

  Georg

0 Kudos
Message 2 of 9
(2,751 Views)

Thanks for the answer!

That the position of the motor changes is (more or less) impossible, there's close to no load during the measurement.

I thought about the time delay while stopping the pulse train already - but how would I "gain" any time using notifiers? Isn't using the condition within the loop and using a condition from a notifier the same thing?

Thanks for the timemachine hint, I might put some time into changing the whole program, however, it would be great to figure out why the finial position is not the same as the initial position first...

 

Thanks again

0 Kudos
Message 3 of 9
(2,743 Views)

You would not gain any time, however you would always now the exact position of the shaft because you

continuously monitor it without any interruption. That does not mean that the shaft could not change its position,

however you would notice it. If you continuously monitor the position you could also plot it in a graph and see

when it changes unexpectedly.

 

 

P.s. _state_ machine

if you manage to implement a time machine in LabVIEW please share the code in the forum 😉

0 Kudos
Message 4 of 9
(2,739 Views)

Smiley Very Happy ok, *state*machine.

 

ok that would be a little nicer...however - I still have no idea why my motor is returning to a different position. Well, usually Z-index is used in order so define a reference position every x degrees. My encounter only has 2 outputs A and B, no Z channel.I still can't believe that there is no solution to my problem. Smiley Frustrated

 

Any hints anyone?

Later, I want to implement a PID controller in the code so I would continuously change the pitch angle over a longer time, so this error will probably add up :(.

 

Regards

0 Kudos
Message 5 of 9
(2,732 Views)

you could also just use a finite pulse train to control the motor. Knowing the amount of pulses you send will make

sure you can calculate the motor is at a known position.

Then you could use the encoder to verify the position.

However, I would still recommend to let the encoder task run continuously in the background. If you stop it

the position of the engin might change without you noticing it. You do not need a Z channel if you _continuously_

monitor the encoder position.

 

Regards,

  Georg

0 Kudos
Message 6 of 9
(2,727 Views)

ok right now I am facing some trouble implementing the notifier in the code posted. I think the state machine will solve this issue. I would like to try if this solves the issue thought within the code existing first. My problem is that in the sequence where I change the pitch I would "fetch" the current pitch position only when entering the sequence.

0 Kudos
Message 7 of 9
(2,716 Views)

Hi again,

well, I tried to create a state machine Smiley Happy

There are probably still some bugs, but as a first stage, I cannot get the second (the 'major') while loop to run.

It is setup exacly as the example posted, however, the loop count of the second loop remains at 0.

 

Thanks for any hint.

Jack

0 Kudos
Message 8 of 9
(2,690 Views)

Hi!

The reason for this behavior is the wire that runs from the one loop to the other one (see screenshot).

Data is only passed through the wire when the first loop stops. The second loop is waiting

for the data input but does not get any till the first loops stops.

Use queues or notifier to pass data between parallel while loops.

Additionally I want to recommend to structure your code better in modules (=subVIs) to improve

the readability of your code.

0 Kudos
Message 9 of 9
(2,683 Views)