ear9mrn
November 28, 2021, 9:02pm
1
I have seen a couple of posts about this and I think I have a method that seems to work.
unsigned long previousMillis = 0;
const long interval = 200;
int pin12 = 12;
int pin14 = 14;
void *arg12 = &pin12;
void *arg14 = &pin14;
void setup() {
Serial.begin(115200);
pinMode(pin12, INPUT_PULLUP);
pinMode(pin14, INPUT_PULLUP);
attachInterruptArg(digitalPinToInterrupt(pin12), ISR, arg12, CHANGE);
attachInterruptArg(digitalPinToInterrupt(pin14), ISR, arg14, CHANGE);
}
ICACHE_RAM_ATTR void ISR(void * myarg){
if (millis() - previousMillis >= interval) {
printf("interrupt: = %d\n", *( (int*)myarg) );
reviousMillis = millis();
}
}
void loop()
{
}
Interested to hear feedback on this approach. Am I doing something stupid?
Thanks.
gfvalvo
November 28, 2021, 9:50pm
3
anon57585045:
Links please?
No link, but see "...\esp8266\3.0.2\cores\esp8266\Arduino.h":
void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode);
So, attachInterruptArg() takes an argument of type 'void *' that will be passed to the ISR when it's called.
ear9mrn
November 28, 2021, 10:10pm
6
gfvalvo
November 28, 2021, 10:29pm
7
A much more interesting application of attachInterruptArg() is the ability to call a class instance function (somewhat indirectly) as an ISR:
class MyClass {
public:
MyClass(uint8_t p) : pin(p) {}
void begin() {
pinMode(pin, INPUT_PULLUP);
attachInterruptArg(digitalPinToInterrupt(pin), classIsr, this, CHANGE);
}
private:
ICACHE_RAM_ATTR static void classIsr(void *p) {
MyClass *ptr = (MyClass*) p;
ptr->instanceIsr();
}
ICACHE_RAM_ATTR void instanceIsr() {
}
uint8_t pin;
};
ear9mrn
November 29, 2021, 11:03am
8
Thanks. This look potentially much more useful. I am reaching the limit of my knowledge here. How do I get the value of the pin in the instanceIsr method?
I tried with;
ICACHE_RAM_ATTR static void classIsr(void *p) {
MyClass *ptr = (MyClass*) p;
ptr->instanceIsr(ptr->pin);
}
Followed by:
void ICACHE_RAM_ATTR instanceIsr(uint8_t thepin) {
Serial.println("testing: " + String(thepin) + "\n" );
}
But clearly that is wrong (compiler error)!.. any guidance would be gratefully appreciated.
Thanks.
gfvalvo
November 29, 2021, 3:45pm
9
Once you're inside an instance function -- in this case instanceIsr() -- you have access to all instance variables -- in this case 'pin'. No need to pass anything around.
gfvalvo
November 30, 2021, 12:23am
10
I just realized there's an even slicker way to call instance function ISRs when using ESP8266 (or ESP32). That's by using FunctionalInterrupt.h. For example:
#include "FunctionalInterrupt.h"
class MyClass {
public:
MyClass(uint8_t p) : pin(p) {}
void begin() {
pinMode(pin, INPUT_PULLUP);
std::function<void(void)> stdFunct {std::bind(&MyClass::instanceIsr, this)};
attachInterrupt(digitalPinToInterrupt(pin), stdFunct, FALLING);
}
void poll() {
if (fired) {
fired = false;
Serial.printf("Interrupt Fired on Pin %d\n", pin);
}
}
private:
volatile bool fired = false;
IRAM_ATTR void instanceIsr() {
fired = true;
}
uint8_t pin;
};
MyClass objects[] = {0, 4, 13, 12};
void setup() {
Serial.begin(115200);
delay(1000);
for (MyClass &obj : objects) {
obj.begin();
}
}
void loop() {
for (MyClass &obj : objects) {
obj.poll();
}
}
ear9mrn
December 3, 2021, 9:52am
11
Slight variation with an array....
unsigned long previousMillis = 0;
const long interval = 200;
uint8_t pin12[] = {12,99};
uint8_t pin14[] = {14,66};
void *arg12 = &pin12;
void *arg14 = &pin14;
void setup() {
Serial.begin(115200);
pinMode(pin12[0], INPUT_PULLUP);
pinMode(pin14[0], INPUT_PULLUP);
attachInterruptArg(digitalPinToInterrupt(pin12[0]), ISR, arg12, CHANGE);
attachInterruptArg(digitalPinToInterrupt(pin14[0]), ISR, arg14, CHANGE);
}
ICACHE_RAM_ATTR void ISR(void * myarg){
if (millis() - previousMillis >= interval) {
uint8_t thepin = ((uint8_t *)myarg)[0];
uint8_t val = ((uint8_t *)myarg)[1];
printf("interrupt: = %d, Value: %d\n", thepin, val );
previousMillis = millis();
}
}
void loop()
{
}
system
Closed
June 1, 2022, 9:53am
12
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.