11
$\begingroup$

Often we use microcontrollers to do things in our robots, but need to make some calculations in decimal. Using floating point variables is very slow, because a software floating point library is automatically included (unless you have a high-end microcontroller). Therefore, we generally use fixed point arithmetic.

Whenever I do this, I just use an integer, and remember where the decimal place is. However, it does take some care to ensure that everything is consistent, especially when calculations involve variables where the decimal point is in a different place.

I have implemented a fixed point atan2 function, but because I was trying to squeeze every last drop of limited precision (16 bits), I would often change the definition of where the decimal point is, and it would change as I tweaked it. In addition, I would have some constants, as a quasi look-up table, which themselves have an implied decimal point somewhere.

I want to know if there is a better way. Is there a library, or set of macros, that can simplify the use of fixed point variables, making multiplication and division between mixed variables easier, and allowing declaration of decimal numbers or constant expressions, but automatically converting to the desired fixed point representation at compile time?

$\endgroup$
  • 1
    $\begingroup$ I think this actually is better for stackoverflow as the solution is kind of generic and not much to do with robotics. $\endgroup$ – Shahbaz Oct 26 '12 at 10:03
  • 1
    $\begingroup$ @Jakob - Note that both of those questions were closed as not constructive. $\endgroup$ – Mark Booth Oct 26 '12 at 17:03
  • 1
    $\begingroup$ This is the sort of thing that would make C++ very useful for embedded systems. Templates would generate the correct and optimal code automatically. $\endgroup$ – Rocketmagnet Oct 26 '12 at 17:15
  • 1
    $\begingroup$ Can I have a look at your atan function? I'm trying to tackle the floating-to-fixed-point conversion problem in my academic research and I would be happy to take a crack at it. $\endgroup$ – Joe Hass Nov 7 '12 at 20:54
  • 1
    $\begingroup$ @ronalchn Parts of Arduino (an AVR micro) language are implemented in C++. There is also an AVR C++ Library. And this thread on which compilers to use. $\endgroup$ – embedded.kyle Nov 8 '12 at 13:24
7
$\begingroup$

It would be nice if we could tell the compiler the range and precision of each fixed-point input variable (perhaps no two having the radix point in the same location), and it would automagically -- at compile time -- use the correct range and precision and rescaling operations for the intermediate values and final values in a series of calculations. I've heard rumors that it may be possible to do that in the Ada programming language or in C++ templates.

Alas, the closest I've seen is fixed-point arithmetic libraries that require you, the programmer, to manually choose the correct representation and manually verify that each operation maintains adequate range and precision. Sometimes they make multiplication and division between mixed variables easier. Such as:

$\endgroup$
  • $\begingroup$ It's almost certainly possible to do this using C++ templates. $\endgroup$ – Rocketmagnet Oct 31 '12 at 15:24
  • $\begingroup$ I'm actually working on something just like your "it would be nice if..." comment. It is a plugin for gcc that converts floating-point C code to fixed-point, optimizing all of the binary point locations along the way. I have a paper submitted to an ACM journal, and another in preparation. If you have C code for the atan function I would be happy to give it a shot...I could give you back C code that uses integer variables and does all of the fixed-point stuff. $\endgroup$ – Joe Hass Nov 7 '12 at 20:52
  • $\begingroup$ +1 for a much more complete answer than mine. I've edited the link in mine to include a link to a place to request the source code to address Mark Booth's comment. You might want to update your link as well. I'd do it myself but a suggested edit is in queue and is blocking me. $\endgroup$ – embedded.kyle Nov 8 '12 at 13:31
  • 1
    $\begingroup$ @Rocketmagnet It most certainly is possible to implement fixed points using templates, see FixedPoints (disclaimer: I wrote this, and it's still very 'young'). $\endgroup$ – Pharap Feb 24 '18 at 10:42
2
$\begingroup$

I've used the TI IQMath Library to implement virtual floating-point on their fixed-point DSPs.

Texas Instruments TMS320C28x IQmath Library is collection of highly optimized and high precision mathematical functions for C/C++ programmers to seamlessly port a floating-point algorithm into fixed point code on TMS320C28x devices. These routines are typically used in computationally intensive real-time applications where optimal execution speed and high accuracy is critical. By using these routines you can achieve execution speeds considerable faster than equivalent code written in standard ANSI C language. In addition, by providing readyto-use high precision functions, TI IQmath library can shorten significantly your DSP application development time.

That uses some TI specific stuff but I've also used that code as a base to implement virtual floating-point math on other microcontrollers. It takes a bit of work to port but it's a lot easier than starting from scratch.

$\endgroup$
  • $\begingroup$ @downvoter Care to comment on what was wrong with my answer? $\endgroup$ – embedded.kyle Oct 29 '12 at 12:37
  • $\begingroup$ +1: This library is better than what he's using now ("just use an integer"). It doesn't do everything the original question asked for, but I think an answer like this (useful, but not a complete solution) doesn't deserve a downvote -- unless a complete solution actually does exist (which I doubt in this case). $\endgroup$ – David Cary Oct 31 '12 at 15:12
  • $\begingroup$ It seems to me that an answer which is specific to a single range of devices and is only free as in beer rather than as in speech is of limited use to future visitors. $\endgroup$ – Mark Booth Nov 8 '12 at 11:51
  • $\begingroup$ @MarkBooth I changed the link from the C28x library to the C64x library. If you follow that link, you can request the source code. You need a company or a university email to get access. Still free as in beer and speech. You just need to raise your hand and wait to be called on before you can talk. A bit annoying, but once you have the source code, it can be adapted to any processor you like. $\endgroup$ – embedded.kyle Nov 8 '12 at 13:14
  • $\begingroup$ Thanks @embedded.kyle source code is definitely better than binary only, but still of little general use if the license only allows you to use it in limited ways. According to the C6x Software Libraries page that source is only released under TI Commercial License, which almost certainly isn't free as in speech. $\endgroup$ – Mark Booth Nov 8 '12 at 13:30
1
$\begingroup$

There are a number of implementations (no libraries that I'm immediately aware of) of Binary Scaling (aka B-scaling)

In this, you keep a mental note (or even better, document the code...) of where the decimal point is, using shifts to move the decimal point up or down.

I've used B-scaling in assembler on defence projects, on even the smallest CPUs so can vouch for its suitability for anything else...

$\endgroup$
  • $\begingroup$ Probably something like this, but I have never seen it referred to as b-scaling. I think of it as fixed point - the decimal is never floating because even though the decimal point might change in the course of calculations, any one variable always has the decimal point fixed at a particular location $\endgroup$ – ronalchn Oct 26 '12 at 21:01
0
$\begingroup$

If you use an integer to remember where the "point" is, they are kind of using floating point arithmetic. Fixed point, really has fixed point.

I suspect that for every function there would be a different "preprocessing" to make your "floating" point number suitable for the function. For example, for atan, you would want to shift the number so that it's decimal point matches that of your fixed-point function. For cos, you may want to get it in the range of $\pi$ and $-\pi$ and then shift it.

This depends on the range of values your application needs, but you may want to completely move to a fixed point representation. That is, for example, instead of keeping a number like this:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

where number is the whole number and decimal_point says where the decimal point is, you can store it like this:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

where the whole number is integer.fraction, which has the same memory usage, higher range of values and in general simpler to use.

$\endgroup$
  • $\begingroup$ Actually storing the decimal point makes it more like a floating point. Normally the decimal point is defined at compile time, and you change between representation depending on your operation. $\endgroup$ – Jakob Oct 26 '12 at 10:11
  • $\begingroup$ I don't mean remember as in stored in a variable, I mean remember as in I remember how to interpret the result (by knowing where the decimal point is) $\endgroup$ – ronalchn Oct 26 '12 at 10:16
  • $\begingroup$ @ronalchn, I see. You meant something like with a #define, right? I thought you actually store it and it can vary based on how big or small your number is. $\endgroup$ – Shahbaz Oct 26 '12 at 11:21
  • $\begingroup$ @ronalchn - are you thinking of B-scaling? (see my answer) $\endgroup$ – Andrew Oct 26 '12 at 19:00

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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