From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, 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: 

Shaft Position -- Rounding Errors (Q&R)

Hi fellaws,

 

I am working on a Real Time aplication in which I have to acquire the position of a shaft through a incremental quadrature encoder.  That part I have already implemented. The shaft has attached a rod and can rotate freely towards its saddle. So here I want to set my "Zero Angle" or reference position for the rod, upright.

 

My worries begun when in Real Time code I was using the function "Quotient & Remainder" in order to stablish a valid reference point. I mean, if the shaft rotates more than a revolution, I need that the return value is e.g. 30º and not 390º, and the same in counterclockwise direction.

 

I thought that implementing this with Q&R funtion will work, but then I realized that it drives the simulations towards infinity, so I am looking for help to tweak the code in order to get this done and create an implementation that does not do the same in my RT mpu, and would make my application to fail or break.

 

I am attaching a snippet so you could get the idea os the problem. I was reading some older post in the forum, and there are people discussing so wheter is better to round the input floating point numbers to a set precision, others that you could put a bullet there and convert the DBL to SGL, but here I am looking for a quick and possibly not so dificult solution. In the code, the numeric controls are for simulation purposes.

 

It seems that this piece of code works fine, but I assure you that it drives my simulation vis crazy, and was making my control action went to 600V when it should be 1V.

 

Maybe the solution for how to put a reference in the encoder meassurement is to use another function or maybe it is in the data type or the numeric precisison of the inputs. i will put here also my dissertation when trying to solve this matters.

 

Q&R Rounding Errors.png

 

 

LabVIEW Enthusiast
0 Kudos
Message 1 of 5
(2,842 Views)

Encoders are inherently "integer" in nature (i.e. 8000 counts/revolution).  I would create a TypeDef called "Encoder Value", possibly as a U16, and have a set of sub-VIs for "Encoder-to-Radians" and "Radians-to-Encoder".  You also need "Add Encoder" and (possibly) "Subtract Encoder".

 

 

[Please ignore previous post, which I just asked a moderator to remove -- I pushed the wrong button, "Post", when I meant to clear the Quote].

 

In your routine, you carry around Encoder values, which is what you get from your device.  To display, you simply send Encoder through Encoder-to-Radians and show Radians.

 

To add or subtract angles/positions, first make sure they are in Encoder values.  Adding is easy -- add and then use the Remainder function to make it in the proper range (0 .. 7999 for an 8000-count encoder).  Subtraction takes a little care -- since the Shaft type is unsigned, you need to convert the numbers to signed (to allow negative numbers), do the Remainder, then convert back to unsigned, like this:

Shaft Arithmetic.png

Bob Schor

0 Kudos
Message 2 of 5
(2,807 Views)

Hi Bob_Schor,  thank you very much for your help!.

 

Let me first introduce a little bit of my problem. I am going to post an image with the problem acotation in order to help the visualization of the code.

 

This is the rod which has the encoder attached to its shaft, and it is mounted on a cart, which has another encoder to measure linear position, (But i am only concern about the rod´s shaft encoder). 

 

Diagram

 

As I said, the "zero angle" position for the rod is vertical upwards, and the angle "Theta" is set to be positive clockwise. (Starts at zero, and ends again upwards at 2*pi,  I added a little trick to the code so if the rod is rotating counterclockwise, then the angular position is the same, so this is an absolute reference frame). It has to be that way in order to accomplish with the non linear equations of movement.

 

I am explaining you that, because the encoder attached to the rod increment counts counterclockwise, and decrements clockwise, so a little math was needed in the code for accounting that.

 

Here it is my actual Real Time code: (I am attaching the SubVI too)

 

RT - Vector de Estado_BD.png

 

So you can see that first I am converting the Integer Encoder Counts Control to DBL and then multiplying it with the encoder angular resolution (0.0015 Rad/count). Then I substract and angle of pi because when the RT program starts, the rod is completely downwards, and that time enocder values are 0. So to maintain the acotation I have to substract pi and then invert the result, so if the pendulum rotates clockwise Theta increases from pi to 2pi, and if the rod rotates counterclockwise Theta decreases towards 0, which is the rod upwards.  (I think that this is somewhat my manner of do what you siad in your post, but I did the conversion to Radians at the very beggining).

 

After that it comes the QR function which is giving me trouble.

 

I modified the code as I understood your directions, which is this: (The encoder is 4096 counts/rev)

 

RT - New_Estado_BD.png

 

Also I am posting the SubVI, just in case. (This is the Estado.vi).

 

P.S.: Just checked the code, and it works. Now the rod downwards is 3.072 Rad (instead pi=3.18) but I guess this is an acceptable error. Maybe it can improve using I32? I do not know right now.

 

I did not checked the entire controller, just this subvi, but I hope this way it is not going to generate numerical problems into my control law. Just left the "solved" tag unmarked until I have time to check the controller, just in case I will have to come back here, but my kudos to Bob. Thanks a lot.

 

And I know this is a very large post, but I´d prefer keeping it this way so maybe others could benefit.

 

Best regards.

 

 

 

 

 

 

 

LabVIEW Enthusiast
Download All
0 Kudos
Message 3 of 5
(2,785 Views)

I have two suggestions to your final code.  First, you do not need to check for "Not a number", as you are dividing an I32 (always a number) by 4096 (also always a non-zero number), so the result will always be a number.  Second, there is no reason to be "sloppy" with the math -- to convert the I32 value to radians, do this:

Shaft to Radians.png

Not only is this far more accurate, but it is "self-documenting" -- there are no "magic numbers", only the number of radians in a circle and the number of counts in your encoder.  [Note I showed two ways to write this -- it's largely a matter of style, as this will take so little time as to not be worth measuring].

 

Bob Schor

0 Kudos
Message 4 of 5
(2,770 Views)

Thanks Bob!

LabVIEW Enthusiast
0 Kudos
Message 5 of 5
(2,741 Views)