1

I am working on a simple project on talking to the serial monitor, and my only global variable ("int" type, named "incomingByte") is consuming a lot of memory. There is no problem on running the scketch, but I am not satisfied to have it that way.

When I load it, I receive: "Global variables use 390 bytes (19%) of dinamic memory...". Why is it happening, and how could I fix this?

int incomingByte = 0; //for the incoming serial data
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  Serial.begin(9600);
  //waits for serial initialization to send the messages:
  //(Serial) returns false for serial off, and true for serial on. This is inverted with !.
  while(!Serial){
    ;
  }
  //sending instructions:
  Serial.println("Initializing...");
  Serial.println(" ");
  delay(2000);
  Serial.println("Please select an option:");
  Serial.println("1 - greetings");
  Serial.println("2 - random number");
  Serial.println("3 - calculator");
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    incomingByte = Serial.read(); // Serial.read() returns the first byte of incoming data
  
    //recognizing the command received:
    if (incomingByte == '1'){
      numberOne();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '2'){
      numberTwo();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '3'){
      numberThree();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
  }
}


void numberOne() {
  Serial.println("Hello, Vitor! Good to see you!");
}


void numberTwo() {
  //sets the random number to be picked between [0, 101[
  long randomNum = random(0, 101);
  Serial.print("Your random number is: ");
  Serial.println(randomNum, DEC);
}

void numberThree(){
  Serial.println("Tool not available yet");
}
5
  • Why do you think, that all the dynamic memory allocation is for that variable? Other things (like Serial) also use some of the RAM
    – chrisl
    Commented Feb 1, 2022 at 18:27
  • I think that because the message I receive is telling "Global variables". As you said, does the object "Serial" count as a global variable, when using RAM?
    – Vitor Z.
    Commented Feb 1, 2022 at 18:30
  • Yes, it is global. It's just defined in a different file (inside the used Arduino core), but there at global scope
    – chrisl
    Commented Feb 1, 2022 at 19:02
  • The random seed also needs to be stored somewhere, or some other state for the RNG.
    – Mat
    Commented Feb 1, 2022 at 19:32
  • Just out of curiosity, if you have two global variables, do they use 38% of memory?
    – Nick Gammon
    Commented Feb 3, 2022 at 9:04

1 Answer 1

7

A few things that count towards the “global variables” that you may not think of:

  • all your literal strings, unless encapsulated within the F() macro; you have quite a few of them
  • The Serial object, including its transmit and receive buffers (157 bytes on an Uno)
  • The vtable for HardwareSerial (that's the class Serial belongs to, 18 bytes)
  • The time-keeping variables (9 bytes).

And then, on top of that, there are the actual global variables of your code, and the static locals which, for the purpose of memory allocation, are the same as globals. An int, for example, takes 2 bytes on AVR and 4 bytes on most other hardware platforms.


Edit: answering the questions in a comment

every single time I call Serial it will increase the memory consumption of the code?

I don't quite understand what you mean by “every time”:

  • Every time you add a reference to Serial to a sketch, the linker will add the Serial object to your compiled code, and the program's RAM consumption will grow by the size of this object.
  • Within a single sketch, whether Serial is used once or many times makes no difference: the object will be instantiated only once.

why does the IDE considers everything that uses RAM as a global variable?

When it says “global variables” it actually means “statically allocated data”. It says “global variables” because it is targeted at beginners, and the authors assume beginners would not understand what static allocation means. Globals are the simplest form of static allocation.

is there a difference in consumption between globals and locals?

Yes. Globals get allocated statically, i.e. at compile time. That's why the IDE can report how much space they will consume. Locals (at least non-static locals) get allocated and deallocated on the stack, at run time. Short of running the program in an emulator, it is very hard to predict how much stack space a program will consume, as this will usually depend on run-time events.

3
  • I understood about the literal strings and the serial consumption, but I couldn't get some points. Firstly, every single time I call Serial it will increase the memory consumption of the code? Also, why does the IDE considers everything that uses RAM as a global variable? (is there a difference in consumption between globals and locals?)
    – Vitor Z.
    Commented Feb 2, 2022 at 21:35
  • 1
    @VitorZ.: se expanded answer. Commented Feb 2, 2022 at 22:18
  • 1
    Oh now I got it! Your explanation was very useful and complete, thank you. By using your tip in transferring the strings to PROGMEM with F(), I could reduce the SRAM consumption from 19% to only 9%, with just 1% more of Flash usage.
    – Vitor Z.
    Commented Feb 2, 2022 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.