1 - Why another library and why in C++

If you are familiar with C++ and object orientated programming (OOP) then you may want to skip to the next section - or read the last <PROLOGUE> paragraph in this section. If you are new to these concepts then a brief overview now follows but remember that this is not a tutorial on how to program in C++ as you can 'google' for existing articles on this large subject.

 

So why C++?

 

Let's start by looking at a typical C program. This has one 'main' routine (ie the starting point) that calls various functions, or subroutines in BASIC parlence, which are either defined in the same file or are 'pulled in' via other header (*.h) files. So the program is very flat in structure - by which I mean that you could cut all of the code from all of the other files and paste them into one monolithic file which does everything (this is what the linker does for you - it merges code). If you do this you will notice that any of your functions can be called by any other code and that any of your variables can be read or written by any of the functions - everything is visible to everything.

 

Assume that you've been prototyping some new software and its all got quite big and complex and you have now decided that you want to get rid of the LED that you added on Port B5, say, for debugging purposes. So you now have to find all of the variables and functions that play with this LED and delete them - and this can mean wading through lots of code. The same thing would happen if you decide to move the LED to port B6 instead of B5. So the moral of this story is that the 'bigger' your code gets then the harder it becomes to maintain (let alone read and make sense of), and hence the increased chance of bugs arising in your code.

 

An interesting metric is that you will introduce a bug into your code for every 10 lines of new code that you write. (OK so this depends on the language etc etc - but is a fairly safe assumption that has been in use by software companies for ages).

 

So how do we make life a little bit simpler? In C you can create methods that deal with the LED. Here are 2 methods from the $50 Robot Tutorial which assume that the LED is attached to D4.

 

 

void LED_on(void)
{
PORT_OFF(PORTD, 4);//turn LED on
}
void LED_off(void)
{
PORT_ON(PORTD, 4);//turn LED off
}
These functions are useful because your main code may turn the LED on or off from lots of different places - so now you can shift the LED to D5 just by changing the two functions rather than every single place in your main code - since your main code just calls 'LED_on()' or 'LED_off()'. In OOP terminology we say that the functionality of the LED has been 'abstracted' - ie your main code doesn't care what pin the LED is connected to as it can continue to call 'LED_on()' and 'LED_off()'. OOP also says that the implementation of how the LED is turned off or on has been encapsulated into these two functions - ie they are the only places that actually know HOW to manipulate the LED. So in a C world then the use of functions is good because it allows our main code to be more abstract from the implementation and our main code is smaller and easier to understand.

 

OK so if functions are good then how does C++ help? To answer the question then lets start with a situation where C is not helpful.

 

Lets assume that rather than one LED you want to have, say, three LEDs on D4,D5 and D6. In C the easiest thing to do is to use cut and paste in your text editor so that you have an 'on' and an 'off' for each of the LEDs. So:-

void LED1_on(void)
{
PORT_OFF(PORTD, 4);//turn LED1 on
}
void LED1_off(void)
{
PORT_ON(PORTD, 4);//turn LED1 off
}

 

void LED2_on(void)
{
PORT_OFF(PORTD, 5);//turn LED2 on
}
void LED2_off(void)
{
PORT_ON(PORTD, 5);//turn LED2 off
}

 

void LED3_on(void)
{
PORT_OFF(PORTD, 6);//turn LED3 on
}
void LED3_off(void)
{
PORT_ON(PORTD, 6);//turn LED3 off
}

 

your main code can then do:

 

LED1_on();

LED3_off();

... etc

 

 

Yep - that will work! But when I used cut and paste to duplicate the functions then I had to be very careful to make sure that I changed the pin numbers so as not to introduce any bugs. Big deal you may think. Well since I can have 8 LEDs on port A, another 8 on port B, and another 8 on port C then I could have to cut and paste stuff 24 times if I wanted 24 LEDs!! However - we don't want to do this otherwise the 24 copies will take up valuable flash memory space for all this code and my program may not require all 24 LEDs.

 

Obviously the code to turn an LED on or off is very simplistic - consider how much code you would be duplicating if it was controlling something more complex like a servo which may, unlike an LED, also require other temporary variables !!

 

This is where OOP comes in.

 

The usual benefits of OOP are normally listed as 'encapsulation' and 'polymorphism' (amongst others see google). So I will now try to describe what they mean and why they are good.

 

If you think about it - the code to handle an LED, a Servo or most 'things' is basically the same - the only change is the controller pin that it is connected to. So in OOP we can define a 'class' (think of it as a 'thing') called an LED or a SERVO. This class contains the code that defines how that 'thing' works. The class would have 'methods' (which are the OOP version of functions that operate on the thing) called On() and Off(). When we want a new LED we can construct what is called a new 'instance' of that class, ie an actual LED, and at that point we say which pin it is connected to. So our main code can create LEDs on pins D4 and D8 by:

LED led1('D',4);

LED led2('D',6);

When these LED instances are created we store away the pin number (ie D4, or D6) in class variables which are invisible to the rest of the code and so cannot get corrupted. When we call:-

led2.On();

it knows to use the 'On()' code for 'led2' and it also knows that led2 is connected to D6.

 

Our 'main' code can create as many, or as few, LED instances as you want without introducing ANY more code. This is because the LED class encapsulates the functionality of how to turn an LED on or off. If there are any bugs in your LED code then you only need to change the code in the LED class as opposed to all the places that you cut and paste it to (eg the potential 24 LED functions in the C example listed previously).

 

This demonstrates one of the key components of OOP called 'encapsulation'. You can write all of the code for an LED in one class file that does the logic required. This code is hidden from the rest of the program - ie just call led1.On() - and it happens - you don't need to worry about how it does it. Other OOP languages call this an 'interface' or a 'contract'. Think of your 'contract' with the mail delivery service:- so long as you write the name and address on an envelope before putting it into a mail box then it will get delivered. You dont care if they use planes, trains, automobiles, bicycles or robots to do it - thats up to the mail company.

 

Astute developers will realise that you can achieve something like this in C by using a 'struct' to store the variables (like port and pin) for a given LED and then pass that to a generic LED_on or LED_off function - you are right but read on.

 

What about that complicated sounding 'polymorphism' thing? The standard analogy is to consider writing a drawing program on a computer. Lets assume that your program allows the user to draw circles and rectangles. So we will need two classes one called Circle and one called Rectangle. Each of these classes would need a method called 'draw' which draws the shape on the screen. But you probably want to be able to drag the mouse so that you can move the shape around the screen before drawing it. To do this you can draw the shape, wait for a mouse change and then 'clear' the shape at the old location before using 'draw' to draw it at its new location. So both of our brush shapes should have a 'clear' and a 'draw' method. Hey but this is the same for all shapes - if you can draw 'yourself' and clear 'yourself' then it doesn't matter what shape you actually are. So now we can create something called a 'Brush' which defines methods called 'clear' and 'draw' which don't actually do anything because the actual implementation depends on whether the brush is a Circle or a Rectangle - ie it adapts at runtime to call the method on the apppropriate thing.

So our main code for the dragging could look like this:-

void mouseDrag(Brush brush, int x, int y){

brush->clear(oldx,oldy); // clear the old brush

brush->draw(x,y); // draw the new brush at the new location

oldx = x; oldy=y; // remember the location for the next clear

}

This is called 'polymorphism' because this will work with ANY brush shape. If I create a new brush to draw an ellipse that has a 'clear' and 'draw' method then the above code will not need to change.

 

Shapes, drawing ? What has that got to do with robotics? Well instead of a 'brush' think of a motor that instead of clear/draw has a 'SetSpeed(int speed)' method. Instead of 'Circle', 'Rectangle' brushes I could create different sorts of motors eg a modified servo motor, a PWM controlled motor, an HBridge controlled DC motor but so long as they all have a 'SetSpeed' method that behaves the same then I could change between any of them without ANY code changes other than where I define the motor on the one line of my main program. Hence 'polymorphism' means that they are all motors and it is only at runtime that you need to say what kind of motor it is. Since they all behave the same, ie have the same set of methods, then they are interchangeable.

 

You astute C guys may say - "I can still do this in C". You're correct although it's now getting a bit more difficult for you. And its about to get harder...

 

At the start of this page we talked about merging all C code into one big file and how everything would be accessible to everything else. Lets concentrate on the Motor interface which just has methods to set the required speed and, maybe, to read the current speed. We discussed previously how this lets you drop-in different motor implementations without having to change you code. Well what if the motor code represented a DC motor via H-Bridge with Encoder feedback. Well the Encoder probably just helps to make sure that the 'SetSpeed(int speed)' method does what it says - but in order to do this it may require several variables to be remembered between calls and there may be other lumps of code eg 'int readEncoder()' all of which only apply to this sort of motor controller. In OOP you can create methods and variables with a given 'visibility' of 'public', 'protected' or 'private'. 'public' stuff can be accessed from anywhere. By 'accessed' I mean: if it is a method then it can be called from anywhere but if its a variable then it can be read/written from anywhere. 'protected' items can only be accessed by an instance of this type or by a derived class - ie a motor variable such as 'currentSpeed' can only be seen by a Motor or another kind of motor. A 'private' variable can only be seen by the same instance - so our Motor+Encoder example above may have a private variable for current encoder position which is not visible to anything except THAT motor.

 

So what's the difference? Well the 'public' methods define the interface/contract with the outside world - ie this is 'what you can ask me to do'. 'private' methods/variables are generally connected with how the class actually does things and since they are not visible to other code then they can be changed without any effect on the outside world. 'protected' methods/variables are a half-way-house in that if you create one in the Motor class then it is visible to anything that is a Motor but is invisible to anything else.

 

You astute C folk will realise that this is kinda where you have to throw in the towel as C cannot enforce visibility as it has no concept of it. I'm sure the real hard-core C folk will still want to beat me up as to how they can work around it but 'why bother' - C++ was designed to make life easier!  But why does 'visibility' matter? Well if everything is visible to everything, as in C, then it can make debugging a nightmare - eg if a variable value is getting changed unexpectedly then the culprit could be in ANY of the code. Whereas, if the variable in C++ is 'private' then the only code that can change it is the class that it belongs to. It also makes modifying code easier since a 'private' variable can only be accessed by the class then it means you can change the implementation code and add/delete/rename variables knowing that this wont upset any other code as it couldn't see the stuff you are changing anyway.

 

<PROLOGUE>

C++ adds some great stuff to make programming easier and more legible but there are times when it doesn't add anything above C, BASIC or Assembler. As we have seen above the ability to create new LEDs is very easy and you can create as many, or as few, as you like. However, once the thing you are trying to control has an interrupt then this benefit reduces down to the level of C. For example: a UART has receive/transmit interrupts that are different for each UART (most AVR processors only support 1, some support 2). So creating 5 Uart objects makes no sense. This is a hardware issue rather than the programming language - but if you can only create one instance of something then the C++ code approximates to the C code . The last question I guess is  - "So OOP constructs apart: then what else does this C++ library do for me". To which the quick answer is initialisation. Create one 'SERVOPWM' motor and the library will automatically set up PWM, equally if you define any A2D inputs then it will set up the A2D convertor. So your main code can concentrate on doing software stuff and delegate the hardware initialisation back to the library. Check out my Photophore code that uses the C++ library and you will see that there are NO calls to initialise things.