Arduino Global and Local Variables Guide

Arduino Global and Local Variables Guide

As we well know, in any programming language, variables are used to store some data. Every variable has a name and a type, and to create a variable, we just have to specify both together. For example, by writing “int sum;” we will tell the compiler to create a memory location with a data type of int and a name of sum.

By creating a variable, we can use it to store and read values. But the question remains: where exactly can we do this? According to the rules of Arduino (in fact, these rules are the basis of C++), every variable has its own area where it can work, i.e., store values and read them. And the programmer must understand where this area ends.

Arduino Local Variables

Local variables are variables whose scope is limited to the current “local” block. For example, we can define a variable in a block restricted by if statements (conditions), and the variable will only be visible inside. Examples of local blocks:

  • Inside a loop (for, while)
  • Inside the function
  • Inside a condition block (if, else).

Restricted means this: the compiler will allow us to use the variable’s name inside the block but will not “recognize” it if we access it from outside. Let’s look at an example:

int sum(int a, int b){
int internalSum = a + b;
return internalSum;
}

In this example, we created a variable internalSum and stored the result of an arithmetic operation summing up the two values given to us in the function arguments into it.

Imagine if we wanted to use this variable to output values to the port monitor. It will not cause any problems:

int sum(int a, int b){
int internalSum = a + b;
Serial.print("Sum = ");
Serial.println(internalSum);
return internalSum;
}

We accessed a variable, took its value and sent it to the port monitor in the Serial.println function.

Let’s try to write another function and try to output this value from there. Will it work?

void calculator(){
Serial.print("Sum = ");
Serial.println(internalSum);
}

Of course not. In the calculator function, the compiler will try to find the definition of the variable internalSum inside the function but will not find it (we defined internalSum in a completely different function, sum()). Getting frustrated by this, the compiler will generate an error (actually, the way to avoid it is to use global variables, which we will talk about later). Thus, we can do anything we want with a variable in our block, but we can do nothing with it in another block.

This compiler behavior is not accidental and can be easily explained. Why would we use a variable and data in an area where we don’t need to process it? If we accidentally change the value of a variable (global variable) that we use elsewhere, we can create many hard-to-find errors. The compiler protects us against this by simply forbidding the use of a variable name from another realm if it is not needed. In addition, human imagination is limited, and it would be hard for us to think of many names for global variables so that they are understandable and don’t overlap.

Arduino Global Variables

A global variable in Arduino is a variable whose scope extends to the entire program; it is visible in all modules and functions.

If the block is inside the current block (for example, there is a block with a loop inside a function), then the values from the “external” block will be visible in it. For example, in this example, inside the for block, we can wonderfully see and use the result variable:

int factorial(int val) {
  long result = 0;
  for (int i = 0; i < val; i++) {
    result = result * val ; // We take the current value of the product, multiply it by the next number and store it back into a variable defined outside the current block but inside the "upper" block
  }
}

The second option is to use a global variable.

A global variable is a variable whose scope is not limited by individual functions or internal blocks. Thus, we can use and change a global variable anywhere in the program, and the compiler won’t mind.

Let’s look at the following example of an Arduino sketch:

int const pinLed = 13; // A global variable to store the pin number. Can be replaced by a constant
int lastMillis; // Global variable for storing the last millis() time
int duration = 1000; // Global variable for storing pause duration
int counter = 0; // Global variable - counter
void setup() {
  Serial.begin(9600);
  pinMode(pinLed, OUTPUT);
}
void loop() {
  if (millis() < lastMillis + duration) {
    digitalWrite(pinLed, LOW);    
  } else {
    digitalWrite(pinLed, HIGH);
    delay(1000);
    counter++;
    Serial.println(counter);
    lastMillis = millis();
  }
}

We use global variables to store values between loop function calls and avoid writing the pin number several times (the global variable pinLed is constant). In addition, the lastMills variable is needed to implement some of the functionality without using delay().

Arduino Global Variables – Possible Problems

We already mentioned the possible problems with global variables. Because we can change the value of a variable at any place, we can accidentally change the value in many places in the program. So we have to go through our whole program and look for all the cases when a global variable is used. We have to keep in mind all the time how changes we make to the global variable in one place will affect the rest of the program. And this is a huge problem for large projects.

Another specific problem with using Arduino global variables is memory. As you know, Arduino controllers don’t just have a limited amount of memory, and they have a very limited amount of memory. In real projects, you can fight for almost every byte. Local variables are created dynamically and disappear when the function completes, freeing up memory. And how do global variables behave? They behave very badly. Because their values should be available everywhere, they are constantly hanging in memory, not releasing it. If there are a lot of global variables in code, you will need a lot of memory to store them too, which can lead to problems.

An alternative to using global variables is constants, or #define instructions. For example, if we write in the code int const pinLed = 13, we make the compiler simply insert the number by removing this variable from the global memory space.

Summarize

In conclusion, understanding the difference between global and local variables in Arduino is crucial for any project. By following the guidelines and tips outlined in this post, you should now have a good grasp of how to declare and use both types of variables in your code. Remember to keep your variables organized and properly named, and to avoid naming conflicts by using unique names for each variable. With these best practices in mind, you’ll be able to write clean, efficient, and reliable Arduino code. Happy tinkering!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top