Encapsulation & Accessibility in C++

Encapsulation : 

Encapsulation is another major component of OOP . the process of restricting access to data is called encapsulation. Encapsulation can be used to hide data members and members' functions. 

note: Class members are actually Class variables(data) and functions 

Access modifiers: 

Access modifiers are keywords in OOP that set the accessibility of classes, methods, and other members. Access modifiers are a specific part of programming language syntax used to facilitate encapsulation. in C++ there are 3 access modifiers 
  1. public 
  2. protected
  3. private 

Explanation:

Suppose you have created a class A. 
Then The private, public and protected members of class A can be accessed within the class. Now say you have created an object of this class then the object can only access the public members of the class. 

Similarly, if you derive a class B from the base class A then the derived class B can access the protected & public members of the base class A

now if you create an object of type Class B then the object can only access the public members of class B. now whether this object can access the members of the Base class A depends on the inheritance type. if it's public then this object of type class B can access public members of class A . on the other hand if the inheritance type is private then this object of type class B won't be able to access public members of class A.   

Now see the following diagram and you will understand everything 

Access specifiers without inheritance: 

Access specifiers with an inheritance: 










C++ in Arduino : Inheritance

What is Inheritance?

Inheritance is the process of creating new classes called "derived classes" from existing classes called "base classes". the derived class inherits all the capabilities of the base class & can add refinements of its own.

But why implement inheritance?

The answer is inheritance permits code re-usability. Suppose that you have made or got a class that is working perfectly but you want to add your own features to that class . Now instead of modifying the codes of Class A you can create a new class and inherit all the properties of Class A . in this way if any bug occurs you will be sure that it is from your newly made class thereby simplifying development by a lot. Inheritance is a major element of OOP.

the derived class is also called the child class
the base class is also called the Parent class

In some languages, the base class is called the superclass and the derived class is called the
subclass.

you will also hear the term child class extending parent class which is actually the same thing i.e. child class inheriting properties of the base/parent class.

let's see inheritance in UML with a very simple example

         
Here Animal is the Base class And Dog is the Derived Class . as Dog is an animal too so it will have all the capabilities of an animal. 

In UML inheritance is called generalization. In UML class diagrams, generalization is indicated by a triangular arrowhead on the line connecting the Derived and Base classes. The Arrow means derived from. The direction of the arrow tells that the derived class refers to functions and data in the base class, while the base class has no access to the derived class. 

Code in Action 

Lots of theory now Let's jump into Arduino and write some practical codes.

Returning to the Sensor Class that we made in our previous post  https://whileinthisloop.blogspot.com/2016/05/c-in-arduino-isr-in-class.html We have a proper working Sensor Class . and let's say we want to use this class For temperature measurement and we want to add functions like 
  • readCelsius() 
  • readFahrenheit() 
Now we can add these extension of ours using inheritance and by doing so we won't have to make any modification to the Sensor class, So to do that let's make a New Class called LM35 which will extend Sensor Class . in UML : 

here are the code snippets for the Sensor Class : 

Sensor.h 

#ifndef _SENSOR_H      //tells compiler to compile this class only once 
#define _SENSOR_H 

#include <Arduino.h>

class Sensor
{
   public:
          Sensor();
          void init(void);
          uint16_t readRawAdcValue(void);
          float readmv(void);
};
#endif

Sensor.cpp

#include "Sensor.h"

volatile static uint16_t adcValue = 0;

Sensor::Sensor()                                             
{}

void Sensor::init(void)
{
  ADMUX|=(1<<REFS0);    //AVCC with external capacitor at AREF pin 
  ADMUX|=(1<<MUX2)|(1<<MUX0); //0101adc channel 5 selected for adc input
  ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);   //prescalar 128 selected 
  ADCSRA|=(1<<ADEN);    //adc enabled
  ADCSRA|=(1<<ADATE);   // ADC Auto Trigger Enable
  ADCSRA|=(1<<ADIE);   //adc interrupt enable such that interrupt will happen after each conversion
  ADCSRA|=(1<<ADSC);   //conversion process begins
  sei();
}

uint16_t Sensor::readRawAdcValue(void)
{
  return adcValue;
}

float Sensor::readmv(void)
{
  return((readRawAdcValue()/1024.0)*5000);
}

ISR(ADC_vect)       //adc interrupt service routine /tasks which will be executed by microprocessor after each conversion
{
adcValue=ADCL;        //ADCL data register read 
adcValue+=(ADCH<<8);  //ADCH data register read
}

LM35.h

#ifndef _LM35_H      //tells compiler to compile this class only once 
#define _LM35_H 

#include <Arduino.h>
#include "Sensor.h"

class LM35:public Sensor     //LM35 class inherits base class Sensor
{
   public:
          LM35();
          float readCelsius(void);
          float readFahrenheit(void);
};
#endif

Notice that after colon : the base class name is written. this sets up the relationship between the parent and child class.

The keyword public after the colon 
: specifies that objects of the derived class LM35 are able to access public member functions of the base class Sensor. The alternative is the keyword private. When this keyword is used, objects of the derived class LM35 cannot access public member functions of the base class Sensor.

LM35.cpp

#include "LM35.h"

LM35::LM35()                                             
{}

float LM35::readCelsius(void)
{
  float mv = readmv();
  float cls = mv/10.0;
  return cls;
}

float LM35::readFahrenheit(void)
{
  float cls = readCelsius();
  float fhr = (cls*9)/5 + 32;
  return fhr;
}

Now let's write the sketch which will create an object of LM35. 

the sketch 

/*
 * this example shows the inheritance of c++ 
 * author: Hassin Ayaz
 * http://whileinthisloop.blogspot.com/
*/
#include "LM35.h"

LM35 myTempSensor;

void setup() 
{
  Serial.begin(9600);
  myTempSensor.init();
}

void loop() 
{
  Serial.print("raw ADC value: ");
  Serial.println(myTempSensor.readRawAdcValue());

  Serial.print("in mv: ");
  Serial.println(myTempSensor.readmv());

  Serial.print("in celsius: ");
  Serial.println(myTempSensor.readCelsius());

  Serial.print("in fahrenheit: ");
  Serial.println(myTempSensor.readFahrenheit());
  Serial.println("-----------------------------");
  delay(1000);
}

here you can see that the LM35 type object myTempSensor can call functions of both the base & derived classes.

In this post we have seen how inheritance of OOP can increase the usability of our codes :)

All the sources are available in this link https://github.com/hassin23ayz/ArduinoCpp/tree/master/T37_inheritance

C++ in arduino : ISR() in a class

In the last post https://whileinthisloop.blogspot.com/2016/04/c-in-arduino-interrupted-adc-with-free.html I showed you how to run the ADC in free-running mode. In this post I am going to show you how to wrap up the ISR() in a Class

I don't know if you have tried it or not but implementing ISR() in a class is a bit tricky ;)

Handling interrupts is not only a job for C or assembly language actually  C++ can also handle it. In a later post, I will show how to wrap up the ISR() with the help of some advanced concepts of c++ like virtual function. 

But in this post, I am going to show you a quick & simple way that may help you if you don't understand advanced concepts of C++. So if you are willing to design and maintain OOP concepts and want to implement your  ISR() in a class in a simple way then this post may help you.

Note: The way I am going to show is kind of mixing C & C++ concepts.

To keep our embedded context relevant, we are going to make a Sensor Class from the last post's codes,

First Let us make the declaration file (sensor.h)


#ifndef SENSOR_H_     //tells compiler to compile this class only once 
#define SENSOR_H_

#include <Arduino.h>
#include <avr/interrupt.h>

class Sensor
{
    //variables
  public:
  private:

    //functions
  public:
    Sensor();
    ~Sensor();
    void init(void);
    unsigned int readAdcValue(void);
};

#endif

you can see that there is no ISR(ADC_vect) function declaration in the header file.

now let's make the implementation file (sensor.cpp)

#include "Sensor.h"

static unsigned int adcValue; //this variable's scope is only this file 

//constructor
Sensor::Sensor()
{}

//destructor
Sensor::~Sensor()
{}
void Sensor::init(void)
{
  //initiating variables
  adcValue = 0;

  //initiating registers
  ADMUX |= (1 << REFS0); //AVCC with external capacitor at AREF pin
  ADMUX |= (1 << MUX2) | (1 << MUX0); //0101adc channel 5 selected for adc input
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); //prescalar 128 selected ADC clk = 125KHz
  ADCSRA |= (1 << ADEN); //adc enabled
  ADCSRA |= (1 << ADATE); // ADC Auto Trigger Enable
  ADCSRA |= (1 << ADIE); //adc interrupt enable such that interrupt will happen after each conversion
  ADCSRA |= (1 << ADSC); //conversion process begins
  sei();                 //global interrupt enabled
}

unsigned int Sensor::readAdcValue(void)
{
  return adcValue;
}


ISR(ADC_vect)       //adc interrupt service routine /tasks which will be executed by microprocessor after each conversion
{
  adcValue = ADCL;      //ADCL data register read
  adcValue += (ADCH << 8); //ADCH data register read
}

Note that the adcValue variable is a  static unsigned int type global variable & this variable gets updated in the interrupt service routine but why I have not declared this variable as a Class member variable? the answer is as 
the ISR() function is not a Class member function you won't be able to access any Class member variable in the ISR() .  

Also, note that the adcValue is a static variable which means its scope is limited to the cpp implementation file only. This pattern provides a data abstraction like private variables in a class. This is kind of implementing a C++ feature in C.

As per language pattern One may argue on the above approach but I found this simple solution working without any runtime / compile time issue but obvisously there may be better ways to implement.

C++ in arduino : interrupted ADC with free running mode

Does your embedded product need faster ADC processing and do you want to implement all that in C++ . In this post I am going to show you how to run ADC of Arduino UNO in interrupted mode. In the next post, we will wrap the code in C++. 

But why do we need to run ADC in interrupted mode?

Well, when you use analogRead() to read an ADC value CPU goes to the function & waits until a conversion is completed by the ADC peripheral. So you are actually waiting and wasting the CPU cycles.

How about you tell the ADC peripheral of the MCU to inform you when it finishes a conversion. In this way, CPU can go back to doing other works and return the ADC value once it is ready/converted. 

So the optimized way is to enable the ADC interrupt & configure the ADC to run in free-running mode. the following code snippet shows how to configure the ADC registers of atmega328 for this purpose.

  ADMUX|=(1<<REFS0);    //AVCC with external capacitor at AREF pin 
  ADMUX|=(1<<MUX2)|(1<<MUX0); //0101adc channel 5 selected for adc input
  ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);   //prescalar 128 selected 
  ADCSRA|=(1<<ADEN);    //adc enabled
  ADCSRA|=(1<<ADATE);   // ADC Auto Trigger Enable
  ADCSRA|=(1<<ADIE);   //adc interrupt enable such that interrupt will happen after each conversion
  ADCSRA|=(1<<ADSC);   //conversion process begins
  sei(); //dont forget to enable the global interrupt 

Please Note that Arduino UNO's mcu is actually atmega328 And the above C snippet configuring Registers will also get compiled by Arduino IDE. 

In this mode after each conversion ADC peripheral will automatically throw an interrupt and at that interrupt service routine CPU will read the adc value from the ADC register. the following code snippet shows how to handle the interrupt handler. 

ISR(ADC_vect)       //adc interrupt service routine /tasks which will be executed by microprocessor after each conversion
{
adcValue=ADCL;        //ADCL data register read 
adcValue+=(ADCH<<8);  //ADCH data register read
}

We can structure all of the above in a good OOP manner. The steps are described in this link  https://whileinthisloop.blogspot.com/2016/05/c-in-arduino-isr-in-class.html 

C++ in Arduino : auto initialization of private variable at constructor

In C++, there may be cases where we need to initialize a private variable with a particular value. In this post, I want to show how initialization should be done in the right manner so that compiler can generate the exact binary instruction & save us from any undefined runtime issue. We will first go through the basics and then implement the concept for initializing an LCD-type object acting as an LCD driver. 

let's say you have a class Counter with a variable noOfCounts


now you might be thinking to initialize the noOfCounts variable like this 

Counter::Counter()
{
   noOfCounts = 0;
}

although it works BUT it is not the preferred approach. There is a better way which is : 

Counter::Counter():noOfCounts(0)
{}

This way the member noOfCounts gets initialized before the constructor even starts to execute. this is important because this is also the only way to initialize const member data & references.

The above argument is true if you want to initialize an object (which is also a variable) with arguments.  

Now let's see how you actually create an LCD object in your Arduino sketch. You may have declared object like this 
#include <Arduino.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);      //object created with pin numbers as argument

But Now let's say you want to make a custom class of your own that internally uses the LiquidCrystal class and does LCD operations for example showing an animation that the actual 
LiquidCrystal does not do. If you ask me then I would think about the following ways. 
  1. Modify the original LiquidCrystal Class        
  2. Make a new class  by Inheriting LiquidCrystal class or 
  3. Make your own Class where a private variable is of LiquidCrystal type and then initialize that object at your own custom class constructor 
I am going to show you solution no 3 (which is an Aggregate pattern) keeping the original Library as it is. 

First of all, Create your CustomLCD class and declare a LiquidCrystal type object lcd as a private variable :

class CustomLCD
{
   public:
          CustomLCD();
          void showSomething(void);
   private:
          LiquidCrystal lcd;
};

Then you can auto init this lcd variable like the way we discussed avobe i.e. using the colon : at the constructor

CustomLCD::CustomLCD():lcd(12, 11, 5, 4, 3, 2)   //here private variable lcd object gets auto initilized with pins                                               
{
  lcd.begin(16, 2);
}

Then you can create a CustomLCD kind object in your sketch and use it

#include "CustomLCD.h"

CustomLCD myCustomLCD;   //CustomLCD object is created

void setup() 
{
  Serial.begin(9600);
  myCustomLCD.showSomething();
}

void loop() 
{}

here is the circuit simulation output in proteus:



Note: you can also init any basic type class variable in this way & it is a good practice to prevent abnormal runtime behaviors. In a later post, I will explain why! 

All the Source Code and circuit diagrams are available at this link https://github.com/hassin23ayz/ArduinoCpp/tree/master/T36_auto_init_constructor 

C++ in arduino : Classes and objects

Hello in this post I want to share how we can implement OOP concepts in Arduino
OOP  means object oriented programming

In OOP Class is the blueprint of an object, in UML class is represented by a rectangle



Object : 
  • The object is an instance of a Class 
  • Both data and functions that operate on data are bundled as a unit & it is called an object 
  • You can create one or more instances of a Class 
OOP designing help solve the problem in a modular fashion and the code becomes very structured, readable & maintainable 

Making a class in Arduino

.cpp & .h are the 2 file  formats of a c++ class and you only need these 2 files to make a class  

.h contains : 
  • any import statement that the class needs to make
  • name of the class & anything that the class extends 
  • Declaration of variables
  • Declaration of methods 
.cpp contains : 
  • The definition of the methods
Let us create a class Ball in Arduino using the following steps 
  1. Open Arduino IDE 
  2. Save the sketch somewhere 
  3. Click the rightmost arrow and press new tab 
  4. Type Ball.h and press enter
  5. Ball.h header file is created 

Now lets think what does a ball can do ?  ............
well it can bounce :) so lets declare a method named bounce() in the .h file


#ifndef _BALL_H      //tells compiler to compile this class only once 
#define _BALL_H

#include <Arduino.h>

class Ball
{
   public:
          Ball(byte _pin, unsigned long int _bounceTime);
          void bounce();
   private:
          unsigned long int bounceTime;
          byte pin;
};
#endif

here the public function Ball() is the constructor . note you can pass argument to the constructor also

but what can we put in the bounce() ? ...
lets Blink the LED at pin 13 so that it would look like bounce :)

now lets make the implementation file to do this like the header file press newtab and create the Ball.cpp  file

#include "ball.h"

Ball::Ball(byte _pin, unsigned long int _bounceTime)
{
  bounceTime=_bounceTime;
  pin = _pin;
  pinMode(pin,OUTPUT);
}

void Ball::bounce()
{
  digitalWrite(pin,HIGH);
  delay(bounceTime);
  digitalWrite(pin,LOW);
  delay(bounceTime);
}

now your blueprint i.e. Class is ready now you can create an instance of it and play with it . now select the sketch from the tabs & copy paste the following code
/*
 * this example shows how to make Class and create object 
 * author : Hassin Ayaz 
 */

#include "ball.h"

Ball b(13,1000);

void setup() 
{
  Serial.begin(9600);
  Serial.println("Ball object created");
}

void loop() 
{
 Serial.println("Ball will bounce i.e Led will Blink");
 b.bounce();
}

so here an object of Ball type is created (note: object b is a global variable)

verify it and upload it
you will see the LED at pin 13 will blink :)

All the sources are available in this link https://github.com/hassin23ayz/ArduinoCpp/tree/master/T13_obj_classes 

I hope you have enjoyed this post
Welcome to the world of OOP :)

Categories

Pages

Firmware Engineer

My photo
Works on Firmware, Embedded Linux, Smart Metering, RTOS, IoT backend

Contact Form

Name

Email *

Message *

Copyrighted by Hassin. Powered by Blogger.