attachInterrupt with an instance method

Is it possible to somehow invoke attachInterrupt from within a constructor and pass it a method of the instance?
I have found a thread with a similar problem but that's not quite what i'm looking for: Arduino Forum

I understand that it's not possible to invoke a member from within a static method and I understand that I can't pass an instance's method to attachInterrupt as my method (even I defined no parameters) has the invisible 'this' argument.

What I want is to have one instance of a class with a certain configuration (passed as constructor arguments). One part of the configuration is an interrupt pin.
I want to have a second instance of this class with a different interrupt pin.
I don't want the methods handling the interrupt to be in my setup/loop code, but in the .cpp where I implemented the class. I know that I could call attachInterrupt twice within setup() and have the two methods call something like myInstance.handleInterrupt(1), but if there's any chance to do it like I said before, it would prefer that way.

Is this possible?

1 Like

The way described in the thread you linked to is the only I am aware of. You can do it a bit more clever and use some registration service to do the dispatching but you cannot use a method of an instance of a class as an interrupt handler.

You can do it like below with some static class members, but it's a bit fiddly:

class Foo
{
  static void isr0 ();
  static void isr1 ();
  
  const byte whichISR_;
  static Foo * instance0_;
  static Foo * instance1_;
  
  void handleInterrupt ();
  
  volatile int counter_;
  
  public:
    Foo (const byte which);
    void begin ();
    
};  // end of class Foo

void Foo::begin ()
  {
  switch (whichISR_)
    {
    case 0: 
      attachInterrupt (0, isr0, FALLING); 
      instance0_ = this;
      break;
    
    case 1: 
      attachInterrupt (1, isr1, FALLING); 
      instance1_ = this;
    break;
    }  
  }  // end of Foo::begin 
  
// constructor
Foo::Foo (const byte whichISR) : whichISR_ (whichISR) 
    {
    counter_ = 0;
    }

// ISR glue routines
void Foo::isr0 ()
  {
  instance0_->handleInterrupt ();  
  }  // end of Foo::isr0

void Foo::isr1 ()
  {
  instance1_->handleInterrupt ();  
  }  // end of Foo::isr1
  
// for use by ISR glue routines
Foo * Foo::instance0_;
Foo * Foo::instance1_;

// class instance to handle an interrupt
void Foo::handleInterrupt ()
  {
  counter_++;
  // and whatever else
  }  // end of Foo::handleInterrupt

// instances of class
Foo firstFoo (0);
Foo secondFoo (1);

void setup()
  {
  firstFoo.begin (); 
  secondFoo.begin (); 
  }  // end of setup

void loop() { }
1 Like

Thank you so much!
The code compiles now.
And after some very intense hours of looking at it and thinking, I even understand how it works :wink:

I've integrated it into my project and still compiles, but my Arduino seems crashing at some point (but that's beyond my initial question).

1 Like