|
|
View previous topic :: View next topic |
Author |
Message |
Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
Question on sending a floating point value to Hyperterminal |
Posted: Sun Mar 29, 2015 8:16 pm |
|
|
Greetings all,
Having great fun connecting our newly built TTL to 232 converter board between the PC and the 877a processor and sending text to Hyperterminal. With integers 8 and 16, and of course text it works fantastic. But I tried a floating point number and I get nothing close!
I would assume that sending a floating value to an LCD is the same issue. Where have I gone horribly wrong here? An example is when I send a value of say 1.8 I got some huge 10 digit number with one decimal with
%3.1w in the print statement. So I tried just plain number 2. Got 12.8 on the screen. Oh my.
Here is most of the pertinent code, with the silly comments at the top of the program deleted. Help!
Code: | #include <16F877A.h> //Normally chip, math, etc. used is here.
//Directives and Defines:
#device ADC=10 //Set ADC when used to 10 bit = 0 - 1023
#fuses NOPROTECT,HS,NOWDT //xtal is used
#use delay(crystal=10MHz) //xtal speed
#use fast_io(ALL) //must define tris below in main when using this
//for LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N,stream=TERMINAL)
void main(void) {
// Set TRIS I/O directions, define analog inputs, compartors:
set_tris_A(0b11111);
set_tris_B(0b11111000);
set_tris_C(0b11111111);
set_tris_D(0b11111111);
set_tris_E(111);
//(analog inputs digital by default)
//Initialize variables and Outputs: --------------------------------------
output_low(Pin_B0); //status off
delay_ms(1000); //LCD warmup time
int8 n = 255;
int16 x = 50000;
float y = 2;
//----------------------------------------------------------------
//MAIN PROGRAM:
while (true) {
output_high(Pin_B0);
delay_ms(250);
output_low(Pin_B0);
delay_ms(250);
//send message to Terminal:
delay_ms(1000);
fprintf(TERMINAL,"ROBOT BOARD= %u"n); //text plus integer
fprintf(TERMINAL,"\n\r"); //New line, Carrige Return
delay_ms(250);
fprintf(TERMINAL,"Value= %Lu"x); //text plus Int 16 (word)
fprintf(TERMINAL,"\n\r"); //New line, Carrige Return
delay_ms(250);
fprintf(TERMINAL,"floating= %3.1w"y); //text plus floating
fprintf(TERMINAL,"\n\r"); //New line, Carrige Return
delay_ms(250);
} //elihw
} //niam |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
Fprintf |
Posted: Sun Mar 29, 2015 8:59 pm |
|
|
Page 233 at the bottom. That doesn't mean I know how to use it...
What would you use?
Chris |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 29, 2015 9:19 pm |
|
|
There's a table of format specifiers:
Code: |
f Float with truncated decimal
g Float with rounded decimal
e Float in exponential format
w Unsigned int with decimal place inserted. Specify two
numbers for n. The first is a total field width. The
second is the desired number of decimal places. |
So, use "%7.1f" for starters. |
|
|
Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
Float |
Posted: Sun Mar 29, 2015 9:49 pm |
|
|
Ok, I figured it all out. The problem seems to have been the example in the manual is for w AND f for format specifiers, and I got them mixed up.
%f. Works great for 2 numbers after the decimal, and %8.3f easily came out correct on the terminal, with three numbers after the decimal. Only one case now was not quite right - when I defined a float like this:
Float x = 65000.123
And it replaces the last "3" with a zero to give on the terminal:
65000.120
I'll be happy with two decimals, that's more than I'll ever need! Just curious why it did this.
Chris |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 29, 2015 11:15 pm |
|
|
The floating point format used by CCS only has about 7 digits of precision.
CCS uses the 32-bit Microchip floating point format. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Mar 30, 2015 12:54 am |
|
|
You have now met the critical 'problem' of floating point, and why it is not used for things like financial calculations.....
A '32bit float', has 23 bits used for the actual 'number' (it's actually technically a 24bit mantissa, with the top bit always set to '1', with just 23bits stored). So binary numbers from 1000 0000 0000 0000 0000 0000 to 1111 1111 1111 1111 1111 1111 1111. In decimal 8388608 to 16777215. A range of 8388607 possible values. These are then 'scaled' by the exponent, to give the number to be displayed. So just under 7 digits of actual 'accuracy' (6.8 digits), but over an enormous 'range'. It is this large range that can make floats useful, but it comes at a huge cost in accuracy.
Compare (for instance), with a 32bit signed integer value (31 bits for the number). If this is used to store milli-values (so an integer count of 0.001's), it can store a value up to 2147482.646, with _every_ possible value useable. An accuracy of 9.2 digits. So using 'floats' here costs 2.4 digits of numeric accuracy.....
The float is also much harder for the processor to work with. A floating point addition for instance, takes eighty five times longer than the same addition in int32!... The actual code involved is also very much larger (typically at least twice the size for a set of FP maths versus int32).
This is why you will see it often suggested here that it is much better to design your code to use scaled integer maths, rather than floating point.
Now like all things it is not absolute (I use FP, for example on a recent project with a logarithmic scaling on the ADC response, there is no simple substitute), but for 99% of the things seen in this forum, it is safer, simpler, and quicker to design the maths from the start to use integer.
On the 'financial' example, if you are Bill Gates, and happen to want to add up 1000026.66 dollars, with 451021.66 dollars, in int32, using integer 'cents', this will give exactly 1451048.32, while in FP, you will get 1451048.40!. Eight cents too much!....
(Maybe this is how he has made a lot of his money.).
So if you are using fixed point x.xxx values, consider whether you could work in integer 'milli-x' values instead of using float. Financial programs generally do exactly this.
Float's, 'look convenient', but this convenience comes at a cost..... |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: Float |
Posted: Mon Mar 30, 2015 3:43 am |
|
|
Arizona Chris wrote: | %f. Works great for 2 numbers after the decimal, and %8.3f easily came out correct on the terminal, with three numbers after the decimal.
I'll be happy with two decimals, that's more than I'll ever need! |
It's not about the number of decimal places, its about significant figures. The number of sig. figs is directly related to the length of the mantissa in the floating point format. Those sig figs. could have the decimal point anywhere, The more bits in the mantissa, the more sig. figs. Where those sig. figs happen to be in real number space is down the the exponent. So the length of the exponent determines the overall range of floating point, the mantissa length determines the precision.
Floating point has some perhaps unexpected oddites. These vary from floating point format to format. For example, in formats with binary exponents, including the very commom 32 bit IEE754 that most people think of as "THE floating point format", integers, 1, 10, 100 etc, can be precisely represented up to that allows by the length on the mantissa, but "simple" decimals can't, such as 0.1 and 0.01- 0.1 would come out as something like 0.0999997. Binary related decimals, however, are precise: 0.5, 0.0625 etc. So in floating point, 1.0/10.0 * 10.0 is NOT equal to 1.0. However, 1.0/16.0 * 16.0 is equal to 1.0. In floating point formats with decimal exponents (rare these days) it would be the other way round.
If the precision of floating point is "good enough", then its good enough. But don't be too certain that all the errors will be in any particular direction or will somehow cancel each other out. They might not, and culmulative errors can be nasty to fix.
Floating point is also very, very slow compared to integers.
All that said, floating point is very useful, and by no means to be avoided at all costs. You just need to be aware of its limitations, and apply it with care. |
|
|
Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
Floating |
Posted: Mon Mar 30, 2015 6:24 am |
|
|
Thanks for the explanations! You guys are the greatest. 7 figures of precision is awesome as far as I'm concerned. Jay, you are right - for 99 percent of micro apps we need only to use integer math and it does the job admirably. On occasion, for small numbers less than 100, a few decimals can come in handy.
Thanks again for all the very understandable explanations. The past decade I have used only integer math at work, and never needed to do floating. Anyway, PBP won't do it anyway. ;)
Chris |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|