Programming with Class

In this project we will use a Red-Green-Blue (RGB) LED to create color sequences, morphing or stepping from one color to the next. A push-button will allow the user to switch the color sequence being displayed. RGB LEDs are used in appliances to create moods by illuminating translucent materials with varying colors. Let’s first examine the characteristics of an RGB LED.

RGB LED

RGB LEDs consist of three LEDs, one red, one green, and one blue contained in a single translucent or transparent package. Each color is controlled separately, allowing a wide gamut of colors to be created by varying the amount of electrical current flowing through each of the LEDs. The following diagram shows the RGB LED schematic and its pinout. The RGB LED portrayed is a common cathode RGB LED. Common anode RGB LEDs are also available.

RGB LED Schematic

Apart from its packaging, the RGB LED works as if it was three independent LEDs and each can be wired in a circuit the way it was done in the ‘Blink’ circuit. The following diagram shows the circuit used for this project. It contains an RGB LED as well as a push-button that will be used to switch between color sequences. Note that we are using three resistors each separately limiting current in each of the LED. If we would have put a single resistor at the common cathode junction of the LEDs, the LEDs would have still lit, but their brightness would have been impacted by other LEDs being activated or not.

The RGB LED Circuit

RGB LED Circuit

Digital I/O pin 9 is connected to the red LED; digital I/O pin 10 is connected to the green LED; and digital I/O pin 11 is connected to blue LED. All connections are made through 330Ω resistors placed between the digital I/O pin and the anode of each light emitting diode. Digital I/O pin 12 is connected to a push button that is connected to ground when depressed. A 10K pullup resistor is connected between the digital I/O pin and the 5-volt supply, ensuring a HIGH input value when the push button is not depressed.

You might have noticed the ’tilde’ character, ‘~’, associated with some of the Arduino’s digital I/O pins. These digital I/O pins are special in that not only do they support digital output as HIGH and LOW values, but they also support analog output values. Instead of being output as a constant voltage value, analog values at these pins are output as a train of on and off pulses. The ratio between on and off is determined by the analog value. This is called pulse width modulation (PWM). In the Arduino, analog output values are discrete values between 0 and 255. For an analog value of 0, the output is always off; for an analog value of 64, the output is 25% on, 75% off; for an analog value of 128, the output is 50% on and off; and for an analog value of 255, the output is always on. The brightness of each LED is proportional to the amount of on time at the digital output. The frequency of the signal at pins 9, 10, and 11 on the Arduino Uno is approximately 490Hz.

Breadboarding

The following picture depicts how to connect the different parts using a solderless breadboard, jump wires, an RGB diode, a push button, a 10K resistor and three 330Ω resistors.

Programming with Class_bb

The RGB LED Program

The purpose of the program is to display a show of colors using the RGB LED. We want the LED to change colors following a sequence of pre-selected colors. The color change can be abrupt, or gradual, depending on the sequence. Because it would be arduous to recreate the code from the code snippets in this blog, I have created a Programming with Class repository on the Git Website. Simply click on the link, then on the “Clone or Download” button to download a zipped version of the files and copy them in a folder named “ProgrammingWithClass” on your computer. You can then load the “ProgrammingWithClass.ino” sketch in the Arduino Integrated Development Environment (IDE).

The program in this project can be fetched from the  Programming with Class repository on the Git Web site.

The Main Sketch

As usual, the Arduino sketch file starts with a comment stating the purpose of the program, the author and copyright notice. The program is licensed under the standard MIT license.

Next, we include two files: “rgbLed.h” and “rgbColor.h“. These files declare the rgbLed and rgbColor classes. We will cover the content of these files, what classes are, and how to program them later in this post. For now, let us simply accept that these classes exist and that we can create variables with them which I will describe shortly.

/*
Main ProgrammingWithClass sketch
Program that outputs sequences of colors to an RGB LED. The
sequence shown can be selected by a push button. This sketch
demonstrates the use of classes. It is associated with the
Programming with Class blog post on https://lagacemichel.com
MIT License
Copyright (c) 2018, Michel Lagace
*/
#include "rgbLed.h"
#include "rgbColor.h"

We have already seen an example of a class: the String class. The String class comes with the Arduino system. It allows programmers to easily work with character sequences. We already have used String classes as part of the Morse Code Generator project. One characteristic of variables created with classes is that they encapsulate, that is hide, the data that they contain. A String variable certainly contains a sequence of characters and possibly a length value, or maybe it is implemented using a null-terminated character sequence. We do not know, unless we actually look at the code implementing the String class and truly, we do not care as long as we can operate on a String. Another characteristic of variables created from classes is that we can call functions, called methods when associated to classes, directly acting upon the variable. As an example from the Morse Code Generator project, we use the length() method associated with a String as follows:

String text = "abcd";
int length = text.length();

In the code above, we create a variable text of type String, the name of the class, and initialize it with the character string “abcd”. We then create an integer variable called length and initialize it with the length, the number of characters, contained in the text variable using the length() method. The method is called by appending the variable name with a period (‘.‘) then the name of the method followed by parenthesis. Methods behave very similarly to functions and there could be parameters within the parenthesis following the method name if required. Notice the strength of variables created from classes as they behave almost like data types.

Variables created from classes are also called ‘objects‘. Along with a set of rules, design patterns, and best practices, objects are at the root of Object-Oriented Programming. Arduino software is written in C++, an object-oriented programming language that also allows C-language constructs. In the next section we will see how to use the rgbColor and rgbLed objects. Later in the blog, we will see the details of the implementation of these classes.

The rgbColor and rgbLed Classes

The rgbColor class allows programmers to create color objects based on the red, green and blue emissive color triad. Users can create a rgbColor object using the three colors or simply by declaring a rgbColor variable without stating values. rgbColor object declaration has the following forms: rgbColor color(float red, float green, float blue) or rgbColor color. Following are examples of rgbColor object declarations.

rgbColor red(1.0, 0.0, 0.0);
rgbColor black;

In the first case, a red object is created by setting the red component to 1.0 and the green and blue components to 0.0. Color components are set to floating point values between 0.0 and 1.0, from completely off to completely on. A rgbColor object can also be created without any component, in which case all components are set to 0.0, corresponding to black. rgbColor objects can also be created from other rgbColor objects, or by assigning a rgbColor object to another.

rgbColor darkRed(0.25, 0.0, 0.0);
rgbColor anotherRed(red);
anotherRed = darkRed;

rgbColor object anotherRed is created as a copy of object red, then assigned the value of just created rgbColor object darkRed. rgbColor also sports three methods to obtain the values, between 0.0 and 1.0, of each color component making up the color stored in a rgbColor object. The following depicts these methods.

float r = darkRed.red();
float g = darkRed.green();
float b = darkRed.blue();

Methods, as shown above, are function names following an object name, separated by a period (‘.‘). The rgbColor class supports one more method, the gradate() method.

rgbColor blue(0.0,0.0,1.0);
rgbColor green(0.0,1.0,0.0);
rgbColor cyan;
cyan.gradate(blue,green,0.5);

The gradate() method assigns to the rgbColor object a color between the first and second color specified, scaled according to the third function parameter, the gradient. The gradient specifies the amount mixed from each color according to the formula

Color = (1.0 – Gradient)•Color1 + Gradient•Color2

A value of 0.0 makes the resulting color equal to the first color, C1; a value of 1.0 makes the resulting color equal to the second color, C2; a value between 0.0 and 1.0 makes the resulting color a combination of both colors according to the gradient specified.

The program uses objects from a second class, the rgbLed class. Each rgbLed object represents an external RGB LED and the actual Arduino pins associated with it. There is no default value possible and three PWM capable digital output pins must be specified to create a rgbLed object.

rgbLed device(8,9,10);

In this line of code, a rgbLed variable is created for an RGB LED whose red LED is connected to the Arduino’s digital pin 8, whose green LED is connected to digital pin 9 and whose blue LED is connected to digital pin 10. The rgbLed class supports only one method, the set() method which assigns a rgbColor object to the rgbLed object.

rgbColor orange(1.0,0.2,0.0);
rgbLed device(8,9,10);
device.set(orange);

In this code snippet, we create the orange rgbColor object, the rgbLed device object representing the external RGB LED attached to the Arduino pins 8, 9 and 10, and we set the external RGB LED to light up orange.

Next in the Main Sketch

Back to the program, we define the RGB LED digital output pins, then the push-button digital input pin. We then set constants to cycle through colors in 10 seconds in 1000 steps, 10 milliseconds per step. We then initialize the global variable that keeps track of the color cycle step.

Next, we use a construct that was never used before, the enumerated type. Enumerated types declare sequences of value names making up an enumeration of things. Enumerated types are themselves named, allowing variables to be created using the enumerated type name. Enumerated types are declared using the enum reserved word followed by the enumerated type name, followed by an enumeration of names separated by commas and enclosed in curly brackets. The whole construct is followed by a semicolon.

In the code below, an enumerated type called colorScheme has the following enumerated value names: nothing, wheel, rainbow, all, and white. In Arduino’s memory, enumerated type value names are encoded as integers starting at 0. Hence, setting a colorScheme variable to rainbow will assign it the value 2 and setting a colorScheme variable to white will assign it the value 4. We added an extra value at the end of the enumeration, numberOfSchemes. It gets assigned the value 5, which is the number of actual color schemes in the list. Following the enumeration is a variable declaration making scheme a colorScheme variable initialized with nothing.

// RGB LED pins
#define REDPIN   9
#define GREENPIN 10
#define BLUEPIN  11

// Pushbutton pin
#define PUSHBUTTON 8

// Constants used to control timings
const int colorCycle = 1000;
const float cycleTime = 10.0;
const int stepTime = cycleTime/colorCycle*1000;
// Color step counter
static int colorStep = 0;

// Color scheme names
enum colorScheme {nothing,
                  wheel,
                  rainbow,
                  all,
                  white,
                  numberOfSchemes
};
static colorScheme scheme = nothing;

//Push Button current value
bool pushButton = HIGH;

// Global LED object
static rgbLed led(REDPIN,GREENPIN,BLUEPIN);

// Array of color sequences made of rgbColor objects
static const rgbColor wheelColors[] = 
  {redColor,yellowColor,greenColor,cyanColor,blueColor,magentaColor};
static const rgbColor rainbowColors[] = 
  {redColor,orangeColor,yellowColor,greenColor,blueColor,
   purpleColor,blackColor};
static const rgbColor allColors[] =
  {redColor,greenColor,blueColor,yellowColor,cyanColor,magentaColor,
   orangeColor,purpleColor,whiteColor,blackColor};

Following the enumerated type variable is a Boolean variable holding the current input value of the push-button. It is initialized to HIGH. As in the Toggle Push-Button blog post, we are interested in the moment the button is pushed as it goes from HIGH to LOW. After, we declare the variable led representing the external RGB LED connected to three Arduino digital output pins that support pulse width modulation. Then, we declare constant arrays of rgbColor values, three in all. Each array corresponds to a color sequence we want displayed at the RGB LED. The color values such as redColor and cyanColor are constants that are declared within the rgbColor class header file. The following RGB color constants have been declared:

  • redColor
  • greenColor
  • blueColor
  • yellowColor
  • cyanColor
  • magentaColor
  • orangeColor
  • purpleColor
  • whiteColor
  • blackColor

Computing the Color of the RGB LED

The main Arduino sketch contains two functions: glideThrough() and stepThrough(). Both functions take two parameters, the color array containing the sequence of colors to glide or step through, and an integer containing the number of colors in the array.

In these functions, each color gradient, or solid color depending on the function, is displayed for the same amount of time, depending on the number of colors in the array. The gradientSpan variable contains the number of steps out of the total number of steps to spend between two colors.

For the glideThrough() function, we select the index of the colors between which we will gradually morph. The first color is selected according to the current step in the color cycle. The second color is the next color in the array. If we have reached the end of the color array, the second color is set to the first color in the array, starting a new color cycle. This is done using the modulo operator ‘%‘, that provides the remainder of the division with the number of values in the array. The gradient value is set to a value between 0.0 and 1.0 corresponding to the step position between the two colors we want to blend, or glide through. Finally, we compute the color blend using the gradate() method of a rgbColor object and then assign the rgbColor object to the rgbLed led object using the set() method.

For the stepThrough() function, we select the color to display according to the current step in the color cycle. We create a rgbColor object initialized with the appropriate color in the color array and assign the rgbColor object to the rgbLed led object using the set() method.

// Glide through colors
void glideThrough(rgbColor colorArray[],int arraySize) {
  // Initialize color gradients
  float gradientSpan = (float)colorCycle/(float)arraySize;

  // Compute color array indices and gradient between colors
  int gradateFrom = colorStep/gradientSpan;
  int gradateTo = (gradateFrom + 1)%arraySize;
  float gradient = colorStep/gradientSpan - (float)gradateFrom;

  // Gradate between the two colors
  rgbColor color;
  color.gradate(colorArray[gradateFrom],colorArray[gradateTo],gradient);
  led.set(color);
}

// Step through colors
void stepThrough(rgbColor colorArray[],int arraySize) {
  // Initialize color gradients
  float gradientSpan = (float)colorCycle/(float)arraySize;

  // Compute color array indeces and gradient between colors
  int colorIndex = colorStep/gradientSpan;

  // Set the color according to time
  rgbColor color(colorArray[colorIndex]);
  led.set(color);
}

Main Sketch Setup

In the setup() function of the main sketch, we setup the push-button digital input pin. The RGB LED digital output pins are setup as part of the rgbLed object construction that we will see later in the post.

// Setup push button pin
void setup() {
  // Setup pin modes
  pinMode(PUSHBUTTON,INPUT);
}

Main Sketch Loop

The first thing we do in the sketch’s loop() function is to display colors according to the selected scheme. This is done through a series of if else statements, selecting the appropriate scheme. If scheme is nothing or white, the RGB LED is set to black or white respectively. If scheme is wheel or rainbow, the RGB LED is set to gradually morph from one color to the next of the wheelColors and rainbowColors respectively. If scheme is all, the RGB LED steps through all available color values. Anything else is a programming error and would set the RGB LED to a solid red color.

Next, we check if the push-button has changed state. If so, and if the old value is HIGH, making the transition from HIGH to LOW, we select the next color scheme. If scheme goes beyond the number of schemes, it is reset to nothing. Upon change of the color scheme, the color step is reset to zero. Upon a change of state of the push-button, the old push-button value is set to the new one.

Finally, we wait the computed step duration before starting the next step. This delay also serves as a de-bounce delay. We then increment the color step and cycle back to zero if the we have reached the end of the color cycle.

// Main loop. Repeatedly through color sequences
void loop() {
  // Output color according to selected scheme
  if (scheme == nothing) {
    led.set(blackColor);
  }
  else if (scheme == wheel) {
    glideThrough(wheelColors,sizeof(wheelColors)/sizeof(rgbColor));
  }
  else if (scheme == rainbow) {
    glideThrough(rainbowColors,sizeof(rainbowColors)/sizeof(rgbColor));
  }
  else if (scheme == all) {
    stepThrough(allColors,sizeof(allColors)/sizeof(rgbColor));
  }
  else if (scheme == white) {
    led.set(whiteColor);
  }
  else { // Program error, this should never happen
    led.set(redColor);
  }
  // Detect if button is going from HIGH to LOW. If so, select next
  // color scheme
  if (digitalRead(PUSHBUTTON) != pushButton) {
    if (pushButton) {
      colorScheme = colorScheme + 1;
      if (colorScheme >= numberOfSchemes) {
        colorScheme = nothing;
      }
      colorStep = 0; 
    }
    pushButton = !pushButton;
  }

  // Wait a bit, then proceed to next color step
  delay(stepTime);
  colorStep++;
  if (colorStep >= colorCycle) {
    colorStep = 0;
  }
}

Object-Oriented Programming

Classes are at the heart of object-oriented programming. They allow programmers to combine data structures, attributes, with code constructs, methods. It allows information collections to be treated as data types. This what we will see in the next sections. We will describe two classes, rgbColor and rgbLed. In C++, classes are declared in header files and code is developed in class implementation files. The header file, ending with the .h file type, contains the interface to objects created from the class while the implementation file, ending with the .cpp file type, contain the code of the different methods associated with objects of the class.

In order to act as data types, classes need to define a few methods that are called whenever an object is created, deleted, or assigned to. If not provided, C++ creates these methods by default. These methods are

  • the default constructor
  • the destructor
  • the copy constructor
  • the assignment operator

Classes that systematically declare these methods are said to follow the orthodox canonical class form. The default constructor is called whenever a new object is created from the class without any parameter or initial values. Its syntax is simply the name of the class followed by parenthesis.

className();

The destructor is called whenever an object goes out of scope, such as when a function exits. It allows the system to release memory and to relinquish links to other objects. Its syntax is the class name preceded by the tilde (~) symbol and followed by parenthesis.

~className();

The copy constructor allows an object of a class to be constructed from another object of the same class. Its syntax is the name of the class followed by a reference to a constant object of the same class within the method’s parenthesis. The & after the class name signifies that a reference to the object is passed to the function instead of a copy. The const keyword signifies that the object referenced cannot be modified.

className(const className&);

The assignment operator allows an object to be assigned from another one of the same class. Its syntax is a reference to a class name followed by operator = followed by a reference to a constant object of the same class within the method’s parenthesis. Here again, the ampersand signifies that we are passing and returning a reference to an object instead of a copy of the object. This is more efficient, especially if objects contain a lot of information.

className& operator = (const className&);

Within the class declaration, methods and attributes that are available outside of the class’ code are declared public. Within the class declaration, anything following a public: declaration is visible and usable by all code outside and within the class. Within the class declaration, anything following a private: declaration is only visible to code within the class. Generally speaking, attributes, that is variables within the class, are in a private section of the class declaration. Sometimes, we do not want the default constructor, copy constructor, or assignment operator to be automatically generated by the compiler and we do not want to provide them to class users. This is achieved by putting them in the private section of the class.

The following sections contain header files and implementation files for the rgbColor and rgbLed classes. Consult a C++ primer to better understand classes in C++.

rgbColor.h Header File

The rgbColor header file defines the rgbColor class. C++ and .ino files that want to use objects of the rgbColor class must include this file using the ‘#include‘ statement. The header file contains the class definition that declares a default constructor, a destructor. a copy constructor and an assignment operator within its public section. A constructor from red, green, and blue floating point components is also declared. Three accessor methods, red(), green() and blue() are declared to return the floating point value of each color component. Finally, the gradate() method explained earlier in the post is declared.

Then follows a private section containing the color components declared as bytes. Although colors are set and accessed as floating-point values between 0.0 and 1.0, they are stored as integer values between 0 and 255 in order to save memory space.

Finally, a set of constant rgbColor objects are created that contain the red, green, blue, yellow, cyan, magenta, orange, purple, white and black colors.

/*
rgbColor class (header)
Class rgbColor stores a color and operates on it.
MIT License
Copyright (c) 2018, Michel Lagace
*/
#if !defined(RGBCOLOR_HEADER)
#define RGBCOLOR_HEADER
#include "arduino.h"

// Class rgbColor
class rgbColor {
  public:
    // Orthodox Cannonical Form
    rgbColor(); // Default Constructor
    ~rgbColor(); // Destructor
    rgbColor(const rgbColor&); // Copy Constructor
    rgbColor& operator = (const rgbColor&); // Assignment operator
    // Other constructors 
    rgbColor(float r,float g,float b);
    // Object accessors (set/get)
    const float red() const;
    const float green() const;
    const float blue() const;
    // Object methods
    void gradate(const rgbColor c1, const rgbColor c2, float g);
  private:
    // Color components
    byte redComponent;
    byte greenComponent;
    byte blueComponent;
};

// Global constant colors 
static const rgbColor redColor(1.0,0.0,0.0);
static const rgbColor greenColor(0.0,1.0,0.0);
static const rgbColor blueColor(0.0,0.0,1.0);
static const rgbColor yellowColor(1.0,0.6,0.0);
static const rgbColor cyanColor(0.0,1.0,1.0);
static const rgbColor magentaColor(1.0,0.0,0.5);
static const rgbColor orangeColor(1.0,0.1,0.0);
static const rgbColor purpleColor(0.2,0.0,0.2);
static const rgbColor whiteColor(1.0,1.0,1.0);
static const rgbColor blackColor(0.0,0.0,0.0);
#endif

rbgColor.cpp Implementation File

The rgbColor implementation file contains the implementation of all methods, including constructors, destructor, assignment operator, declared in the header file. All method names within the file are prefixed with the class name followed by two colons. In the case of the rgbColor class, all its methods are prefixed with rgbColor::. We will describe each method in turn.

The default constructor rgbColor::rgbColor() initializes all color components to zero. The destructor rgbColor::~rgbColor() does nothing. The copy constructor rgbColor::rgbColor(const rgbColor& color) copies each color component from the source to the current object. The assignment operator rgbColor& rgbColor::operator =(const rgbColor& color) first checks if the source being copied from is the object itself. If not, it copies each color component from the source to the current object. The assignment operator also returns a reference to the rgbColor object.

The constructor rgbColor::rgbColor(float r,float g, float b) transforms each color component from a 0.0 to 1.0 value to a 0 to 255 value. It also clamps values between 0 and 255. The method rgbColor::gradate(rgbColor c1, rgbColor c2, float g) computes the color value between c1 and c2 at the gradient g specified. The gradient is a floating-point value between 0.0 and 1.0. The resulting color is computed according to the following formula.

Color = (1.0 – Gradient)•Color1 + Gradient•Color2

Finally, the rgbColor::redComponent(), rgbColor::greenComponent(), and rgbColor::blueComponent() methods return the value of each component as a floating point value between 0.0 and 1.0.

/*
rgbColor class (implementation)
Class rgbColor stores a color and operates on it
MIT License
Copyright (c) 2018, Michel Lagace
*/

#include "rgbColor.h"

// Default constructor. Set to black.
rgbColor::rgbColor() {
  redComponent = 0;
  greenComponent = 0;
  blueComponent = 0;
}

// Destructor. Does nothing.
rgbColor::~rgbColor() {
}

// Copy constructor. Constructs a color from another.
rgbColor::rgbColor(const rgbColor& color) {
  redComponent = color.redComponent;
  greenComponent = color.greenComponent;
  blueComponent = color.blueComponent;
}

// Assignment operator. Assigns a color to another.
rgbColor& rgbColor::operator =(const rgbColor& color) {
  if (&color != this) {
    redComponent = color.redComponent;
    greenComponent = color.greenComponent;
    blueComponent = color.blueComponent;
  }
  return *this;
}

// Constructor with initializers. Initialize the color with
// the specified red, green, and blue value.
rgbColor::rgbColor(float r, float g, float b) {
  // Limit red component between 0 and 255
  if (r <= 0.0) {     redComponent = 0;   }   else if (r >= 1.0) {
    redComponent = 255;
  }
  else {
    redComponent = (byte)(r*255.0);
  }
  // Limit green component between 0 and 255
  if (g <= 0.0) {     greenComponent = 0;   }   else if (g >= 1.0) {
    greenComponent = 255;
  }
  else {
    greenComponent = (byte)(g*255.0);
  }
  // Limit blue component between 0 and 255
  if (b <= 0.0) {     blueComponent = 0;   }   else if (b >= 1.0) {
    blueComponent = 255;
  }
  else {
    blueComponent = (byte)(b*255.0);
  }
}

// Set color value as a gradient between two values.
// Color1 and color2 are the values between which the new value
// will be set as a gradient between the two values. Gradient
// is a value between 0 and 1.
void rgbColor::gradate(const rgbColor startColor,
                       const rgbColor endColor,
                       float gradient) {
  redComponent = startColor.redComponent +
    (endColor.redComponent - startColor.redComponent)*gradient;
  greenComponent = startColor.greenComponent +
    (endColor.greenComponent - startColor.greenComponent)*gradient;
  blueComponent = startColor.blueComponent +
    (endColor.blueComponent - startColor.blueComponent)*gradient;
}

// Red, green and blue accessors. Return values.

const float rgbColor::red() const {
  return redComponent/255.0;
}

const float rgbColor::green() const {
  return greenComponent/255.0;
}

const float rgbColor::blue() const {
  return blueComponent/255.0;
}

rgbLed.h Header File

The rgbLed header file defines the rgbLed class. C++ and .ino files that want to use objects of the rgbLed class must include this file using the ‘#include‘ statement. The header file contains the class definition that declares a destructor within its public section. A constructor from red, green, and blue digital output pin assignment is also declared. The set() method allows users to assign a color to a rgbLed object. The default constructor, copy constructor and assignment operator are declared in the private section and cannot be used for rgbLed objects. Then follows a private section containing the pin numbers corresponding to the red, green and blue LEDs declared as integers.

/*
rgbLed class (header)
Class rgbLed represents an external rgbLed
MIT License
Copyright (c) 2018, Michel Lagace
*/

#if !defined(RGBLED_HEADER)
#define RGBLED_HEADER

#include "rgbColor.h"

//Class rgbLed
class rgbLed {
  public:
    // Orthodox cannonical form
    ~rgbLed(); // Destructor
    // Other constructors
    rgbLed(int,int,int);
    // Color assignment of RDG LED
    void set(const rgbColor);
  private:
    // Unusable and hidden orthodox cannonical form
    rgbLed();  // Default constructor
    rgbLed(const rgbLed&); // Copy constructor
    rgbLed& operator = (const rgbLed&); // Assignment operator
  private:
    // RGB LED associated Arduino pins
    int redPin;
    int greenPin;
    int bluePin;
};

#endif

rgbLed.cpp Implementation File

The rgbLed implementation file contains the implementation of all methods declared in the public section rgbLed header file. All method names within the file are prefixed with the class name followed by two colons. In the case of the rgbLed class, all its methods are prefixed with rgbLed::.

The destructor rgbLed::~rgbLed() does nothing. The rgbLed::rgbLed(int redPin, int greenPin, int bluePin) constructor sets the specified pins as output and sets their digital value to LOW, extinguishing all LEDs. The rgbLed::set(rgbColor color) method writes an analog value between 0 and 255 corresponding to each color value to the RGB LED pins.

/*
rgbLed class (implementation)
Class rgbLed represents an external rgbLed
MIT License
Copyright (c) 2018, Michel Lagace
*/

#include "Arduino.h"
#include "rgbLed.h"

const int ANALOGMAX = 255;       // Maximum analog output value

// Destructor. Does nothing.
rgbLed::~rgbLed() {
}

// Constructor with initializers. Initalizes the LED with
// the specified red, green, and blue pins.
rgbLed::rgbLed(int r, int g, int b) {
  redPin = r;
  greenPin = g;
  bluePin = b;
  pinMode(redPin,OUTPUT);
  pinMode(greenPin,OUTPUT);
  pinMode(bluePin,OUTPUT);
  digitalWrite(redPin,LOW);
  digitalWrite(greenPin,LOW);
  digitalWrite(bluePin,LOW);
}

void rgbLed::set(rgbColor color) {
  // Output color to RGB LED
  analogWrite(redPin,color.red()*ANALOGMAX);
  analogWrite(greenPin,color.green()*ANALOGMAX);
  analogWrite(bluePin,color.blue()*ANALOGMAX);
}

Published by

Michel Lagacé

More than 44 years working in the high technology sector, I now share tips and tricks on software and electronics. I also love to cook and to write in my spare time.

2 thoughts on “Programming with Class”

Leave a comment