2

At the moment I try to make a library which uses attachInterrupt(?,?,RISING) to read a sensor. The article of Nick Gammon on Calling an ISR from a class helped me a lot, but his "Glue routines" get pretty ugly with more than 30 potential Interrupt Pins on the ESP32, which all need their own static void. Has anyone got a more elegant idea how to do this "Gluing"?

  • 2
    Can you give more details about the kind of interrupts you want to handle? Type of board? In general, you will need one glue function per interrupt, not necessarily one per interrupt pin. This can make a difference if several pins share an interrupt, which is the case for the pin change interrupts on AVR. – Edgar Bonet May 30 at 12:32
  • An "Arduino" library, which is ESP32 specific, is a bit problematic. An ESP32 isn't an Arduino at all, strictly speaking. – DataFiddler May 30 at 13:14
  • How about going more low level? attachInterrupt() uses different interrupt types depending on the used pin. Most chips only have 1 or 2 external interrupt pins, so the rest is done via pin change interrupts, which cover a whole port, meaning 1 interrupt for a group of 8 pins. You could configure these interrupts directly via their control registers. Though I'm not sure, how this is organized on an ESP. – chrisl May 30 at 13:17
4

As a matter of efficiency, I would favor chrisl’s advise to use the platform's low-level interrupts if at all possible. This, however, comes at the cost of portability: you would need an implementation specialized for each platform you want to support. If you don't want to or cannot maintain all this platform-specific code, attachInterrupt() may be a reasonable option.

Then, you will absolutely need all those glue routines: since the interrupt system calls your handlers with no parameters, you will not be able to share handlers between interrupts, and you end up with as many handlers as interrupts you are going to use.

There is, however, an elegant way of creating all these specialized functions without writing them explicitly: you can ask the compiler to write them for you on the basis of a template you provide.

Below is a version of Nick Gammon's example code modified to use a template class. Note that you do not necessarily need a class to use templates: you could use template functions as interrupt handlers if that is appropriate for your use case.

template <uint8_t pin>
class myClass
{
    static volatile bool switchChanged;

public:
    static void begin()
    {
        pinMode(pin, INPUT_PULLUP);
        attachInterrupt(digitalPinToInterrupt(pin),
                        switchPressed, FALLING);
    }

    static void switchPressed()
    {
        switchChanged = true;
    }
};

template <uint8_t pin>
volatile bool myClass<pin>::switchChanged;

myClass<2> foo;
myClass<3> bar;

void setup()
{
    foo.begin();
    bar.begin();
}

void loop(){}

Note also that myClass<2> and myClass<3> are two different classes: you actually have a different class for each pin. This means that foo::switchChanged and bar::switchChanged are two different class members even though both are static. Since you should (in principle) have at most one instance of each pin-specific class, you can make everything within the class static.

The main caveat of this method is that the pin numbers have now to be compile-time constants. The great advantage is that you will have a class created for each interrupt that is actually used: no need for an array of 32 instances on an ESP32 if only a handful of interrupt pins are going to be actually used.

| improve this answer | |
  • Thanks a lot! It works brilliant for me. I mostly got what you did, but there's one question left: Why do we have to initialize our private volatile bool myClass<pin>::switchChanged; outside the class definition? – Adrian Immer Jun 1 at 12:00
  • It's not an initialization, it's a definition. Static class members are declared within the class definition but have to be defined outside of it. Otherwise you get the link-time error “undefined reference to myClass<(unsigned char)2>::switchChanged” (and the same for myClass<3>). – Edgar Bonet Jun 1 at 12:25

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.