0

Hello i have a class and i would like to attach an interrupt inside the class and attach it to a function of the class.

class counter{
  public:

  counter(int pin){
    Ipin=pin;
  }
  void startCounting(){
    attachInterrupt(digitalPinToInterrupt(Ipin),this.addCount,CHANGE);
  }
  void stopCounting(){
    detachInterrupt(digitalPinToInterrupt(Ipin));
  }

  void addCount(){
    count++;
  }

  private:
  int Ipin;
  unsigned long count= 0;
};

Some what of the code above. There can be multiple intialization of this class. hopefully depending on the user uses a different pin.

There is a way arround this where the attaching of pin is done in the loop or setup and just calling a public function of the class. But to me that kinda doesn't fit the spirit of classes like a properly made library is done.

Im not very good at programming if you could teach me how it would be greatly appreciated.

  • I's not supported by attachInterrupt. You need some function that calls that desired method. – KIIV Mar 18 at 21:54
  • @KIIV so how do libraries with interrupts do it? – Jack Mar 18 at 22:05
  • By using some function that calls method on specific object. You can't use more callbacks for the same interrupt source anyway. – KIIV Mar 18 at 22:08
  • So if we go by what you have said and to lets say i were to create a library. I would have 2 fuunctions that does not belong to any class in the .h or .cpp that first function attaches the interrupt to the second function, and that second function calls a method of the class?? Is it possible to call a global function inside of a class? – Jack Mar 18 at 22:24
3

I have a post about this problem.

Basically you cannot attach a class function with attachInterrupt because of the hidden "this" pointer which needs to be supplied to a (non-static) class function, where "this" is the particular instance of the class. You can work around it like this:

class myClass
  {
  static volatile bool switchChanged;  // declare

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);
    }  // end of myClass::begin

  static void switchPressed ()
    {
    switchChanged = true;
    }  // end of myClass::switchPressed

  };  // end of class myClass

volatile bool myClass::switchChanged;  // define

myClass foo;  // make an instance of myClass

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

void loop ()
  {
  // whatever    
  }  // end of loop

But that isn't great because, as you observed, you are really downgrading the class to use a static boolean.


Another way of doing it is to write "glue" routines, like this:

class myClass
  {
  volatile bool switchChanged;

  static myClass * instances [2];

  static void switchPressedExt0 ()
    {
    if (myClass::instances [0] != NULL)
      myClass::instances [0]->switchPressed ();
    }  // end of myClass::switchPressedExt0

  static void switchPressedExt1 ()
    {
    if (myClass::instances [1] != NULL)
      myClass::instances [1]->switchPressed ();
    }  // end of myClass::switchPressedExt1


  public:

  void begin (const byte whichPin)
    {
    pinMode (whichPin, INPUT_PULLUP);
    switch (whichPin)
      {
      case 2: 
        attachInterrupt (0, switchPressedExt0, CHANGE);
        instances [0] = this;
        break;

      case 3: 
        attachInterrupt (1, switchPressedExt1, CHANGE);
        instances [1] = this;
        break;

      } // end of switch
    }  // end of myClass::begin

  void switchPressed ()
    {
    switchChanged = true; 
    }

  };  // end of class myClass

myClass * myClass::instances [2] = { NULL, NULL };

// instances of our class  
myClass foo; 
myClass bar;

void setup ()
  {
  foo.begin (2);   // pin D2
  bar.begin (3);   // pin D3
  }  // end of setup

void loop ()
  {
  // whatever    
  }  // end of loop

That's still not a great solution, but it might give you some ideas.


Your fundamental problem is that classes, by their nature, can be instantiated many times, however you only have a small, fixed, number of interrupts on the microprocessor.

| improve this answer | |
  • Thank you for the great reference, the "glue" solution would work for me because i am using a custom built board and there is a fix number of pins to interrupt. I just want to take the trouble off the user when using the library, when begin is called on my main class all the interrupts should be ready to go. Atleast i wont have to make a function on all interrupt pins (60+ pins = 60+ functions on due). Thank you again for the answer. – Jack Mar 19 at 10:39
  • I can understand it would cause trouble where the number of instantiation would exceed the number of interrupts the processor. Although that can be fixed by adding protection macros that throws an error if the number of instantiation exceed the number of interrupts,but that would be a lot of macros for each board you want your class to work. – Jack Mar 19 at 10:50

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.