LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Quotient & Remainder FPGA Implementation

Solved!
Go to solution

I would like to use the Quotient & Remainder function in a while loop (not SCTL) of a FPGA vi.  Specifically, I want to use the Remainder output of the function for a modulo operation.  The help leads me to believe that I can use the function as long as it is not in a SCTL.  However, when I try to use it, I get the error that the data type is not supported for that function.  It seems the Q&R function requires a double data type and will not work with a single data type, yet the FPGA implementation does not support double data types.  Is there any work around to allow use of the Q&R function in a FPGA vi?  Ultimately, I need to take a variable and perform a modulo 2pi operation on it.  I'm open to other implementations to accomplish this task and would appreciate any recommendations.  

0 Kudos
Message 1 of 11
(2,056 Views)

Hi John,

 

Q&R usually is used with integer datatypes. Which datatype do you want to use in this SCTL? In the FPGA you should stick with integers and FXP!

 


@johnsoja wrote:

Is there any work around to allow use of the Q&R function in a FPGA vi?  Ultimately, I need to take a variable and perform a modulo 2pi operation on it.


Where does that "variable" value comes from?

You can replace Q&R by (repeated) comparisons&subtractions: IF greater than 2pi THEN subtract 2pi…

Or you could split that "2pi" into an integer and "pi" so you can simplify the Q&R operation only on the integer part. Or...

 

It all depends on your current implementation and your requirements!

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 2 of 11
(2,050 Views)

Thanks John for the response.

 

The input to the modulo function is a FXP mechanical angle of a motor shaft.  I need to perform mod 2pi on that angle to produce the electrical angle of the motor to feed a Park transform for Field Oriented Control.  

 

Joel

0 Kudos
Message 3 of 11
(2,034 Views)

@johnsoja wrote:

The input to the modulo function is a FXP mechanical angle of a motor shaft.  I need to perform mod 2pi on that angle to produce the electrical angle of the motor to feed a Park transform for Field Oriented Control.


Convert the 2*pi into the needed FXP before the Q&R.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 4 of 11
(2,019 Views)

So the Q&R will accept FXP inputs?

0 Kudos
Message 5 of 11
(2,014 Views)

You didn't attach any VIs or provide detailed information of what you are doing, but I'm going to make a few assumptions:

  1. You have a method of getting a Float (non-integer) value, probably sampled, of a shaft position in radians.
  2. It is not clear if the encoder you are using reports values modulo 2 pi, or if it is more like an odometer, able to say "the shaft has turned by 100 radians (or about 16 times) since the last measurement".  I'm going to assume it is like an odometer -- it is also fairly simple to handle if it is modulo 2 pi.
  3. I'll assume that you make measurements a few times per revolution.

Assume you know the Last Shaft Position (LSP) and also the Last Shaft Position Modulo 2 Pi (LSPM).  Calculate the difference between the Current Shaft Position (CSP) and the Last Shaft Position, which by Assumption 3 will always be < 2 pi.  Add this to LSP and call it CSP.  Now do the following:

  • If CSP < 0, CSPM = CSP + 2 pi.
  • Else If CSP >= 2 pi, CSPM = CSP - 2 pi.
  • Otherwise CSPM = CSP.

Save CSPM in the LSPM Shift Register.

 

Now all you have to do is to initialize the LSPM Shift Register from the initial LSP.  Apply the same algorithm to "brute force" compute LSP mod 2 pi without doing any division.

 

The above algorithm, which uses no floating point multiplication or division (expensive in an FPGA, I'm told), should be easy to implement and very fast.

 

Bob Schor

 

 

With these assumptions, the difference between successive measurements gives you the change in shaft position, which will always be < 2 pi. 

 in a Shift Register (initialize it with the starting Shaft Position).  

0 Kudos
Message 6 of 11
(2,001 Views)

Bob,

 

Thanks so much for the reply.  I've got an incremental encoder with index (A,B,Z outputs) mounted on the motor shaft and I'm using the Labview SoftMotion Encoder function running in a SCTL, which provides an I32 output of counts representing mechanical position in a continuous fashion.  The encoder function (I32 output) is not a read of delta position, but rather a continuous output counting up with rotation in one direction and counting down with rotation in the other direction.  I take the I32 output into a flat sequence structure where I do my servo loop controls.  In that structure I take the I32 position count output from the encoder function, convert it to FXP, multiply it by a scale factor to convert the counts to mechanical degrees.  It is this output that I need to perform the mod 2pi on.  Any other thoughts based on this info?

 

Thanks again!


Joel

 

Thanks,

Joel

0 Kudos
Message 7 of 11
(1,931 Views)
Solution
Accepted by topic author johnsoja

All you probably need to do is take the integer and use Q&R to divide by the number of counts for a full revolution. No need for any other datatype here. You can convert the result afterwards to whatever the next node expects. 

Message 8 of 11
(1,927 Views)

@johnsoja wrote:

 The encoder function (I32 output) is not a read of delta position, but rather a continuous output counting up with rotation in one direction and counting down with rotation in the other direction. 

..

 

In that structure I take the I32 position count output from the encoder function, convert it to FXP, multiply it by a scale factor to convert the counts to mechanical degrees.  It is this output that I need to perform the mod 2pi on.  Any other thoughts based on this info?


 

If you have an absolute integer encoder position, it seems weird to be to convert it to fxp and do a modulus. This seems dangerous, as 2*pi isn't an exact number so divide or modulus will sooner or later be wrong...

 

If you have integers, I'd stick to them as long as possible. If you have a relative integer position, you can simply get the absolute integer position by accumulating.

 

So instead of:

read integer.

to fxp

scale

modulus 2*pi

 

I'd:

read integer:

modulus counts per rotation -> get rotations and remainder

(remainder + rotations X cnt/rot) X scale = total position

(remainder) X scale = position

 

If you're lucky (people making encoders aren't stupid), the cnt/rot is 2^n. If so, you can replace the remainder with an AND, and the rotations with a shift.

0 Kudos
Message 9 of 11
(1,885 Views)

If you have a rotary encoder, it probably has a "resolution" expressed as "Counts per revolution".  That is, from whatever position it is in, if you rotate it exactly one revolution, it "counts" (say) 1000 edges (fill in the actual number here).

 

So count edges.  If you are rotating "up", increment the "edge position", and if you are counting down, decrement it.  If it goes over 999 (to 1000), change it to 0 (or subtract 1000), while if it goes < 0, add 1000.  You now have "rotatory position" expressed as an integer from 0 to 999 (and with 1000 edges, that the maximum resolution possible).  0 = 0 radians, 1000 = two-pi radians.  No need, really, for doing any floating point nor quotient/remainder arithmetic, it seems to me ...

 

Bob Schor

 

Note -- replace "1000" with the number of edges of your encoder, which should be 1/resolution.

0 Kudos
Message 10 of 11
(1,861 Views)