8

I have been programming for quite a while now but I am new to Arduino and AVR Programming. The main question I have about programming these Micro-controllers is are there major differences in designing code in Object Orientated Classes vs the more traditional inline programming I have seen in many examples?

In other words in the world of Arduino/AVR Controllers are there any savings with Memory and Performance utilizing classes or visa versa?

Say for example we have a Class:

class SomeClass(){

private:
   int x;
   int y;

public:
   void foo();
   void bar();
}

SomeClass thisClass;
thisClass.foo();
thisClass.bar();

Would there be any performance or memory gains designing the program in a more inline fashion like:

int x;
int y;

void foo(){ /*** Do something ***/};
void bar(){ /*** Do more stuff ***/};

I tried doing some searches on Stack Exchange and Google but couldn't find quite the answer I am looking for the closest thing I was able to find was this Stack Exchange Question.

The reason I am asking about this is I have a project that needs to be as light as possible and I am not clear how I should be designing my program in this environment.


Edit

Thank you for the answers, this has shed light on things. There is one thing that I am not quite clear about.

Say you have a class that you are designing that utilizes the u8glib as follows:

class UserInterface{
private:
   U8GLIB_ST7920_128X64 Display;

public:
   UserInterface();
}

How would you get around using "Dynamic Memory" like:

UserInterface::UserInterface(){
   UserInterface::Display = U8GLIB_ST7920_128X64(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE);
}
2

The main question I have about programming these Micro-controllers is are there major differences in designing code in Object Orientated Classes vs the more traditional inline programming I have seen in many examples?

...

In other words in the world of Arduino/AVR Controllers are there any savings with Memory and Performance utilizing classes or visa versa?

Yes, there is a great difference between using C or C++ for small scale embedded systems such as Arduino/AVR. C++ allows more information to be provide for compiler optimizations.

If you are implementing an OOP framework, platform or runtime C++ and classes can also help with software architecture and reuse. In Cosa a number of OOP design patterns are used to achieve interfaces for both application programmers and device driver programmers. The most common is delegation.

Using abstract classes, virtual member functions, inlining, and templates can help achieve lower foot-print and higher performance than traditional implementations. As an example the Cosa Pin classes are X5-X10 faster than the Arduino core and at the same time smaller in foot-print. Please see the benchmarks.

One thing to "unlearn" from traditional C++ programming is the usage of new/delete (malloc/free). With SRAM size of only a few Kbyte using a heap is very much a risk. The answer is static classes and stack based data.

There is much more to be said about OOP framework architecture but I hope this helps answer your initial questions.

Cheers!

  • Nice Answer! I updated my question asking about how to get around the dynamic memory (new/delete/malloc/free). Do you have any input on not using dynamic memory allocation? Should everything that needs to be shared throughout the classes be global? That doesn't sound right to me, I was always taught not to use globals if you can help it. – Andy Braham Dec 1 '15 at 22:20
  • A short comment on your UserInterface example above. The Display is actually object composition (not reference/pointer) so you do not need new. You do need to initiate the Display. The UserInterface construction should look something like this. UserInterface::UserInterface() : Display(LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE) { ... }. The necessary Display constructor parameters should be passed to the UserInterface constructor. – Mikael Patel Dec 2 '15 at 10:54
  • OOP is all about encapsulation, hiding data, so sharing should be a minimum (zero). The goal is to more or less only have a number of global static objects that interact. They hold and hide the global state. For the objects the member data is a non dynamic local state. To achieve the goal you need again a set of tricks; program transformations. – Mikael Patel Dec 2 '15 at 11:10
  • An example; Consider the design of a BitSet class that may have variable number of members. The obvious solution is to calculate the number of bytes required and use new/malloc. An alternative is to pass the storage as a parameter to the BitSet constructor. A third alternative is a template class with number of elements as parameter. This allows a member variable that is the necessary number of bytes. Please see Cosa/BitSet.hh for more details on this variant of program transformation. There are more transformations. – Mikael Patel Dec 2 '15 at 11:12
  • I updated my UserInterface example, is that more or less the correct approach? I think I now have a very good understanding on how to implement what I need to. – Andy Braham Dec 2 '15 at 16:16
4

The reason you can't find the answer is because the answer is both Yes and No.

For basic class stuff - defining your class with methods etc and instantiating objects from it - there's little difference in the end result compared with "vanilla" C. The compiler's optimizations are so good now that performance is just the same. Yes, there may be slight increases in memory use since you're passing an extra pointer with each method call (instead of foo(int x) you have foo(MyClass *this, int x)) but that's so small as to not be noticeable.

The big differences come when you start playing with polymorphism and other advanced topics. When start doing these complex programs the compiler is not always unable to work out which functions are required and which aren't, and it's not able to cut out the unused functions ("garbage collection"). So you may well end up with bigger code.

That doesn't mean slower code, just chunks of code that are hanging around that never do anything.

Of bigger importance is managing your dynamic memory better than you are used to. Since there is such a small amount of memory the heap is very small, and as a result it gets fragmented very easily. Dynamic creation and destruction of objects (new myClass, delete myClassObject, etc) is very bad. Class objects really need to either be statically defined (in global scope is the most common) or temporarily allocated on the stack (local instances). Otherwise you're asking for trouble - and the first you will know of it is strange things happening (no error reports or exceptions, you see...).

  • Alright so if I understand this correctly in this world of programming, classes are used for more of a organizational and portability role than true OOP and that things should be allocated statically and explicitly rather than dynamically. Great thank you, this makes allot of sense and explains why I have been seeing examples and what not written the way they are. – Andy Braham Nov 20 '15 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.