Arduino Programming: Static Variables

Arduino static variables

Here we are with another tutorial on Arduino programming. This time, we will look at static variables and how you can use them to your advantage.

You may need to read about functions and classes before going through this one.

What is a Static Variable?

A variable is known to be static if it keeps its data as long as the program is running. Of course, this warrants a more thorough explanation.

Consider a function that rotates a servo motor:

rotateServo()
{
 int angle = 90; 
 servo.write(angle);
 Serial.println(angle);
 angle += 10; 
}

Here we are using the write() function from the Servo library to make the servo arm rotate at 90 degrees. We print that angle in the serial port and then we, for the purpose of demonstration, increment the angle by 10.

What would happen if you called this function five times? Since the angle is initialized at 90 at the start of this function, the 10-degree increment will not hold effect with every call.

void loop()
{
 rotateServo();
 rotateServo();
 rotateServo();
 rotateServo();
 rotateServo();
}
Output:
90
90
90
90
90

Now, what if we want to increment the angle by 10 with every function call? And we want it to happen without exposing the angle variable? That is done simply by adding the modifier static to the angle variable.

rotateServo()
{
  static int angle = 90;
  servo.write(angle);
  Serial.println(angle);
  angle += 10;
}

This time, the angle increments by 10 for every call of the rotateServo() function.

void loop()
{
 rotateServo();
 rotateServo();
 rotateServo();
 rotateServo();
 rotateServo();
}
Output:
90
100
110
120
130

Static vs. Global Variables

While it may seem that making a variable static makes it looks like a global variable, that is not the case.

We can make angle global by initializing it outside of the function:

int angle = 90;

rotateServo()
{
  servo.write(angle);
  angle += 10;
}

Calling rotateServo() will still increment angle by 10. But the difference is that with the above code, you can use angle in another function. Whereas in this code:

rotateServo()
{
  static int angle = 90;
  servo.write(angle);
  angle += 10;
}

angle is usable only within rotateServo(). Using it outside will cause a compiler error.

Static Members in a Class

If a class has a static member, then there would be only one copy of that member, and will be shared among all instances of the class.

Consider this example class that controls an LED:

class LED
{
  public:
    LED (int p){
      pinMode(p, OUTPUT);
      pin = p;
    }
    void toggle(void){
      digitalWrite(pin,!digitalRead(pin));
      delay(1000);
    }
  private:
    int pin;
};

We want to improve this class by allowing the user to specify the delay for the toggle. Hence, instead of the constant, we add a variable, _delay:

class LED
{
  public:
    int _delay;
      LED (int p){
        pinMode(p, OUTPUT);
        pin = p;
      }
    void toggle(void){
      digitalWrite(pin,!digitalRead(pin));

delay(_delay);

    }
  private:
    int pin;
};

To use this class, we create an instance:

LED led1(9);

Then we specify the value of  _delay through:

int LED::_delay = 1000;

To toggle the LED, we use the class function toggle() inside loop:

void loop() {
  led1.toggle();
}

However, this code will have a compile error:

19:10: error: 'int LED::_delay' is not a static data member of 'class LED'
exit status 1

To fix this, we simply need to declare _delay as static:

class LED{
  public:
    static int _delay;
    LED (int p){
      pinMode(p, OUTPUT);
      pin = p;
    }
    void toggle(void){
      digitalWrite(pin,!digitalRead(pin));
      delay(_delay);
    }
  private:
    int pin;
};

Also, we can now create multiple instances of the class but only be declaring _delay once:

LED led1(9);
LED led2(10);

int LED::_delay = 1000;

void setup() {}

void loop() {
  led1.toggle();
  led2.toggle();
}

This tutorial is originally written by Roland Pelayo for circuitxcode.com

 

Leave a Reply

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