[Solved] String() function not working inside a FreeRTOS task

Hello.

I have this problem when I try to use the String() function to display a double through the arduino serial port. The function works when I use it in the setup() part but not into the task. Could someone explain what is happening to me?

This is my test code:

#include <Arduino_FreeRTOS.h>

void ensayo();

double un_double = 5.6775;

void setup() {
  Serial.begin(9600);
  xTaskCreate(ensayo,  (const portCHAR *)"Ensayo" ,  128 ,  NULL,  1 ,  NULL );
  Serial.println(String(un_double, DEC));
  Serial.println(String(7.99584, DEC));
}

void loop() {}

void ensayo()
{
  for (;;)
  {
    Serial.println(String(un_double, DEC));
    Serial.println(String(7.99584, DEC));
    delay(1000);
  }
}

Thanks in advance.

Could someone explain what is happening to me?

Not yet. The code does something. Only you know what it actually does. You expect the code to do something. Only you know what you expect it to do.

Is it REALLY reasonable to construct a String representation of a value with 10 decimal places?

Why is it necessary to create a String representation to be printed? The print() method knows how to print a float/double.

Pauls, thanks for your answer. I guess it's true, I don't need a 10 decimal places value considering that the value will come from an analogRead and all the noise involved, however the function should work properly into the task "ensayo()".

I see that I didn't explained the situation clearly. This is what I expect: the serial monitor displays un_double then 7.99584 during setup and then it repeats every second. What the code actually does is this: displays un_double then 7.99584 during the setup and after that it displays 2 empty lines every second. I'm asking for an explanation because I don't see any reason for this code to do what it is doing.

I’m asking for an explanation because I don’t see any reason for this code to do what it is doing.

One thing that you are doing is calling the String constructor. That requires dynamic memory allocation. Perhaps there isn’t enough memory available.

What does:

void ensayo()
{
  for (;;)
  {
    Serial.println(un_double, DEC);
    Serial.println(7.99584, DEC);
    delay(1000);
  }
}

accomplish?

PaulS:
What does:

void ensayo()

{
  for (;:wink:
  {
    Serial.println(un_double, DEC);
    Serial.println(7.99584, DEC);
    delay(1000);
  }
}



accomplish?

I wrote that before

Sergio_Restrepo:
it displays 2 empty lines every second

I'm expecting that part to print 5.6774998000 and 7.9958401000 as setup does but repeatedly.

PaulS:
Perhaps there isn't enough memory available.

If that were the case, then something like

void ensayo()
{
  for (;;)
  {
    Serial.println(String(un_double, DEC));
    Serial.println(String(7.99584, DEC));
    Serial.println("some string test message");
    delay(1000);
  }
}

Should not display a thing either, right? but when I try it (the code rigth above) it prints 2 empty lines and the message repeatedly so I think that the problem is String() returning an empty String.
If it is a memory problem then, how could I check/know?

Use of Strings causes memory problems in Arduino. Most people avoid using Strings.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

It is probably even less good when using something like FreeRTOS which will itself use up some of the limited SRAM.

Is FreeRTOS really necessary?

...R

jremington:
Use of Strings causes memory problems in Arduino. Most people avoid using Strings.

+1

If you want something more than Don't Use String™, how about this: dynamic memory allocation is not thread safe.

If you don't know what that means, you can't possibly use String safely. There are many others reasons.

Just print the number. There is no reason to convert a number to characters and then print the characters. The Serial object knows how to do that for you, because it is derived from the Arduino Print class.

Here's the method you are trying to use. Review it and other methods so you know how to call them. Hint: passing DEC as the second argument is wrong.

OK, I won't use the String() function then.
I'll mark this thread as solved but I was just wondering if the fact that Strings are so evil to memory (so they shouldn't be used) makes the question about its failure when used within a FreeRTOS task not worth of an answer. I think that this answer would not be very useful since it came from a need that has been satisfied by some other (better) methods and the knowledge derived from it wouldn't be very helpful. From that perspective, it is understandable why the thread is solved but the question stills lacks an answer.
Thank you all for your help.

Sergio_Restrepo:
OK, I won't use the String() function then.
I'll mark this thread as solved but I was just wondering if the fact that Strings are so evil to memory (so they shouldn't be used) makes the question about its failure when used within a FreeRTOS task not worth of an answer. I think that this answer would not be very useful since it came from a need that has been satisfied by some other (better) methods and the knowledge derived from it wouldn't be very helpful. From that perspective, it is understandable why the thread is solved but the question stills lacks an answer.
Thank you all for your help.

the answer is good-ole C strings

Sergio_Restrepo:
I was just wondering if the fact that Strings are so evil to memory (so they shouldn't be used) makes the question about its failure when used within a FreeRTOS task not worth of an answer.

It might be a good question for the designers of FreeRTOS.

I'll mark this thread as solved but I was just wondering if the fact that Strings are so evil to memory (so they shouldn't be used) makes the question about its failure when used within a FreeRTOS task not worth of an answer.

No. It was a good question. But, you didn't answer all of the questions that were asked, so you can't expect answers to your question, either.

I wrote that before

Apparently, you didn't read the code or try it. The code I posted did NOT convert the double/float to a String, and then print the String. Your response indicates that it would operate exactly the same as your code that did convert the double/float to a String, uselessly, and then print the String.

I say PROVE IT!

In any case, -dev gave the answer.

dynamic memory allocation is not thread safe.

Your unnecessary RTOS (pretends to) use(s) threads. You can not do things in the thread(s) that are not thread-safe.

One thread does not know that another thread has allocated memory. You don't know which thread Serial.print() is running in, so you do NOT know whether the memory allocated in the task thread is known to be allocated in the thread that Serial.print() runs in.

If not, then you are effectively dereferencing a NULL pointer, which, on a real OS would throw an exception. The Arduino blindly ignores exceptions, so you ASSume that everything worked as you expected.

PaulS, nothing I could say to apologize for not noting that you posted a whole different code is enough to obtain forgiveness, but still, I apologize.

Yes, under the ligth of your explanation, -dev gave the answer, but your answer is more complete and clear. Thank you for your help.