Surprising increase in global v ariables

The IDE reported that global variables used 1199 bytes (58%).

For temporary debugging I added 18 sets of lines like this to void setup() :

Serial.print("Tracks in folder 01\t"); Serial.print(myDFPlayer.readFileCountsInFolder(1)); Serial.print("\n");
delay(50);

The global variables jumped to 1577 (77%) and I had a 'Low memory..instability..' message.

Should I be surprised at this? If I want to use these variables elsewhere, such as to get a total of those 18 file counts, or in void loop(), must I now define them all again myself? Presumably reducing storage even more?

If it's relevant, I'm using the DFRobot library:```
#include "SoftwareSerial.h"

Were the constant strings the same in each of them ?

From the context of your other topics I would guess not. Make "Tracks in folder " a const global string and see what difference it makes using that

You need to use the f macro in those print statements

1 Like

There were 18 file counts, with an initial header set, i.e:

// TEMP INFO
Serial.print("File counts \t"); Serial.print(myDFPlayer.readFileCounts()); Serial.print("\n");
delay(50);
Serial.print("Tracks in folder 01\t"); Serial.print(myDFPlayer.readFileCountsInFolder(1)); Serial.print("\n");
delay(50);
Serial.print("Tracks in folder 02\t"); Serial.print(myDFPlayer.readFileCountsInFolder(2)); Serial.print("\n");
delay(50);
// etc
// etc
Serial.print("Tracks in folder 18\t"); Serial.print(myDFPlayer.readFileCountsInFolder(18)); Serial.print("\n");
delay(50);

I'm not sure what you mean by Make "Tracks in folder " a const global string, why that would help? And trying any of these three in my initial code all gave errors, presumably because my syntax is wrong?

const char "Tracks in folder ";
String "Tracks in folder ";
String Tracks in folder ;

Thanks @Grumpy_Mike, that fixed it! Back to 1199.

If you declared "Tracks in folder " as a global const string like this

const char * tracksText = "Tracks in folder ";

then the text would only be present once in memory rather than it being there 18 times, thus saving memory

How about a for loop?

Serial.print(F("File counts \t")); 
Serial.print(myDFPlayer.readFileCounts()); 
Serial.print(F("\n"));
delay(50);

for (int i = 1; i <= 18; i++)
{
  Serial.print(F("Tracks in folder "));
  Serial.print(i);
  Serial.print(F("\t"));
  Serial.print(myDFPlayer.readFileCountsInFolder(i)); 
  Serial.print(F("\n"));
  delay(50);
}

By the way, more than one statement per line is discouraged.

1 Like

Does this:
Serial.print(F("\t"));
Really take less memory than:
Serial.print('\t');
?

It takes the same amount of memory but it uses different memory

Thanks, much neater, and working fine.

1 Like

Thanks, got it. But I found no difference in the memory usage. With my original (no F macro, no for loop) it uses:
1615 bytes of dynamic memory (78%, prompting the stability message)
10174 bytes of program storage.
After adding the statement

const char * tracksText = "Tracks in folder ";

the numbers were identical.

Using the F macro gave:
1223 bytes of dynamic memory (59%)
9418 bytes of program storage (29%)
Again, your constant made no difference.

which Is better written as Serial.write('\t');

:wink:

And what about the extra instructions that are needed to get this 1 character from PROGMEM to Serial.print()? OK, those instructions are also in PROGMEM, but still I guess it is not really worth it for one character...

well the function is already loaded for the other prints with the F() macro and a longer text, so you don't eat up more memory for the code, but the pointer will be 2 bytes whereas the char itself is only 1 byte. and if you use write() it's faster.

You don't just add the declaration, you need to use the variable when printing the messages. Did you try that ?

Duh, yes, of course! I have yet to study that asterisk (pointer?) stuff and had assumed it was a sort of #define.

With this replacing my function, your suggestion does indeed give a small reduction, 1255 down to 1249 bytes:

void folderCountsUKH()
{
  /////////// TEMP INFO ON FOLDER COUNTS //////////////////////
  Serial.print("File counts \t");
  Serial.print(myDFPlayer.readFileCounts());
  Serial.print("\n");
  delay(50);

  for (int i = 1; i <= 18; i++)
  {
    Serial.print("tracksText ");
    Serial.print(i);
    Serial.print("\t");
    Serial.print(myDFPlayer.readFileCountsInFolder(i));
    Serial.print("\n");
    delay(50);
  }
}

With the following that number is 1223 bytes.
( I'm only applying it to 3 folders at the moment, not 18, although that appears to make no difference.)

void folderCounts2()
{
  /////////// TEMP INFO ON FOLDER COUNTS //////////////////////
  Serial.print(F("File counts \t"));
  Serial.print(myDFPlayer.readFileCounts());
  Serial.print(F("\n"));
  delay(50);

  for (int i = 1; i <= 3; i++)
  {
    Serial.print(F("Tracks in folder "));
    Serial.print(i);
    Serial.print(F("\t"));
    Serial.print(myDFPlayer.readFileCountsInFolder(i));
    Serial.print(F("\n"));
    delay(50);
  }
}


P.S. Unlikely, but if any other user of DFRobotDFPlayerMini library sees this: have you succeeded in getting readFileCountsInFolder() to work reliably? That's yet another failing in this this buggy and woefully documented library. This thread was a good learning exercise, thanks to all, but I've now abandoned use of the command.

You can replace this

By

Serial.println(myDFPlayer.readFileCounts());

(You get an extra CR out)

Note that When sending only one character Serial.write('\n'); would be more efficient.

Thanks. The way this sketch is growing, maybe that tip will prove crucial. :slightly_smiling_face:

I briefly read
https://arduinogetstarted.com/reference/serial-write
But I find the distinction hard to grasp. When should I not use write() instead of print(), for Arduino programming?

Print typically builds an ASCII representation of what you are asking to send out and then sends those bytes out (using write)

write takes literally the binary representation of the parameter and sends it out.

For example with a number

Serial.print(65);

Will send out the ascii code for 6 and the ascii code for 5 as print understood you wanted to see the integer printed out.

whereas

Serial.write(65);

will send out ONE byte which decimal value is 65. If the target is the Serial monitor you will see a capital A as 65 is the ascii code for ‘A‘ and the serial monitors interprets bytes as an ASCII flow

When you send only one char like "X" or F("X") (note the double quote), there is no need to use print which will dereference the pointer to the const string and go through the steps of looking at the length of the string (which is just 1) and do a loop to call write for each byte. Just calling write with a char notation (simple quote) is thus more effective.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.