Jump to content
yellamo

String Concatenation with Long

Recommended Posts

Hi Guys,

 

I've posted an issue over on the Ti website but they have suggested posting in an Energia forum too.

 

The issue I am seeing is when concatenating a string and a long number. It either goes one of two ways - the value is zeros, or the numbers following the decimal point are missing.

 

https://e2e.ti.com/support/wireless_connectivity/f/968/t/414222

//This works fine
static float diet = tmp006.readDieTempC();
Serial.print("Die Temperature: "); Serial.print(diet); Serial.println("*C");

//This doesnt
String pubString = "Temperature " + long(diet);
Serial.print(pubString);

The following gives zeros:

String pubString = "Temperature Test ";
  
pubString  += diet;

Serial.print(pubString);

Thanks

 

Share this post


Link to post
Share on other sites

When you cast a float to a long there is no surprise that the numbers after the decimal separator are missing; you explicitly tell your compiler to add this behaviour.

 

The zeroes are odd, though you must expect String to not work nicely on embedded platforms; concatenating to a string will reallocate memory to expand the required memory to accommodate the new size. Since this will require free space (heap) management, thing get ugly with restricted memory.

Do you really need to format your string in your embedded platform, or could a PC user interface do it as well?

If you really need to format the string on the embedded platform, do you really need to have it formatted in memory, or is formatted over the serial line fine too (like you're doing in your first example)?

If you really must use embedded formatting, you'd better use a c-string (char array) instead of String, since it's much easier to manage the size beforehand and uses lighter functions for the formatting.

//This does, but it leaves out the decimal separator
String pubString = "Temperature " + long(diet * 1000) + "m*C";
Serial.print(pubString);

// This does too, but uses c-string
char pubString[] = "Temperature xx.xxx*C";
sprintf(pubString + 12, "%6.3f*C", diet);
Serial.print(pubString);

Share this post


Link to post
Share on other sites

Hi RoadRunner,

 

Thanks for the helpful reply.

 

Ultimately I want to construct a string of multiple values which can be posted as a JSON value.

 

I have tried both the examples and the second one is very good, but I am having the same issue with this bit of code - it works fine in a new sketch, but once I add this into my sketch with all the code in, it returns zeros! The same goes for another piece of code suggested there too:

String pubString7;
char buffer1[8];
float diet1 = 40.05;

sprintf(buffer1, "%.2f", diet1);
pubString7 = "\r\n\Temperature Test : ";
pubString7 += buffer1;
Serial.println(pubString7);

I am just about to reply over there, but it was originally looking like an issue with SPI.h. Here are my imports (which does not make a difference on my main sketch:

#ifndef __CC3200R1M1RGC__
#endif
#include <WiFi.h>
#include <PubSubClient.h>
#include <math.h>
#include "Adafruit_TMP006.h"
#include <Wire.h>
#include <stdlib.h>

Any help greatly appreciated.

 

Thanks

Share this post


Link to post
Share on other sites

Ultimately I want to construct a string of multiple values which can be posted as a JSON value.

Which should work fine if you just format it on the line, instead of in memory.

I have tried both the examples and the second one is very good, but I am having the same issue with this bit of code - it works fine in a new sketch, but once I add this into my sketch with all the code in, it returns zeros! The same goes for another piece of code suggested there too:

This most probably indicates you're running out of memory. If the code is identical in a separate application as in the integrated one, there must be something that hogs your memory and causes some kind of overflow.

String pubString7;
char buffer1[8];
float diet1 = 40.05;

sprintf(buffer1, "%.2f", diet1);
pubString7 = "\r\n\Temperature Test : ";
pubString7 += buffer1;
Serial.println(pubString7);

You're not doing the same as I suggested. The essential difference is that in my example the String is declared with all concatenation in place, no concatenation thereafter. As a result, the compiler does never have to reallocate memory, which in worst case could require up to three times the memory for the resulting string.

int color = 123;
int styleId = 4;
String text = "foobar";
Serial.print("{\"color\":\"");
Serial.print(color);
Serial.print("\", \"style_id\":\"");
Serial.print(styleId);
Serial.print("\", \"text\":\"");
Serial.print(text);
Serial.println("\"}");
// {"color":"123", "style_id":"4", "text":"foobar"}

What's wrong with this for formatting JSON?

Share this post


Link to post
Share on other sites

Thanks @@roadrunner84,

 

The issue is with the float. I can construct the JSON fine in string, but everything after the decimal point in the float is trimmed.

static float diet = tmp006.readDieTempC();

//This Displays fine - from standard TMP006 Example
Serial.print("Die Temperature: "); Serial.print(diet); Serial.println("*C");
   
//This example with "long" will only give a value before decimal, as exptected, but I need the exact value eg. 20.12.
String pubString = "{\r\n\"abc\":" + String1 + ",\r\n\"temp\":" + long(diet) + ",\r\n\"def\":" + String2 + "\r\n}";

//What I get {"abc":"123456", "temp":"20", "def":"1234"}
//What I Need {"abc":"123456", "temp":"20.24", "def":"1234"}

I am trying to get the float value of diet into a string, but all efforts within my sketch make it be "0.00". When I try your examples and those from ti.com, they work fine in a new sketch, but not in mine, even if I do this at the very start of the program..

Thanks

Share this post


Link to post
Share on other sites

Look at my signature, it says: Never use floating points in embedded systems.

It's a bit if a crude statement, but what it means is, floating point types make your system big and slow. Unless you have a floating point processor (which the msp430 does NOT have), try to avoid them wherever possible.

If there is no way to read 100ths or 1000ths of degrees as an integer, move away from floating point as fast as possible.

int deg, deg100;
char diet[8];
deg100 = modf(tmp006.readDieTempC(), °) * 100;
sprintf(diet, "%u.%02u", deg, deg100);
String pubString = "{\r\n\"abc\":" + String1 + ",\r\n\"temp\":" + diet + ",\r\n\"def\":" + String2 + "\r\n}";

another approach:

int raw = tmp006.readRawDieTemperature();
int deg100 = raw * 3 + (raw >> 3); // at this point, deg100 holds 100ths of degrees
deg = raw >> 5;
deg100 -= deg * 100;

Share this post


Link to post
Share on other sites

Hi @@roadrunner84,

 

Sorry for the delay getting back!

 

Thanks for the pointers about the float.

 

I've tried the code, had to change the ints to double as there was an error, and getting the following output - I've got a digital themomethere here and it is showing 21c.

double deg, deg100;
char diet[8];
deg100 = modf(tmp006.readDieTempC(), °) * 100;
sprintf(diet, "%u.%02u", deg, deg100);

Serial.print("\r\n\DIET ");Serial.print(diet);

The error with the int was as follows:

 

error: cannot convert 'int*' to 'double*' for argument '2' to 'double modf(double, double*)'
 

Thanks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×