I'm working inside the Arduino IDE environment and have made a class that builds on the Adafruit RDG LCD with interrupts While looking at how to combine the Attach Interrupt()
into my class I came across this post about using namespaces
Why make a class then? What about a namespace?
A class with one instance is like a group with one person in it.
-nickgammon
Understanding that Mr.Gammon is kind of a big deal around these parts, I'd like to understand how to insert/alter my current class into a namespace format. Currently, the most in-depth tutorial I've found is here, but I don't see how I would mix in the Attach Interrupt()
function
Right now, my code looks like
/**** Pre-Setup *****/
#define Menu_PIN 3
voltile bool flag;
//Init Class
class LcdMenu : public Adafruit_RGBLCDShield
{
public:
MenuFoo()
}
LcdMenu LcdM;
//run Setup
void setup() /****** SETUP: RUNS ONCE ******/
{
pinMode(Menu_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(Menu_PIN), ProcMenu, FALLING);
}
void loop()
{
if(flag){
LcdM.MenuFoo();
flag=false;
}
}
//Handles Inturrupts for Class
void ProcMenu()
{
flag=true;
}
//define MenuFoo
void LcdMenu::MenuFoo(){[code]}
As I understand it, Implementing a namespace would eliminate the need for the ProcMenu()
function making my code easier to read/maintain.
2 Answers 2
In this particular instance, and since you are inheriting from a class
of a known library, making your own class makes sense. You just have to
be aware that, although you can in principle have multiple instances of
a class, you can only have one single handler for a particular
interrupt. Thus the handler cannot be a regular method of the class (a
method that knows it has been called for this
instance), but it can be
a static
method. Such a method is much like a regular function which
uses (abuses?) the class as a sort of namespace.
I would try something along these lines:
class LcdMenu : public Adafruit_RGBLCDShield
{
public:
LcdMenu();
void begin([params]) {
Adafruit_RGBLCDShield::begin([params]);
attachInterrupt(digitalPinToInterrupt(Menu_PIN), handleInterrupt, FALLING);
}
void MenuFoo();
void update() {
if (flag) {
MenuFoo();
flag=false;
}
}
private:
static volatile bool flag;
static void handleInterrupt() { flag = true; }
}
volatile bool LcdMenu::flag;
Then you just have to call LcdM.update()
in loop()
.
-
Don't forget to give your member functions return types... (apart from the constructor of course).Majenko– Majenko2018年01月22日 15:37:12 +00:00Commented Jan 22, 2018 at 15:37
-
to clarify:
begin()
is the constructor and the member functions should read something to the effect ofvoid MenuFoo();
ATE-ENGE– ATE-ENGE2018年01月22日 15:40:52 +00:00Commented Jan 22, 2018 at 15:40 -
Ok so I got the
attachInterrupt()
function into the class, but when I try to addstatic volatile bool flag;
I get an error sayingcckcVoVT.ltrans0.o:(.text.startup+0x838): undefined reference to 'LcdMenu::flag'
ATE-ENGE– ATE-ENGE2018年01月22日 16:33:40 +00:00Commented Jan 22, 2018 at 16:33 -
@Majenko: Oops! Fixed, thanks! @ATE-ENGE:
LcdMenu::flag
has to be defined, in addition to being declared. I added that to the code snippet in the answer.Edgar Bonet– Edgar Bonet2018年01月22日 18:17:53 +00:00Commented Jan 22, 2018 at 18:17
I don't it will change your design.
The main reason to use namespaces is to have an extra 'layer' of hierarchy.
Like a book that can be divided in chapters (classes). But if you want to combine multiple books (projects) than you use name classes (e.g. to prevent name clashes of equally named class names).
ProcMenu()
into theLcdMenu
class. It will have to be static and then you can write member function to hide theattachInterrupt()
e.g.LcdM.begin(MENU_PIN);
LCD Menu
is aAdafruit_RGBLCDShield
As to why overall, I wanted a way to group the LCD functions together.