Reputation: 13
I'm using an encoder to track the position of a motor. The encoder sends pulses to a stm32 microcontroller, which calls an interrupt function on every rising edge. The ISR must be a global function, with no parameters, and return void.
void setup() {
attachInterrupt(pin_number, ISR_function, RISING);
}
void ISR_function() {
//do something
counter++;
}
I've created an encoder class, but its kind of ugly. Each encoder needs its own interrupt function, which increments a counter. I only have two encoders, so I wrote two ISR's above my class. In my class, the constructor takes an integer (either 1 or 2) and assigns ISR 1 or ISR 2 depending on this. Hence, I can only have two encoders, and additional encoders require more copy/pasting. Skeleton of my code:
volatile int counter1;
volatile int counter2;
void ISR1{
counter1++;
}
void ISR2{
counter2++;
}
class Encoder{
private:
int pin, num;
public:
Encoder(int pin, int num){
if(num == 1){ attachInterrupt(pin, ISR1, RISING); }
if(num == 2){ attachInterrupt(pin, ISR2, RISING); }
this-> pin = pin;
this-> num = num;
}
//functions that do things with counter
};
This isn't really a class in the abstract sense. How can I make a class that can handle an arbitrary number of encoders without writing a new ISR for each one? Is there a way to automatically create these functions from inside the class?
Upvotes: 1
Views: 1021
Reputation: 4732
If you have attachInterruptParam()
, use it like the following.
class Encoder {
protected:
static void staticOnInterrupt(void *this_) {
((Encoder *)this_)->onInterrupt();
}
void onInterrupt() {
...
}
public:
Encoder(int pin, int num) {
...
attachInterruptParam(pin, staticOnInterrupt, RISING, this);
...
}
...
};
If you don't, you probably have this C++ API.
typedef std::function<void(void)> callback_function_t;
void attachInterrupt(uint32_t pin, callback_function_t callback, uint32_t mode);
Then, use it like the following.
class Encoder {
protected:
void onInterrupt() {
...
}
public:
Encoder(int pin, int num) {
...
attachInterrupt(pin, std::bind(&Encoder::onInterrupt, this), RISING);
...
}
...
};
Upvotes: 1