Serial.println("Random Text") uses quite some RAM

Hi All.

I was writing code for a MEGA, but as I developed the program, the RAM usage kept rising quite fast even though I did not add any variables.

I use a lot of

Serial.println("Different text to inform about status, erros etc");

I then made a small test (see image) - and found out that even when printing a fixed text without using any variables, this consumes quite some RAM.

This surprised me. Does anyone know why this is so? I would expect this to take up flash memory since it is fixed text that does not change in the program - but not RAM.

I searched the forum but did not find other posts about this topic.

Looking much forward to your kind replies.

Test code is below. Try to compile, remove the // and compile again. Then you probably get the same result as me.

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  delay(1000);
  Serial.println("This is just a text");
  Serial.println("This is just another text");
  //Serial.println("This is a third text");
}

You need to tell/force the compiler to keep the text strings in FLASH. Try using the F() macro like this:

Serial.println(F("This is just a text"));
1 Like

In the AVR processor family, the FLASH is in a different address space from the RAM. Your sketch has easy access to RAM but very limited access to FLASH. To allow your sketch to treat strings as any other data they are all copied from FLASH to RAM before your sketch starts.

There is a trick you use to prevent this copying for string literals used for .print() or .println(). There is a macro named 'F()' that marks the string literal as data that should stay in FLASH and then casts it to special type ('__FlashStringHelper *'). The cast causes the compiler to select the .print() and ,print() functions that know how to fetch the characters from FLASH (a.k.a. PROGMEM).

Just change your prints to:
Serial.println(F("This is just a text"));
to save a bunch of RAM.

Some day you might need a large look-up table of constant data. To keep your table from being copied into RAM you can use the "PROGMEM" attribute but be warned: The compiler doesn't keep track of the location of variables for you. You have to remember which addresses are in PROGMEM and call special functions like 'pgm_read_byte()' to read data from PROGMEM.

2 Likes

Thanks a lot for this very valuable information.
Very kind of you to take time for this :smiley:

Kindest regards
Hans-Henning

1 Like

@markd833 Also thanks to you. John got the points because he explained the background. But I still highly apreciate your time answering this.

Have a great weekend (whatever is left of it :smiley: )

@johnwasser Bonus question: Will this work for lcd.print as well even when I am using the non-standard LiquidCrystal440.h which by the way I would like to share with other users who likes to use HD44780 compatible LCD displays with 2 enable pins - but I am too newbie to use github correctly.

Any object class derived from the Print class inherits its features, including support for the F() macro. The Stream class is derived from the Print class so streams (SD files, network servers, network clients) also support the F() macro.

1 Like

Excellent! Thanks a lot :smiley:

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