This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Tiva TM4C123GH6PM wrong floating point result?

Hi all,

I've been playing with the Tiva Launchpad and in particular with the compdcm_mpu9150 example employing the SensorHub Boosterpack.

I modified it so that it sends via UART, at 100Hz, the ASCII representation of both "xacc_calibrated" and "xacc":

      float xacc_calibrated = xacc * 0.0011970964f;

where "xacc" is the uncalibrated raw measurement taken from the MPU9150. Then I acquire the values of "xacc" and "xacc_calibrated" from the other end of the UART (acquiring data with MATLAB). 

I found a strange behaviour: the ratio

    xacc_calibrated / xacc 

is not always 0.0011970964f !!! For a few samples (like 6 samples over 2434 samples) I got values < 0.0011970964f, like 1.1500e-03 .

I'm compiling the code with --fp_reassoc=off and --fp_mode=strict and --float-operations-allowed=32, as reccomended at http://processors.wiki.ti.com/index.php/Floating_Point_Optimization .

The wrong ratio values are associated with high accelerations (obtained shaking the MPU9150 sensor).

I would exclude UART connection / computer connection as problem source because I tried moving the processing of "xacc_calibrated" from MATLAB to the Tiva: even in that case I found that the processing outputs are wrong, because of wrong values of "xacc_calibrated". For these reasons, I believe that the problem is caused by wrong floating point calculations on the Tiva... any suggestion on how to proceed?

Thanks A LOT for any hint!

Francesco

  • Francesco,

      I assumed that your problem was due to the fact that floating point is not precise and that you were likely suffering a loss of precision due to the sizes of the numbers involved. I wrote a testcase, though, and I don't see anything unusual when using the numbers I expect you are using. I assume that xacc is in the range [-32768, 32767] being a signed, 16-bit value. Running the following code:

        volatile float fSingleRaw, fSingleMultiplier, fSingleResult;
        char pcBuffer[80];

        fSingleRaw = 32767.0f;
        fSingleMultiplier =  0.0011970964f;
        fSingleResult = fSingleRaw * fSingleMultiplier;

        snprintf(pcBuffer, 80, "Raw: %f, Multiplier %f\n", fSingleRaw, fSingleMultiplier);
        UARTprintf(pcBuffer);
        snprintf(pcBuffer, 80, "Result: %f\n", fSingleResult);
        UARTprintf(pcBuffer);

        fSingleResult /= fSingleRaw;

        snprintf(pcBuffer, 80, "Ratio: %f\n", fSingleResult);
        UARTprintf(pcBuffer);

    I get the expected output without any obvious ratio error:

    Raw: 32767.000000, Multiplier 0.001197
    Result: 39.225258
    Ratio: 0.001197

    I checked the assembler generated and it's definitely performing both the multiplication and the division (without the voltatile modifiers, the compiler cleverly just printed the multiplier value rather than performing the ratio division). Could you let me know the specific values that you are seeing problems with so that I can plug these into the test and see what's going on?


  • Dave,

    thanks a lot for spending time checking this issue. As I said in the first post, I'm sending over UART both "xacc" and "xacc_calibrated"... this is a small excerpt of what I get on the other UART side, in MATLAB:

    >> from_tiva

    from_tiva =

    1.5720e+03    1.8818e+00
    2.8260e+03    3.3829e+00
    3.8850e+03    4.6507e+00
    -2.0000e+00    -2.3000e-03
    -3.2300e+03    -3.8666e+00
    1.7670e+03     2.1152e+00
    3.4010e+03    4.0713e+00

    here COLUMN#1 (on the left) shows the acquired values for "xacc" (you can see that all values are integers, more exactly int16_t); COLUMN #2 (on the right) shows the values acquired from the Tiva MCU for "xacc_calibrated" (these are floating point numbers).

    Now if I get the ratio between the two columns, element by element, I get:

    >> from_tiva(:,2) ./ from_tiva(:,1)

    ans =

    1.1971e-03
    1.1971e-03
    1.1971e-03
    1.1500e-03         <------------------------ outlier ratio
    1.1971e-03
    1.1971e-03
    1.1971e-03

    So apparently the value xacc =  -2.0000e+00, resulted in the value xacc_calibrated = -2.3000e-03, instead of the correct value -2.3942e-03 .

    Can you see something wrong or some possible source of error?

    By the way, at first I thought these were either UART errors or an error in the UARTprintf_float() routine I'm using to print out floating point numbers, but the point is that removing MATLAB from the chain and placing the whole processing on the Tiva still shows wrong results due to these outliers... anyway I can post the UARTprintf_float() code if you want to take a look...

    Thanks!

  • I fed your errant values into my little floating point testcase (posted earlier) and got:

    Raw: -2.000000, Multiplier 0.001197
    Result: -0.002394
    Ratio: 0.001197

    so it looks as if the basic calculation, at least for me, is fine.

    A few months ago, I spent a Friday afternoon working on adding "%f" support to UARTprintf. I expected this would be easy but a bit of research and a couple of failed attempts to implement code that gave the expected output in all cases and performed the correct rounding showed me that converting floating point numbers to text is a very complex issue indeed. Based on this experience, I used the C runtime "snprintf" function to format the floating point results in my test rather than a home-baked function and I would suggest that you try this too in case your UARTprintf_float() implementation suffered from the same kind of problems that my equivalent did.

    Another option would be to read the actual 32-bit float value in hex and manually decode it to determine what it represents. This could be messy by hand but there's a site here that claims to perform this conversion online and which may offer a good crosscheck.

  • Dave,

    I think that the function printing the floating point numbers is not the problem (as I mentioned I moved the whole processing on the Tiva and I'm still getting wrong processing results due to floating point error outliers). 

    Right now I cannot test firmware modifications on my Tiva and I thus cannot provide further debugging results. I will post here as soon as I have access to my Tiva again!!

    Thanks a lot in the meanwhile.

    Francesco

  • Dave,

    You mentioned that, "A few months ago, I spent a Friday afternoon working on adding "%f" support to UARTprintf". I had to stop and write about how ambitious that is. The %f support to UARTprintf has cost the community in questions, time spent going the wrong way and workarounds many hundreds of hours. It would have cost TI hundreds of hours too in support. If indeed a much requested feature as %f support to UARTprintf could be done in an efficient and clean manner in even 1 day it would be a small miracle.

    Not sure what my point is, but I think it centers around the general belief than in a day a function can be implemented in a weekend an entire application can be generated, when studies have shown that a couple of line of code per day is more like it.Software looks deceptively like anything can be done in a Friday afternoon, but in practice the same task will take 2 weeks to define, implement and unit test (and quite some time to validate in the final product).

    Regards, Vito

  • Vito,

      Occasionally, I'll spend a Friday afternoon working on some feature that would be good to have but which isn't considered particularly vital. %f support falls into that category and the work I did that afternoon convinced me that it would not be worthwhile spending the effort required to do the job. The code would be large, significant development time would be necessary, and the usefulness would be debatable especially given that all our supported toolchains have C runtime libraries containing full sprintf support already.


      The work I did on this showed me that the scope of the problem was far wider than could easily be accomplished using extra hours here and there so I abandoned the side project. The studies I've seen seem to quote about 10 to 15 lines of designed, tested, documented end-product code per programmer-day and I suspect that isn't too far from the truth. Remember, though, that individual programmer productivity can vary enormously :-)

  • Hi Dave,

    I thought you were talking about finishing it off in one afternoon.

    I don't find the missing %f for UARTprintf a problem since Instead of:

        UARTprintf("The float = %f", theFloat);

    I write:

        sprintf(theString, "%f", theFloat);

        UARTprintf("The float = %s", theString);

    The problem is for newcomers who are not aware of the limitation and fall into a trap. From memory, it doesn't even report an error.

    BTW, wouldn't be just a matter of cutting and pasting the code out of sprintf into UARTprintf (or calling a common function)? This contradicts my earlier assertion about things are never as easy as they first look and probably duplicates what you already said.

    Regards, Vito

  • I'm glad we agree on the best solution to the problem! As regards cutting and pasting the sprintf code into UARTprintf, although that may work. I'm sure there would be licensing concerns!