Energia - Float to string? - Page 1
Forum section: electronics / general

author: Jon86
author_rank: Frequent Contributor
timestamp: November 01, 2013, 10:45:15 pm
content: My project's come to a halt now. I'm trying to do something very simple, take the output of a temperature sensor and write it to an SD Card. I've got all the code working, 100 sample averaging and I can write strings to the card just fine, but I can't convert the float average temperature value to a string needed by the card library...Also, I'm using the Energia IDE and an MSP430G2553.

author: nctnico
author_rank: Super Contributor
timestamp: November 01, 2013, 10:48:49 pm
content: Use snprintffloat valuechar bufsnprintf(buf, sizeof(buf), "%f", value);After this buf will have a string representing the value.

author: Jon86
author_rank: Frequent Contributor
timestamp: November 01, 2013, 10:59:46 pm
content: No luck, I just get %f ó ÒÐ tÀžÃtÀ on the SD Card...Code:float value = 21.54;char buf;snprintf(buf, sizeof(buf), "%f", value);rc = FatFs.write(buf, 20, &bw);

author: Jon86
author_rank: Frequent Contributor
timestamp: November 01, 2013, 11:37:20 pm
content: If I swap out 'buf' in the write statement to "21.54" it works fine and writes to the card, but if I use 21.54 it gives me an incompatibility error, and with buf it seems to just write out whatever's in the format section of snprintf.

author: tanstaafl
author_rank: Contributor
timestamp: November 01, 2013, 11:46:02 pm
content: Quote from: Jon86 on November 01, 2013, 11:37:20 pmThat it writes out the format section tells me that your compiler isn't set to using full printf support, that is usually switched off when building for microcontrollers since it takes quite a lot of space to support floats...

author: Jon86
author_rank: Frequent Contributor
timestamp: November 01, 2013, 11:47:51 pm
content: Quote from: wilfred on November 01, 2013, 11:42:59 pmAh sorry I misread your last post, I'm incredibly tired...First one does exactly the same thing as before, and the second throws me a compiler error.

author: Jon86
author_rank: Frequent Contributor
timestamp: November 01, 2013, 11:48:37 pm
content: Quote from: tanstaafl on November 01, 2013, 11:46:02 pmAha! Is there any way to turn it on in Energia?

author: nctnico
author_rank: Super Contributor
timestamp: November 01, 2013, 11:55:53 pm
content: Quote from: wilfred on November 01, 2013, 11:42:59 pmBoth completely wrong!snprintf(buf, sizeof(buf), "%f", value); must work otherwise there are other (bigger problems).@Jon86:Put a line which saysbuf=0;before the snprintf. This initialises buf to a zero length string. If you get no output then the snprintf is somehow ignored. Also change FatFs.write(buf, 20, &bw) to FatFs.write(buf, strlen(buf), &bw). Please get familiar with how C strings work!It could be possible that the C library doesn't support floating point. Perhaps its best to post this question on the energia forum.

author: IanB
author_rank: Super Contributor
timestamp: November 02, 2013, 12:01:29 am
content: If you are doing simple arithmetic on a microcontroller it may not be appropriate to bring in the complexity of floating point arithmetic and floating point library support.You could consider using integers and fixed point arithmetic instead, and then conversion to a string would be much easier. You could use itoa() and some simple character processing to put the decimal point in the right place.

author: Jon86
author_rank: Frequent Contributor
timestamp: November 02, 2013, 12:06:28 am
content: Don't be too hard on me, I don't do much programmingAnyway, now it just outputs %fI've posted in the SD Card thread over on the Energia forums, but no reply yet. I might just make a thread tomorrow...

author: Jon86
author_rank: Frequent Contributor
timestamp: November 02, 2013, 12:08:03 am
content: Quote from: IanB on November 02, 2013, 12:01:29 amThat sounds like a good path to take. I've already had a look around but I can't really find anything on doing it that way, have you got any pointers?

author: tanstaafl
author_rank: Contributor
timestamp: November 02, 2013, 12:09:04 am
content: No idea, never used it...For CCStudio it is a command line option:http://processors.wiki.ti.com/index.php/Printf_support_in_compiler. Could also be that you need to link to a different library.Another possibility would be to not use floats at all, something likehttp://forum.43oh.com/topic/1954-using-the-internal-temperature-sensor/

author: Jon86
author_rank: Frequent Contributor
timestamp: November 02, 2013, 12:15:26 am
content: Quote from: tanstaafl on November 02, 2013, 12:09:04 amThanks, I'll look into that.I'll try it without floats, it's only a bit of simple maths so I guess it shouldn't be too complicated. All that C code is making no sense to me though...

author: tanstaafl
author_rank: Contributor
timestamp: November 02, 2013, 12:19:25 am
content: mmm maybe this one instead, it's a example from energiahttps://github.com/energia/Energia/blob/master/examples/3.Analog/AnalogInput_InternalThermometer_430/AnalogInput_InternalThermometer_430.ino

author: Jon86
author_rank: Frequent Contributor
timestamp: November 02, 2013, 12:31:37 am
content: Now that makes a bit more senseThanks for your help, I'm going to get a couple of hours sleep then have another go at this tomorrow. I'll get back to you if it doesn't work, I'm sure it won't, Murphy's out to get me!

author: westfw
author_rank: Super Contributor
timestamp: November 02, 2013, 01:16:41 am
content: QuoteIt's very common for small microcontroller environments to provide a version of printf/etc that does NOT include the floating point functions; this results in much smaller program sizes, especially if floating point is not used elsewhere. There's usually a simple link option to get the full-featured printf, but simplified IDEs like Arduino/Energia make that hard to modify.You could do something like:Code:print_float(float f) {int int_part, fraction;int_part = (int) f;fraction = (f - int_part) * 1000.0; // three digits after decimal.printf("%d.%03d", int_part, fraction);}

author: Jon86
author_rank: Frequent Contributor
timestamp: November 02, 2013, 08:32:53 am
content: IT WORKS! (I think)Ideal, thanks westfw

author: dannyf
author_rank: Super Contributor
timestamp: November 03, 2013, 01:25:35 am
content: Using printf takes up lots of space / time.I would use something like itoa() or a specialized version of it.

author: nctnico
author_rank: Super Contributor
timestamp: November 03, 2013, 07:31:24 am
content: That is not a good idea. You'll want some formatting so sooner or later you'll pull in vsprintf and in the meantime wasted lots of time of coming up with non-standard solutions which makes the software much harder to maintain. I've seen it happen and go wrong many times. The best way is to stick with a Posix compliant C environment (use the standard C library). In other words: if printf from the standard C library is too big, make your own printf which supports the bare minimum. Its not that hard:https://github.com/mludvig/mini-printf/blob/master/mini-printf.c

author: Jon86
author_rank: Frequent Contributor
timestamp: November 03, 2013, 08:21:57 am
content: I'm sure you're right, but this is just a (kind of) simple project I want to do quickly and forget about, I'm moving to a different IDE after this so I guess I'll learn how to do all this properly when I do that. I expect this will be easy in code composer studioThanks for the help

author: dannyf
author_rank: Super Contributor
timestamp: November 03, 2013, 08:58:03 pm
content: QuoteIt will fail if the float type is negative.But the general idea is correct: decompose the float type into an integer + fraction and then process each individual (preferably with itoa()) to minimize foot print.QuoteThe solution is compiler dependent, regardless of the IDE used.

author: westfw
author_rank: Super Contributor
timestamp: November 04, 2013, 03:11:36 am
content: QuoteYep. It also fails if the magnitude is too big for an int, or smaller than 0.001, which are well within the range handled by floats. That's how you save space, by knowing something about your actual data. Likewise, that's a lot of why the usual printf implementations are so large (in addition to sucking in FP libraries.)

author: nctnico
author_rank: Super Contributor
timestamp: November 04, 2013, 11:34:31 am
content: And there are rounding issues as well. 0.0001 to 0.0009 will be printed as 0 because the decimals are truncated when converting from float to integer. You'd need to use the round function (slow) or add/stubstract 0.0005 (fast) to the floating point number for proper rounding.

author: tszaboo
author_rank: Super Contributor
timestamp: November 07, 2013, 06:29:29 pm
content: You can store the data in milikelvins, and then no floating point is needed. You should not need float for temperature, but I've seen others doing this on 8 bit (with compensation), because they are LAZY.

author: dannyf
author_rank: Super Contributor
timestamp: November 07, 2013, 09:13:30 pm
content: QuoteWhy milikevins? It is too complicated. Why not just 2-based Kelvins? Like Kelvinx16, or Kelvinx8, etc.: much easier to process.

author: IanB
author_rank: Super Contributor
timestamp: November 09, 2013, 08:14:40 pm
content: Indeed.If you sample a value from an A-D converter you will get an 8 bit or 12 bit scaled quantity. That is your raw data and it also represents the inherent precision of your sampled value. If you are going to do processing like filtering or averaging you may as well do it in the scaled integer space corresponding to your input device and convert it for display at the last moment. (This is how many control systems and PLCs work internally. They don't work with floating point as it is unnecessarily expensive.)For instance, suppose you want to take an average of eight samples. You simply sum each of your samples into an accumulator until you have eight of them stored. To get the average you need to divide the result by 8 which is a simple matter of shifting right by 3 bits. Shifting and adding are very fast operations on all processors.As a matter of interest I did this in 1984 during my final year lab project for my engineering degree. I had a laboratory scale glass distillation column and an 8 bit microcomputer running a version of tiny BASIC that only had integer variables. I could measure the temperature at the top of the column using an 8 bit analog input from a temperature sensor and I could control the reflux flow with a digital output that would open and close a solenoid valve. A single reading from the temperature sensor only gave me a temperature precise to 1 degree with a lot of random noise. So I took several readings in succession and averaged them, giving me a much more stable reading precise to about 0.1 degrees. I then implemented a PI control algorithm and used it to adjust the reflux flow by PWM on the reflux valve. All was done in 16 bit integer arithmetic with no floating point available. It worked fine and I could could regulate the temperature at the desired set point.