I\'m writing a simple library for an ultrasonic distance sensor and thought i\'d try using interrupts.
However i can\'t set my functions in the attachCallback<
Arduino interrupt handlers can only be functions. You are trying make method of an object an interrupt handler. Hence the compiler complains.
To be more precise about it, object methods are like functions, but it is as if they take a "hidden" parameter, which specifies the object instance. Therefore, they actually have different type signatures from plain functions. This disallows one to pass a method pointer when what a function is looking for is a plain function pointer.
The solution is to move your echoHigh()
and echoLow()
out of the HCSR04Interrupt
class, and make them plain functions.
As I stumbled upon this question and it hasn't had an accepted answer, I write what I found, which worked for me:
The interrupt has to be called by a global wrapper. This wrapper needs to call a handleInterupt
function of the class. Therefore it has to know the class. This can be done by storing it in a global variable. If multiple instances of the class should be used, multiple such global variables have to be used. But as the interrupt pins are just a few you can write a global variable and function for every pin:
MyClass theInstance_pin3 = NULL;
MyClass theInstance_pin7 = NULL;
// Somewhere, fill in an initialized copy of MyClass,
// and set theInstance_pin3 or theInstance_pin7 to it
void ISR_3()
{
if (theInstance_pin3)
theInstance_pin3->handleInterrupt();
}
void ISR_7()
{
if (theInstance_pin7)
theInstance_pin7->handleInterrupt();
}
as a reference see: http://forum.arduino.cc/index.php?topic=41713.0 or http://forum.arduino.cc/index.php?topic=160101.0
So the compiler (not the IDE) tells you exactly what's wrong:
argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()
So, while attachInterrupt()
takes a function pointer of type void (*)()
, you're trying to pass it a non-static member function, which you can't. You can try making the member function static
and casting:
static void echoHigh();
// ...
attachInterrupt(_echo_pin - 2, reinterpret_cast<void (*)()>(&echoHigh), RISING);
I got around this by making a singleton base class which represents the hardware as a whole (which kinda makes sense in this situation anyway).
Any function pointers can then be passed to the sub-component class, and handled by the singleton, whose member variables and methods are all static.
Example headers (untested):
// Sub-component
class LampButton {
public:
LampButton(int pin, void(*pushHandler)());
}
// Sub-component
class LampLed {
public:
LampLed(int pin);
void toggle();
}
// Singleton represents the hardware in it's entirety
class Lamp {
public:
// Call this instead of a constructor
static void initialize(int buttonPin, int ledPin);
// Function implemented inline for clarity - don't do this
static void handleButtonPush() {
led.toggle();
}
private:
static LampButton button;
static LampLed led;
}