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.
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.
10-15-2020 06:31 AM
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.
Solved! Go to Solution.
10-15-2020 06:43 AM - edited 10-15-2020 06:45 AM
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!
10-15-2020 07:17 AM
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
10-15-2020 07:53 AM
@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.
10-15-2020 07:57 AM
So the Q&R will accept FXP inputs?
10-15-2020 08:46 AM
You didn't attach any VIs or provide detailed information of what you are doing, but I'm going to make a few assumptions:
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:
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).
10-20-2020 03:32 PM
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
10-20-2020 03:43 PM
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.
10-21-2020 04:06 AM
@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.
10-21-2020 03:55 PM
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.