4
\$\begingroup\$

I'm writing a new Arduino project that uses an 16x2 LCD Crystal Display with a KeyShield. I would like to construct a menu structure in which the user can navigate using the buttons.

I'm new to Arduino but I do have 5 yrs experience in C#. What I would like to do is the following:

Define an interface called Screen and inherit each Screen from it such as LanguageScreen, TurnOffAfterScreen, MainScreen, etc. Each specialized Screen implements a method called drawScreen that will take care of the screen content.

Now I would like to have a class named ScreenController that handles the navigation between the Screens. In this class I'd like to store the screens in an array Screen screens[3].

When user presses the Select button on the KeyShield the Controller would call the next Screen's drawScreen method something like this:

void showNextScreen()
{
   currentScreen++;
   screens[currentScreen]->drawScreen();
}

Is this possible to do in an Arduino project? Am I expecting too much? :)

\$\endgroup\$
  • \$\begingroup\$ There’s no particular reason why this cannot be made to work. However, in C++, Screen would have to be an (abstract) base class, and your array would have to be Screen * screens[3]. \$\endgroup\$ – microtherion Jun 18 '13 at 19:51
  • \$\begingroup\$ Sounds cool! Can you post some code as well? \$\endgroup\$ – papaiatis Jun 18 '13 at 19:53
  • \$\begingroup\$ I’ve added some code in an answer below. This is really straightforward C++ code with little Arduino specific relevance. \$\endgroup\$ – microtherion Jun 18 '13 at 20:53
3
\$\begingroup\$
class Screen {
public:
   virtual void drawScreen() = 0;  // Needs to be implemented by each subclass

   virtual ~Screen() {}            // Destructor
};

class LanguageScreen : public Screen {
public:
   virtual void drawScreen();
};

class MainScreen : public Screen {
public:
   virtual void drawScreen();
};

void LanguageScreen::drawScreen() {
   // Draw language screen
}

void MainScreen::drawScreen() {
   // Draw main screen
}

MainScreen     mainScreen;
LanguageScreen languageScreen;
Screen *const  screens[2]   = {&mainScreen, &languageScreen};
int            currenScreen = 0;
\$\endgroup\$
  • 2
    \$\begingroup\$ It would be a good idea to avoid calling new in a microcontroller example. Declare them as statics/globals and then use their addresses. \$\endgroup\$ – walrii Jun 19 '13 at 0:15
  • \$\begingroup\$ Good point, @walrii. I’ve revised the code to do that. \$\endgroup\$ – microtherion Jun 19 '13 at 1:28
  • \$\begingroup\$ Thank you so much! This was quite helpful. Now I have good menu structure using well defined OOP code :) \$\endgroup\$ – papaiatis Jun 20 '13 at 18:19
  • \$\begingroup\$ I'm coming from PHP and I'm expecting to get an error message if I don't implement a method in a class that's based on an interface. class Screen { public: virtual void drawScreen() = 0; // Needs to be implemented by each subclass virtual ~Screen() {} // Destructor }; class LanguageScreen : public Screen { // I didn't define the void drawScreen(); }; So I actually want to get a message that the method drawScreen() is missing in the class LanguageScreen since it implements the "interface" class Screen. Or is this different to PHP? \$\endgroup\$ – alve89 yesterday
1
\$\begingroup\$

C++ using classes on a microcontroller with limited memory is generally not considered to be a viable development strategy. There are literally limitless ways that you can construct a "menu system" on a display without having to resort to resource intensive OOP programming style.

Edit: I am amazed at the reader reaction to putting a lot of down votes to my answer. I can tell you that with over 30 years of experience in developing code and firmware solutions for microcontrollers of many sorts that there is truth to the statement of my answer. There are loads of applications using low performance MCUs (in comparison to their big brothers in PCs and the like) where the program at times even needs to be coded in assembly language to get the job done in a efficient and low latency way.

\$\endgroup\$
  • \$\begingroup\$ It won't be that big project so I'm not afraid of running out of memory. I prefer OOP to spagetti code. \$\endgroup\$ – papaiatis Jun 18 '13 at 19:47
  • 2
    \$\begingroup\$ @papaiatis - A menu system can be coded in nice clean programming style in C or even Assembly language without it turning into spagetti code. The latter mess of code usually results when you try to program something up by the seat of the pants without taking the time to do a full architectural design of the intended functionality tp be developed. \$\endgroup\$ – Michael Karas Jun 18 '13 at 19:57
  • \$\begingroup\$ You might be right I have no doubt. But I'm still rather interested in the OOP way. \$\endgroup\$ – papaiatis Jun 18 '13 at 20:05
  • 3
    \$\begingroup\$ The Arduino I/O library is in fact a very conventional OOP design, constructed around a set of classes with virtual methods. There is little in OOP programming style which is inherently “resource intensive”. \$\endgroup\$ – microtherion Jun 18 '13 at 20:47
  • 1
    \$\begingroup\$ I concur - given the limited memory on these puppies, you are right on the money with your answer. I also dislike the buttons on these LCD shields, as they use variable resistance for each button through an analog input, and the shield I have gives some wildly different values each time. \$\endgroup\$ – Ron J. Jun 19 '13 at 12:53

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.