Interrupt inside a class

Hi,

May be you can help me. I'm looking for use a interrupt with a function inside a class, but the attachInterrupt instruction is inside of the same class.

Can you help me? I paste the class.h and class.cpp

The error code is:

Encoder.cpp:13:43: error: argument of type ‘void (RotaryEncoder::)()’ does not match ‘void (*)()’

#include "Encoder.h"

RotaryEncoder::RotaryEncoder (uint8_t PinA, uint8_t PinB) 
{
  encoderPin1 = PinA;
  encoderPin2 = PinB;
  
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, UpdateEncoder, CHANGE); 
  attachInterrupt(1, UpdateEncoder, CHANGE);
}

void RotaryEncoder::UpdateEncoder (void) {
  uint8_t encoded = (digitalRead(encoderPin1) << 1) | digitalRead(encoderPin2); //converting the 2 pin value to single number
  uint8_t sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) Variable ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) Variable --;

  lastEncoded = encoded; //store this value for next time
}
#ifndef Encoder_H
#define Encoder_H

#include "Arduino.h"

class RotaryEncoder
{
public:
  RotaryEncoder(uint8_t PinA, uint8_t PinB);
  
  volatile uint8_t* Variable;
private:
  
  volatile uint8_t lastEncoded;

  uint8_t encoderPin1;
  uint8_t encoderPin2;
 
  
  void UpdateEncoder (void);
};

#endif

Moderator edit: Smiley eliminated.

I'm not sure of the way around this but (i suspect) your problem is this that's the extra parameter added to a C++ method when its translated to a c function.

http://www.learncpp.com/cpp-tutorial/87-the-hidden-this-pointer/

The examples not completely correct as it omits name mangling.

Mark

Yes, I have been tried the this->UpdateEncoder instead of UpdateEncoder only, but the error is the same...

The usual way around it is to have a function outside your class which then calls the function inside the class. The interrupt is then bound to that outer function.

eg:

void _MyClass::doSomething() {
  // blah blah blah
}

_MyClass MyClass;

void isr() {
  MyClass.doSomething();
}

attachInterrupt(0, isr, FALLING);

The C++ translator (C++ to C) adds an extra parameter to your method it's called "this".

Mark

You can't do this directly. You are trying to pass a "pointer to a member function" to attachInterrupt(), which takes a "pointer to a function" as an argument. Yes, there is a difference.
As majenko pointed out, you can use an external function, or, I would prefer a static function to solve this issue.

Header:

class RotaryEncoder
{
public:
    RotaryEncoder(uint8_t PinA, uint8_t PinB);
    void updateEncoder();

private:
    static RotaryEncoder* sEncoder;
    static void updateEncoderISR();
};

Implementation:

RotaryEncoder* RotaryEncoder::sEncoder = 0;

RotaryEncoder::RotaryEncoder(uint8_t PinA, uint8_t PinB)
{
    ...
    sEncoder = this;
    attachInterrupt(0, RotaryEncoder::updateEncoderISR, CHANGE);
    attachInterrupt(1, RotaryEncoder::updateEncoderISR, CHANGE);
}

void RotaryEncoder::updateEncoderISR()
{
    if (sEncoder != 0)
        sEncoder->updateEncoder();
}
1 Like