I am trying to attach a class function as an ISR callback but I am getting this error:
lib/classA/classA.cpp: In member function 'uint8_t MethodA::Init()':
lib/classA/classA.cpp:32:71: error: invalid use of non-static member function 'void MethodA::FlowCounter()'
attachInterrupt( digitalPinToInterrupt(PIN_B), FlowCounter, FALLING );
^
lib/classA/classA.cpp:12:16: note: declared here
void IRAM_ATTR MethodA::FlowCounter() {
^~~~~~~
*** [.pio\build\featheresp32\lib71a\classA\classA.cpp.o] Error 1
How do I correctly reference the FlowCounter
function in the attachInterrupt
call?
This is the main.cpp file:
#include <Arduino.h>
#include "classA.h"
MethodA myMethod( 5, 6 );
void setup() {
myMethod.Init();
}
void loop() {
}
This is the classA.h file:
#pragma once
#include <Arduino.h>
class MethodA {
public:
MethodA( uint8_t _PIN_A, uint8_t _PIN_B );
uint32_t stopCount;
static const uint32_t stepCount;
uint8_t Init();
void Update();
void StartCycle();
private:
volatile uint32_t flowCount;
uint8_t pumpDone;
void IRAM_ATTR FlowCounter();
uint8_t PIN_A;
uint8_t PIN_B;
};
And the classA.cpp file:
#include <Arduino.h>
#include "classA.h"
const uint32_t MethodA::stepCount = 10;
MethodA::MethodA( uint8_t _PIN_A, uint8_t _PIN_B ) {
PIN_A = _PIN_A;
PIN_B = _PIN_B;
}
void IRAM_ATTR MethodA::FlowCounter() {
flowCount++;
if ( flowCount >= stopCount ) {
digitalWrite( PIN_A, LOW );
pumpDone = true;
}
return;
}
uint8_t MethodA::Init() {
pinMode( PIN_A, OUTPUT );
digitalWrite( PIN_B, LOW );
pinMode( PIN_B, INPUT_PULLUP );
attachInterrupt( digitalPinToInterrupt(PIN_B), FlowCounter, FALLING );
return true;
}
void MethodA::Update() {
if ( pumpDone ) {
Serial.print( "Cycle complete.");
}
return;
}
void MethodA::StartCycle() {
stopCount = flowCount + stepCount;
digitalWrite( PIN_A, HIGH );
pumpDone = false;
return;
}
I tried making the ISR function static by static void IRAM_ATTR FlowCounter();
but that made the compiler scream about the variable inside the function. I tried referencing it by MethodA::FlowCounter
but that yielded the same error. I tried using a pointer &FlowCounter
and &Method::FlowCounter
to no avail. So I am missing something fundamental about cpp programming (I more familiar with the relative ease of Python).
From the IRAM_ATTR
I'm assuming you're working with ESP8266 (or ESP32). The Arduino ESP8266 core has an attachInterrupt()
overload that accepts a std::function
, which can be produced by a std::bind()
from an object and a member function. You are calling the wrong overload that is meant for just a function pointer to a static function.
See
So you just have to change this to use it:
#include <FunctionalInterrupt.h>
uint8_t MethodA::Init() {
pinMode( PIN_A, OUTPUT );
digitalWrite( PIN_B, LOW );
pinMode( PIN_B, INPUT_PULLUP );
attachInterrupt(
digitalPinToInterrupt(PIN_B),
std::bind(&MethodA::FlowCounter, this),
FALLING);
return true;
}
Edit: Added include for FunctionalInterrupt.h
.