9
\$\begingroup\$

I need to do rotational (and other) transformations in an embedded application, requiring the sin() cos() and tan() functions. I know you can use look-up tables, and that's the only solution I could find doing my own research, but is there a good fixed point trig library out there?

I'm thinking of using a cortex M3 for the application, so I want to stay away from floating point as much as possible to keep applications zippy.

\$\endgroup\$
  • \$\begingroup\$ Two thoughts: A traditional primitive implementation of rotation is the CORDIC algorithm. You might also see if your vendor now offers a Cortex M4 competitive with the M3 you were considering. \$\endgroup\$ – Chris Stratton Oct 2 '13 at 14:40
  • 4
    \$\begingroup\$ Why don't you want to use lookup tables? That works very well for sin and cos. Doing sin and cos algorithmically is going to take longer. The only advantage might be less program memory space used, but does that really matter in your application? \$\endgroup\$ – Olin Lathrop Oct 2 '13 at 14:46
  • \$\begingroup\$ @OlinLathrop, I want to know what others have found: perhaps some efficient way of solving the problem quickly with little error while saving memory space exists that I haven't found? From what I know (and I could be wrong), the biggest problem for solving algorithmically with the standard libraries is that all the math is done in floating point, and without an FPU that all has to be done numerically, which is dreadfully inefficient... The biggest trouble with look-up tables is: how accurate do I need to be? And if that accuracy req changes, will I still have enough program memory? \$\endgroup\$ – Bob Oct 2 '13 at 14:54
  • \$\begingroup\$ How accurate do you need? A modest size lookup tables is quite sufficient for most embedded sin/cos needs. With 1025 table entries, you get 4096 angle resolution. At that point, linear interoplation gives you good accuracy between table entries. There seem to be a lot of incorrect myths about sine lookup. See my answer at electronics.stackexchange.com/a/16516/4512 for more details. \$\endgroup\$ – Olin Lathrop Oct 2 '13 at 16:01
  • \$\begingroup\$ I hear what you are saying, and I understand the idea of the look up table for the sine function, but if I am code limited (projects always fill code space), is there a more compact way of handling this? That's why I asked: there are lots of talented folks out there contributing, and I'd like to know if they've found anything better. \$\endgroup\$ – Bob Oct 2 '13 at 16:13
6
\$\begingroup\$

A good approach for doing trigonometry in embedded applications is to use polynomial approximations to the functions you need. The code is compact, the data consists of a few coefficients, and the only operations required are multiply and add/subtract. Many embedded systems have hardware multipliers, giving good performance.

\$\endgroup\$
  • 1
    \$\begingroup\$ Has anyone released a version of this in C optimized for embedded applications not using floating point instructions? The high error at either side of the polynomial approximation lends itself to using tricks to use different polynomials for different segments to reduce error, or some other trick... \$\endgroup\$ – Bob Oct 2 '13 at 16:25
  • 1
    \$\begingroup\$ Generic C does not directly support non-integer fixed-point data types and operations, so optimizations for this data type tend to be fairly platform-specific. For example, most DSPs support a fixed-point fractional data type directly in their hardware. From C, you access this via proprietary libraries. \$\endgroup\$ – Dave Tweed Oct 2 '13 at 16:34
  • \$\begingroup\$ coranac.com/2009/07/sines \$\endgroup\$ – endolith Apr 12 '15 at 21:11
  • \$\begingroup\$ Generic C is gaining support through the _Fract data type, but most microcontroller implementations do have vendor-specific libraries. I use libmathq15 for all of my fixed-point needs. Has done the job so far. \$\endgroup\$ – slightlynybbled Feb 19 '16 at 1:31
  • \$\begingroup\$ _Fract is a piece of crap IMHO; I hate the fact that it was "standardized" by the C committee. It forces you to use Q15 or Q31 for everything, which doesn't make sense in many situations, and leaves you stranded without help for those situations. \$\endgroup\$ – Jason S Jan 31 '18 at 19:00
3
\$\begingroup\$

Are you opposed to using the fixed point Cortex libraries for this?

q31_t arm_sin_q31 (q31_t x)
Fast approximation to the trigonometric sine function for Q31 data.

from:

CMSIS-DSP: DSP Library Collection with over 60 Functions for various data types: fix-point (fractional q7, q15, q31) and single precision floating-point (32-bit). The library is available for Cortex-M0, Cortex-M3, and Cortex-M4.

It uses a lookup table with quadratic interpolation, but it's pretty fast. You could adapt it to linear interpolation for faster speed but more error.

Also note that even Cortex M4 doesn't necessarily have FPU. I've seen them called "M4F" if they do.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.