Classes in Arduino: Creating a Traffic Light

Jan 12 2021 · 7 min read

Let's learn how to build classes in Arduino by getting down and dirty in a simple project. In this tutorial, I'll be explaining how to create a Traffic Light Class to control Red, Yellow, and Green LEDs.

What You Will Need

  • 1 ˣ Arduino Uno
  • 1 ˣ USB Type B (for connecting the Arduino to your PC)
  • 3 ˣ LEDs or 1 Traffic Light Module
  • 3 ˣ 220 Ohm Resistors
  • Jumper Wires

Build The Circuit

From the image provided above, connect:

  • Red, Yellow, and Green LED Cathode to GND
  • Red Anode -> 220Ω -> PIN 11
  • Yellow Anode -> 220Ω -> PIN10
  • Green Anode -> 220Ω -> PIN10

If you are using the Traffic Lights Module, follow this instead:

  • R -> 220Ω -> PIN11
  • Y -> 220Ω -> PIN10Y -> 220Ω -> PIN10
  • GND -> GND

What is a Class?

Before we begin, we have to understand the concept behind creating a class. Why should we trouble ourselves in creating a class when we can just turn each LEDs on/off without one?

A class is a concept used heavily in Object Oriented Programming (OOP). It acts like a template for the object that we want to create.

Whenever we want to create a new object, we only need to call the class. This greatly improves scalability in the long run. Compare having to manage 2 different Traffic Light objects like this

// pins for the first traffic light
int redPin1 = 11;
int yellowPin1 = 10;
int greenPin1 = 9;

// pins for the second traffic light
int redPin2 = 8;
int yellowPin2 = 7;
int greenPin2 = 6;

void setup() {
   // initialize pins for first traffic light
   pinMode(redPin1, OUTPUT);
   pinMode(yellowPin1, OUTPUT);
   pinMode(greenPin1, OUTPUT);
   // initialize pins for second traffic light
   pinMode(redPin2, OUTPUT);
   pinMode(yellowPin2, OUTPUT);
   pinMode(greenPin2, OUTPUT);
}

void loop() {
   // make each traffic light blink from red to green
   digitalWrite(redPin1, HIGH);
   digitalWrite(greenPin1, LOW);
   digitalWrite(redPin2, HIGH);
   digitalWrite(greenPin2, LOW);
   delay(1000);
   digitalWrite(redPin1, LOW);
   digitalWrite(yellowPin1, HIGH);
   digitalWrite(redPin2, HIGH);
   digitalWrite(yellowPin2, LOW);
   delay(300);
   digitalWrite(yellowPin1, LOW);
   digitalWrite(greenPin1, HIGH);
   digitalWrite(yellowPin2, LOW);
   digitalWrite(greenPin2, HIGH);
   delay(1000);
}

With this:

// pins for the first traffic light
int redPin1 = 11;
int yellowPin1 = 10;
int greenPin1 = 9;

// pins for the second traffic light
int redPin2 = 8;
int yellowPin2 = 7;
int greenPin2 = 6;

// initialize tl1 object using the TrafficLight class
TrafficLight tl1(redPin1, yellowPin1, greenPin1);

// initialize tl2 object using the TrafficLight class
TrafficLight tl2(redPin2, yellowPin2, greenPin2);

void setup() {
}

void loop() {
   // make each traffic light blink from red to green
   tl1.Stop();
   tl2.Stop();
   delay(1000);
   tl1.Careful();
   tl2.Careful();
   delay(300);
   tl1.Go();
   tl2.Go();
   delay(1000);
}

Note that this is example only uses 2 traffic lights. What happens when we add 3 more traffic lights? We can clearly see the benefits of using classes for scalability and reducing duplicate codes.

Let’s Get into Coding!

We will be creating the class inside our own library. So today we are actually also learning how to create a library in Arduino!

First, create a new file by either clicking the drop down icon on the right and then selecting “New Tab”, or just pressing Ctrl + Shift + N.

Name the file TrafficLight.h. If you didn’t know, Arduino uses C++ as a programming language. The file that we just created is called a header file. Header files contains the classes and functions that we can use. Let’s write this in the file:

#ifndef TrafficLights_h
#define TrafficLights_h

// enumerate the color names to be more readable
enum color {GREEN, YELLOW, RED};

class TrafficLight {
  public:
    TrafficLight(byte redPin, byte yellowPin, byte greenPin);
    void Toggle(int color);
    void TurnOff(int color);
    void TurnOn(int color);
    void Go();
    void Careful();
    void Stop();
    bool GetState(int color);
    bool* GetStates();
  private:
    byte pins[3];
    bool states[3]={0}; 
    void init();
};
#endif

I’ll explain what we’ve typed. We first wrap our code in

#ifndef TrafficLights_h
#define TrafficLights_h

/*
your code here
*/

#endif

This is what we usually call an #include guard. It ensures that our library will only be declared once. It first checks whether TrafficLights_h is defined. If it’s not defined, we define it and call our code. If it’s already defined, it will skip the code entirely.

Next we have

// enumerate the color names to be more readable
enum color {GREEN, YELLOW, RED};

This is basically assigning GREEN, YELLOW, and RED to 0,1, and 2 respectively. This way, it is easier for us to see what we are currently calling.

Then we initialize the class TrafficLight, containing some variables divided by public and private. The public section contains all the variables that can be called by anyone using the class, while the private section contains the variables only the class itself can call. byte pins[3] declares an empty array of length 3 to store the Arduino pin locations. bool states[3]={0} declares an empty array of length 3 with a default value of false to store the state of each LED light (true means on, false means off). I will explain the public section more on the next part.

Next up is creating the implementation of the class. We will create another file and name it TrafficLight.cpp. Inside of it, we write:

#include "Arduino.h"
#include "TrafficLight.h"

void TrafficLight::init() {
   for(int i=0; i<3; i++) {     
     pinMode(this->pins[i], OUTPUT);
   }
 }

TrafficLight::TrafficLight(byte redPin, byte yellowPin, byte greenPin) {
   this->pins[RED] = redPin
   this->pins[YELLOW] = yellowPin;
   this->pins[GREEN] = greenPin;
   this->init();
 }
 
bool TrafficLight::GetState(int color) {
   return this->states[color];
 }

bool* TrafficLight::GetStates() {
   return this->states;
 }
 
void TrafficLight::Toggle(int color) {
   this->states[color] = !this->states[color];
   if(this->states[color]) {
     digitalWrite(this->pins[color], HIGH);
   } else {
     digitalWrite(this->pins[color], LOW);
   }
 }
 
void TrafficLight::TurnOn(int color) {
   if(!this->states[color]) {
     this->Toggle(color);
   }
 }
 
void TrafficLight::TurnOff(int color) {
   if(this->states[color]) {
     this->Toggle(color);
   }
 }
 
void TrafficLight::Go() {
   this->TurnOff(YELLOW);
   this->TurnOff(RED);
   this->TurnOn(GREEN);
 }
 
void TrafficLight::Careful() {
   this->TurnOff(RED);
   this->TurnOff(GREEN);
   this->TurnOn(YELLOW);
 }
 
void TrafficLight::Stop() {
   this->TurnOff(YELLOW);
   this->TurnOff(GREEN);
   this->TurnOn(RED);
 }

This one is much longer than the previous one! Let’s break it down.

#include "Arduino.h" imports the necessary Arduino libraries while #include "TrafficLight.h" imports the class that we have made earlier.

TrafficLight::TrafficLight(byte redPin, byte yellowPin, byte greenPin) is the constructor for the TrafficLight class. It will assign the pins to its respective positions and initialize the class in this->init(). void TrafficLight::Toggle(int color) is used to switch a specific color on/off based on its state. Both void TrafficLight::TurnOn(int color) and void TrafficLight::TurnOff(int color) are for forcing the state to true / false respectively. void TrafficLight::Go(), void TrafficLight::Careful(), void TrafficLight::Stop() ensures that only one LED color will be turned on, with Go() showing green, Careful() showing yellow, and Stop() showing red.

Now that we have made the implementation for our class, we can use it in our Arduino sketch:

include "TrafficLight.h"

int redPin = 11;
int yellowPin = 10;
int greenPin = 9;

TrafficLight tl(redPin,yellowPin,greenPin);

void setup() {
}

void loop() {
  tl.Stop();
  delay(1000);
  tl.Careful();
  delay(300);
  tl.Go();
  delay(1000);
  tl.Careful();
  delay(300);
}

If you don’t have an Arduino with you, here’s a simulation made in Tinkercad: https://www.tinkercad.com/things/dSYGrVSqiBS-shiny-turing-fulffy.

That’s It!

If you’ve completed this project, congratulations! Now you understand how to create classes in Arduino and can even make your own Arduino library!

Summing it All Up

Let’s review what we’ve learned today!

  • A class is a template to be used repeatedly, enabling higher scalability in your code.
  • Arduino’s programming language uses C++.
  • In C++, we split files into header files .h and implement them in a .cpp.

Thank you for reading!

Tags

Share