Arduino Programming: Classes

The Arduino platform runs on C++ and with this comes all the pros (and cons) of the language. One of those pros is the use of classes and in general, object oriented coding. This article aims to guide you in creating your own Arduino classes which can make your sketches more efficient.

Introduction

A class is a code template for defining objects in object-oriented programming (OOP) languages such as C++. Defining a class follows this syntax:

class <class name> {
  <access modifier>:
     <member>;
};

Here class is a keyword and <class name> is the name you assign to your class. The <access modifier> defines the members and is either private, public and protected. These access modifiers are defined as:

  • private members - accessible only from other members of the same class.
  • protected members - accessible from other members of the same class and members of their derived classes.
  • public members - accessible from anywhere where the object is visible.

Finally, members are either variables or functions. If undefined, members are given a private access modifier. This is the primary difference between structs and classes because in structs (strictly C++ speaking), members are public by default.

Creating an Example Arduino Class

We can look at classes as something that defines an object.  For example, let the object be a LED wired to an Arduino’s pin. The class definition could start with:

class LED{
…
}

What possible properties can this LED have? For example, where it connects to an Arduino pin should be known.

class LED{
…
  byte pin;
…
}

The user of the class should be able to define this pin, hence this member should be public.

class LED{
  public:
    byte pin;
…
}

What can the user do with the LED? Maybe he or she can flash it. Let’s add a function member inside the class that does that:

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

Of course, this function (toggle) is also accessible to the user hence it’s public.

To use this class, we declare it as:

LED led;

Now the object led can access the data members of the class. For multiple objects, just do:

LED led1;
LED led2;
….

Say the LED is wired to pin 9, then:

...
LED led;

void setup(){
   led.pin = 9;
}
...

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

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

This is now the full sketch for flashing the LED using our Arduino class:

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

LED led;

void setup() {
  led.pin = 9;
}

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

Class Constructors

Classes also allow us to use constructors. This can make our sketch shorter.

A constructor is a function data member that has the same name as the class but without a return type.

We can modify the LED class to add a constructor:

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

The constructor here is this part:

LED (int p){
  pinMode(p, OUTPUT);
  pin = p;
}

This function is automatically called during class initialization.

Also, notice that the pin variable is now private.

private:
int pin;

In the previous version of our class, this variable was used to define where the LED is connected. But since that pin number is now part of the constructor, only members of the class use the pin variable. Hence, it is now a private member.

Making a member private is one way of protecting data. This concept in OOP is know as encapsulation.

This is how we use our new class with constructor:

LED led(9);

Flashing the LED uses the same function:

led.toggle();

Here is now the full sketch:

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

LED led(9);

void setup() {}

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

By the way, you can put the class definition inside a separate file. Click “new tab” on the IDE or press CTRL+SHIFT+N. In our example, let’s name this new file as LED.h and its contents are:

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

In your main sketch, include the file using:

#include "LED.h"

So the main code is now sans the class definition:

#include "LED.h"

LED led(9);

void setup() {}

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

Class Inheritance

Members of a class can be inherited by another class. This means a function in another class may be used by a derived class.

Let’s create a new class called RELAY with two functions:

class RELAY{
  public:
    RELAY (int p){
      pinMode(p, OUTPUT);
      pin = p;
    }
    void on(void){
      digitalWrite(pin,HIGH);
    }
    void off(void){
      digitalWrite(pin, LOW);
    }
  private:
    int pin;
}

With this class, we can attach a relay to an Arduino pin and control it. For example:

// RELAY class definition here
...

RELAY rel(3);

void setup(){}

void loop(){
  rel.on();
  delay(1000);
  rel.off();
  delay(1000);
}

This sketch turns on the relay for a second and then turns it off for another second.

We want the RELAY class to also have a toggle function like in the LED class. So we inherit the members of the LED class by defining the RELAY class like this:

class RELAY : public LED{
  public:
    RELAY (int p) : LED(p){
      pinMode(p, OUTPUT);
      pin = p;
    }
    void on(void){
      digitalWrite(pin,HIGH);
    }
    void off(void){
      digitalWrite(pin, LOW); 
    }
  private:
    int pin;
};

This way, even though the RELAY class doesn’t have a toggle function, we can still do this:

RELAY rel (3);

…

rel.toggle();

 

Polymorphism

In our LED class, the toggle function flashes the LED for one second:

void toggle(void){
  digitalWrite(pin,!digitalRead(pin)); 
  delay(1000);
} 

When the RELAY class inherits this, it will have the same 1 second delay. What if we want another time delay specific only for the RELAY class?

We can add a toggle function right into the RELAY class and use a different time delay:

void toggle(void){
  digitalWrite(pin,!digitalRead(pin)); 
  delay(500);
} 

Even if the RELAY class is derived from the LED class, it still can have a function with the same name but with a different function. This is another OOP concept called polymorphism.

That’s it! You have now created your own Arduino class. Just a few more steps and you can now create your own Arduino library.

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 *