Pages: 1 [2] 3   Go Down
Author Topic: Concatenate Float w/ a String  (Read 4075 times)
0 Members and 1 Guest are viewing this topic.
Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 792
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Getting people to think about other ways to approach a problem and practice their problem solving skills through critical thinking is nothing to scoff at. Stuff like this also helps highlight the limitations of the hardware and encourages to think about it while they are writing their code.

That's like telling me that, although I always USED to start my car by turning the key, I now have to do it by opening the hood and jumping the starter relay and yanking on the throttle cable.

Working around the missing floating point support is not "sharpening critical thinking skills", it's a waste of time.

Now, I fully agree... IF a person is running up against the memory limit and simply cannot spare another 1.5K, then there's no choice. But otherwise, why not do it the "right way"?

The reason I am so adamant about this is that when I first ran across the "problem", it drove me nuts. I KNEW I was using the "sprintf" format characters properly, but all I was getting was a question mark. Everything else worked (decimals, hex, etc...) so I HAD to be doing something wrong (so I thought). I spent (wasted) close to a WEEK trying to figure out what I was doing wrong. I had a project to finish (not a toy robot, but a real job that I was being paid to do) and I was stuck with the stupid sprintf problem (and I simply was not going to output data with line after line after line of "Serial.print(a_little_piece)" to build up a simple string).

I searched. I Googled. I tried the same code in the GCC compiler for Linux. It worked, so I was sure it was right. Hmmm maybe the Arduino board was bad. So I go and buy another one and had the same problem (i.e. wasted $50 of my customer's money).

Finally, in desperation, I asked about it here... never in a million years would I have guessed that %f was disabled to save a few bytes of code.

After many of the same type of replies (use parsing kludges, use strtof(), etc... finally someone told me the simple fact that floating point was left out on purpose.

I was FURIOUS! How absolutely absurd to do that and not give the user an option to enable it or disable it. And how absurd not to have it documented anywhere!!!

I understand WHY it was left out, but it should have at least had the option to use it or not. And it should be documented!

So, now that I know the problem (and the solution), I see others on here every other day with the same problem and they are given the same advice - kludge it.

User after user faces the same problem and asks the same question, yet the option (which is all of about 5 lines of JAVA code) isn't put into the IDE.

When I offer a simple modification to give the user a checkbox to enable or disable floating point support, everyone starts yelling "My code is 31K already and I just can't spare another byte!"

Baloney! Again, to use the car analogy, it's like buying a new car and then trying to start it, but not finding any place to insert the key. You KNOW there MUST be a key slot SOMEWHERE (all cars have them!), but you look and look and just can't find it. Finally in frustration, you call the dealer and they tell you "Oh your model doesn't have a key - the manufacturer left it out to save weight - gas mileage you know?" and then "There is a jumper cable in the trunk - open the hood and jump the starter".

Are you SERIOUS??? That is completely unacceptable!

I can't speak for others, but I personally do not enjoy beating my head against the wall... especially when there is nothing to gain by doing so.
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3368
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What you said makes sense, except that limitation does not exist if they use up to date hardware. The mega came out ages ago then there was the mega 2560. Now we have the DUE.

... And more expensive. Not every project needs a $10 microcontroller, especially if I can spend ~$1 on an ATTiny and accomplish what I need to with a simple "kludge"

Quote
Seeing as the overall goal of Arduino is to create prototype systems that may warrant actual development I don't see why the additional detail in data(i mean floating point data) availability should be limited.

I've always seen Arduino as a entry point to get people into the world of microcontrollers. If I want to actually put something into development, it wouldn't make much sense to spend 10x the amount on the chip for additional software support that can be handled with a "kludge" like this:

Code:
const int precision = 100;
int psuedoFloat = myFloat * precision ;
sprintf(buffer, "My Float: %d.%d", psuedoFloat / precision , psuedoFloat % precision);
« Last Edit: February 18, 2013, 12:19:46 am by Arrch » Logged

Anaheim CA.
Offline Offline
Faraday Member
**
Karma: 46
Posts: 2865
...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Personally I find no issue with using C style strings. I am a NEWBIE to C and C++ and although the Strings are handy (lazy?) when it comes to C or C++, learning how to deal with array's or C style strings is much more important than saving a line of typing to waste 1.5K of program memory. The function to deal with that bad old issue... could well be a macro saved in what I call a "Snippet Library" (I use a sketch and add code as I find it and prove it). Keeping it in a sketch works for me as a macro/code library.
I am NOT defending the POOR choice made by the Arduino development team, not by any means but with 2K of sram in an Uno you encourage people with less programming experience than you to make uninformed decisions that waste more time than simply learning how to deal with simple arrays and the rather simple Arduino Crutch that makes sprintf work...
Time spent by the person writing the sketch to as well as the people involved in debugging it. wasted.

Bob
Logged

--> WA7EMS <--
“The solution of every problem is another problem.” -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Isn't this meant to be an easy to use platform?   
Sure. But take a look at the Arduino-specific functions, like digitalRead() and analogRead(). What types do those functions return? What about millis()? micros()? Can you find a single Arduino-specific function that returns a float?
Logged

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 792
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sure. But take a look at the Arduino-specific functions, like digitalRead() and analogRead(). What types do those functions return? What about millis()? micros()? Can you find a single Arduino-specific function that returns a float?

I'm beating the dead horse but......

A lot of the programs that I write are for student projects or for lab hardware. Lots of these have a user interface (usually a serial terminal).

The interface is usually arranged as menu pages with individual choices on each page.

Many of these menu pages display things like "Setting 1 is xxx.xx, Setting 2 is yyy.yy", etc. Usually there are many options to set and most of these are floating point values (like one I did the user can set individual solenoid valves to go "on" or "off" with intervals ranging from 0.01 seconds to 99.9 seconds).

So you can imagine what a nightmare it would be to generate a menu page with dozens of individual Serial.print calls to build up each little piece.

Instead, a simple sprintf mask does the whole thing in one shot.

Here is one function from one of my programs. The program has DOZENS of pieces like this:

Code:
// menu: set serial baud rate
void set_baud_rate(void)
{
        byte x;
        const char *message[2] = {
                PSTR("     SETUP MODE     "),
                PSTR("SET SERIAL BAUD RATE")
        };
        lcd_print(message);
        update_params(); // refresh params from EEPROM
        cls(); // clear terminal screen
        const char *menu[5] = {
                PSTR(
                        "\r\n  Four Channel Independent Controller - Serial baud rate\r\n"
                        "\r\n  Current serial rate is %ld baud."
                ),
                PSTR(
                        "\r\n"
                        "\r\n"
                        "  Please select an option:\r\n"
                        "\r\n"
                ),
                PSTR("    (%d)  %6ld Baud\r\n\r\n"),
                PSTR(
                        "    (enter) Return to main menu\r\n"
                        "\r\n"
                        "    Option: "
                ),
                PSTR(
                        "\r    Setting serial rate to %ld baud\r\n"
                        "\r\n    You must reconfigure your terminal baud rate now! "
                )
        };
        sprintf_P(buffer, menu[0], baud_rate);
        Serial.print(buffer);
        sprintf_P(buffer, menu[1]);
        Serial.print(buffer);

        // print available baud rates
        for(x = 0; x < (sizeof(rates) / sizeof(unsigned long int)); x++) {
                sprintf_P(buffer, menu[2], (x + 1), rates[x]);
                Serial.print(buffer);
        }

        sprintf_P(buffer, menu[3]);
        Serial.print(buffer);
        param = get_user_input();

        switch((int) param) {
        case 0:
                do_menu();
                break;
        default:
                if((int)(param) > (sizeof(rates) / sizeof(unsigned long int))) {
                        unrecognized_cmd();

                } else {
                        sprintf_P(buffer, menu[4], rates[(int)(param-1)]);
                        Serial.print(buffer);
                        _delay_ms(5000);
                        EEPROM.writeWord(baud,(int)(param-1));
                        _delay_ms(100); // let EEPROM write finish
                        asm volatile(" jmp 0");  // restart program
                }

                break;
        }
}

Can you imagine the mess I would have if I used dozens of individual Serial.print calls to build up all that text? And this particular menu doesn't even use floating point numbers!  smiley
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 792
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've always seen Arduino as a entry point to get people into the world of microcontrollers.

The Arduino also fits very well into the student / university niche. It's easy enough for a beginner to learn on, and it's powerful enough to build many different kinds  of "teaching aids" (lab experiments).

I may do an Arduino project as a prototype, then have to build 16, 24 or more of the same thing to be used as teaching lab hardware. The project is (probably) too small to justify making a custom PC board and, besides, why re-invent the wheel? The Arduino board works out of the box.

As I've said before, I completely understand why the floating point code was left out. What is "wrong" is that this (very important) fact is not officially documented anywhere and there is no user friendly (i.e. in the IDE) way to enable or disable it.

Countless hours have been collectively wasted by people trying to do something that should certainly work, but strangely does not. It should at least be documented.

The user should have the choice to use floating point code at the expense of code size, or to not use it. IMHO.

Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 792
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sure. But take a look at the Arduino-specific functions, like digitalRead() and analogRead(). What types do those functions return? What about millis()? micros()? Can you find a single Arduino-specific function that returns a float?

Well then why not get rid of the "float" and "double" datatypes? It could save another 500 bytes I'm certain!

After all, nobody uses floats, right?
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3368
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As I've said before, I completely understand why the floating point code was left out. What is "wrong" is that this (very important) fact is not officially documented anywhere and there is no user friendly (i.e. in the IDE) way to enable or disable it.

Countless hours have been collectively wasted by people trying to do something that should certainly work, but strangely does not. It should at least be documented.

Well my experience was completely different: I tried using sprintf() for a float, got some undesirable results, googled it, which lead me to a thread on these forums informing me that sprintf() didn't work with floats. I then spent 2 minutes developing my single line "kludge".
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
... And more expensive. Not every project needs a $10 micro-controller, especially if I can spend ~$1 on an ATTiny and accomplish what I need to with a simple "kludge"
I understand the cost point here but that isnt the problem. Thats why I love arduino's compatibility features with several different micro-controllers. The point here is I spent the money on a mega why am I not allowed to use floats naturally without an ugly kludge or including some third party modifications?

It should be a documented step to enable, or like the very nice edit a checkbox. I would uncheck that box when working with tinys or unos.

Quote
it wouldn't make much sense to spend 10x the amount on the chip for additional software support that can be handled with a "kludge" like this

10x? Really? The mega cost me just under double the price of the uno. I'm not sure about the actual controller but if i was a large company and buying in bulk this wouldn't come close to 10x the cost. Again I don't see why I'm not allowed to make the decision to have floats.

Kludges are a problem. I expect a C++ programmer to be able to pickup an Arduino sketch and have a go. Suddenly they see some weird code which needs to be included either once(A function) or every time a float is used. This leads to backwards learning.

Quote
Sure. But take a look at the Arduino-specific functions, like digitalRead() and analogRead(). What types do those functions return? What about millis()? micros()? Can you find a single Arduino-specific function that returns a float?

Allow me to quote the arduino home page:
Quote
Arduino can sense the environment by receiving input from a variety of sensors and can affect its surroundings by controlling lights, motors, and other actuators.

How many sensors are you aware of that output floats? GPS,Accelerometers,Gyros, I even saw a geiger counter shield.

I get what you are saying, I guess the point here is. I want the option to enable them and disable them at will. Most of the time its disabled.

Something else from the main website:
Quote
Simple, clear programming environment - The Arduino programming environment is easy-to-use for beginners, yet flexible enough for advanced users to take advantage of as well.

Well I want to as what i would consider myself to be( an advanced user) want take advantage of floats in sprintf and thanks to a third party I can. smiley
« Last Edit: February 18, 2013, 07:34:09 pm by ahref » Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3368
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

without an ugly kludge or including some third party modifications?
You keep using the word "kludge", but I don't think that's really what is; you're just writing the code that the function would normally do for you; it's not that complicated. My workaround requires only a single extra line of code and 2-4 bytes of memory.

Quote
10x? Really? The mega cost me just under double the price of the uno. I'm not sure about the actual controller but if i was a large company and buying in bulk this wouldn't come close to 10x the cost.

Cost of an ATTiny84/85 - ~$1
Cost of an ATMega1280 - ~$10

You were talking about production, so I priced base on the microcontroller.

Quote
Kludges are a problem. I expect a C++ programmer to be able to pickup an Arduino sketch and have a go. Suddenly they see some weird code which needs to be included either once(A function) or every time a float is used. This leads to backwards learning.

How is it backwards learning? You aren't given the crutch, so you have to build it yourself. Learning math isn't just about learning how to use a calculator.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If were talking about a project that could do with a 1280 I don't know why we are comparing it to the price of a tiny with a lot less processing power that will probably fall short anyway. Regardless. Its still my choice to throw money around and have enough power to throw floats around. I think that solves the money problem.

Your Kludge is a kludge.
Quote
A kludge (or kluge) is a workaround, a quick-and-dirty solution, a clumsy, inelegant, difficult to extend, hard to maintain yet effective and quick solution to a problem, and a rough synonym to the terms "jury rig", "Jugaad" or "jerry rig".

which leads me to backwards learning, I mean if someone sees your kludge and they aren't aware of the lack of float support they will most likely come to your desk and ask you what is going on. Instead you could enable floating support because your platform obviously needs it if you are writing that code.

Without wanting to flog a dead horse here i'll make it brief, The option to enable floats should be a part of the arduino core. Do you have any arguments to just that sentence that make it not being an option logical?
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3368
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If were talking about a project that could do with a 1280 I don't know why we are comparing it to the price of a tiny with a lot less processing power that will probably fall short anyway.
Like it has in all my projects  smiley-roll
Quote
Regardless. Its still my choice to throw money around and have enough power to throw floats around. I think that solves the money problem.
Well then, sticking to prototyping is ideal for you.

Quote
A kludge (or kluge) is a workaround, a quick-and-dirty solution, a clumsy, inelegant, difficult to extend, hard to maintain yet effective and quick solution to a problem, and a rough synonym to the terms "jury rig", "Jugaad" or "jerry rig".

Without saying "you should be able to already do this with sprintf()" (which makes it a workaround, not a kludge), explain how my workaround is inelegant, klumsy and difficult to extend?

Quote
which leads me to backwards learning, I mean if someone sees your kludge and they aren't aware of the lack of float support they will most likely come to your desk and ask you what is going on. Instead you could enable floating support because your platform obviously needs it if you are writing that code.

Then why not use a device that has an FPU? Hell, you could consider the entire floating point software suite for the Arduinos as a kludge.

Quote
Without wanting to flog a dead horse here i'll make it brief, The option to enable floats should be a part of the arduino core. Do you have any arguments to just that sentence that make it not being an option logical?

I tend to avoid doing floating point calculations in my projects, so I have no need to enable it. If enough people care about this lack of option and complain to the developers that it should be included, I'm not going to argue against it.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I tend to avoid doing floating point calculations in my projects, so I have no need to enable it. If enough people care about this lack of option and complain to the developers that it should be included, I'm not going to argue against it.

That is fair smiley. So let's get it as a valid option smiley-grin!
Logged

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 792
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It should be a documented step to enable, or like the very nice edit a checkbox. I would uncheck that box when working with tinys or unos.

Grab this file: https://github.com/krupski/arduino-1.0.3/blob/master/app/pde.jar

Backup your pde.jar file and replace it with this one. It adds a checkbox in Preferences to enable or disable floating point support (i.e. using %f).

It works with Arduino 1.0.0 to 1.0.3.
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did this the moment I saw it krup. Many thanks for the github link though. I find it more reliable than your site smiley
Logged

Pages: 1 [2] 3   Go Up
Jump to: