Skip to main content
Arduino

Return to Revisions

3 of 4
Updated question to reflect suggestions in answer.
Marcel
  • 181
  • 4
  • 11

Pass class's public function as an argument to external command

I am trying to write a library for encoders.

main.ino:

#include <./Encoders.h>
Encoders encoders();
void setup(){
 Serial.begin(9600);
}
void loop(){ 
 Serial.print("");
}

Encoders.h:

#ifndef Encoders_h
#define Encoders_h
#include "Arduino.h"
class Encoders{
 public:
 Encoders();
 void EncodersSetup();
 long RightCount;
 long LeftCount;
 void R_A_RISE();
 void R_A_FALL();
 void R_B_RISE();
 void R_B_FALL();
 void L_A_RISE();
 void L_A_FALL();
 void L_B_RISE();
 void L_B_FALL();
 private:
 short R_A_SIG, R_B_SIG, L_A_SIG, L_B_SIG;
};
#endif

Encoders.cpp

#include "Arduino.h"
#include "Encoders.h"
long RightCount;
long LeftCount;
long R_A_SIG, R_B_SIG, L_A_SIG, L_B_SIG;
Encoders::Encoders(){
 attachInterrupt(0, R_A_RISE, RISING);
 attachInterrupt(1, R_B_RISE, RISING);
 attachInterrupt(2, L_A_RISE, RISING);
 attachInterrupt(3, L_B_RISE, RISING);
 R_A_RISE();
}
void Encoders::R_A_RISE(){
 detachInterrupt(0);
 R_A_SIG = 1;
 if(R_B_SIG == 0){
 RightCount++;
 }
 if(R_B_SIG == 1){
 RightCount--;
 }
 attachInterrupt(0, R_A_FALL, FALLING);
}
void Encoders::R_A_FALL(){
 detachInterrupt(0);
 R_A_SIG = 0;
 if(R_B_SIG == 1){
 RightCount++;
 } 
 if(R_B_SIG == 0){
 RightCount--;
 }
 attachInterrupt(0, R_A_RISE, RISING);
}
void Encoders::R_B_RISE(){
 detachInterrupt(1);
 R_B_SIG = 1;
 if(R_A_SIG == 1){
 RightCount++;
 }
 if(R_A_SIG == 0){
 RightCount--;
 }
 attachInterrupt(1, R_B_FALL, FALLING);
}
void Encoders::R_B_FALL(){
 detachInterrupt(1);
 R_B_SIG = 0;
 if(R_A_SIG == 0){
 RightCount++;
 }
 if(R_A_SIG == 1){
 RightCount--;
 } 
 attachInterrupt(1, R_B_RISE, RISING);
}
void Encoders::L_A_RISE(){
 detachInterrupt(2);
 L_A_SIG = 1;
 if(L_B_SIG == 0){
 LeftCount++;
 }
 if(L_B_SIG == 1){
 LeftCount--;
 }
 attachInterrupt(2, L_A_FALL, FALLING);
}
void Encoders::L_A_FALL(){
 detachInterrupt(2);
 L_A_SIG = 0;
 if(L_B_SIG == 1){
 LeftCount++;
 } 
 if(L_B_SIG == 0){
 LeftCount--;
 }
 attachInterrupt(2, L_A_RISE, RISING); 
}
void Encoders::L_B_RISE(){
 detachInterrupt(3);
 L_B_SIG = 1;
 if(L_A_SIG == 1){
 LeftCount++;
 }
 if(L_A_SIG == 0){
 LeftCount--;
 }
 attachInterrupt(3, L_B_FALL, FALLING);
}
void Encoders::L_B_FALL(){
 detachInterrupt(3);
 L_B_SIG = 0;
 if(L_A_SIG == 0){
 LeftCount++;
 }
 if(L_A_SIG == 1){
 LeftCount--;
 } 
 attachInterrupt(3, L_B_RISE, RISING);
}

When I try to compile this, I get errors like this:

C:/Users/marcel/Documents/dev/Arduino/encodeurs/Encoders.cpp:10:38: error: cannot convert 'Encoders::R_B_RISE' from type 'void (Encoders::)()' to type 'void (*)()'

I tried answers on other threads. Most said to make the functions passed to attachInterrupt() static. That threw different errors:

C:/Users/marcel/Documents/dev/Arduino/encodeurs/Encoders.cpp:16:33: error: cannot declare member function 'void Encoders::R_A_RISE()' to have static linkage [-fpermissive]

I also tried this:

attachInterrupt(0, &Encoders::R_A_RISE, this, RISING);

with no success.

The Arduino in question is a Mega but I doubt that matters.

#Edit: Per Nick Gammon's answer, I now have this.

MotorEncoderMaster.ino

#include </home/marcel/dev/Arduino/encoders/MotorEncoderMaster/Encoders.h>
Encoders * Encoders::instances [2] = { NULL, NULL };
// instances of our class
Encoders right;
Encoders left;
void setup (){
 right.begin (2); // pin D2
 left.begin (3); // pin D3
} // end of setup
void loop (){
 // whatever
} // end of loop

Encoders.h:

class Encoders{
 volatile bool switchChanged;
 static Encoders * instances [2];
 static void switchPressedExt0(){
 if(Encoders::instances [0] != NULL){
 Encoders::instances [0]->switchPressed();
 }
 }
 static void switchPressedExt1 (){
 if (Encoders::instances [1] != NULL){
 Encoders::instances [1]->switchPressed();
 }
 }
 public:
 void begin (const int whichPin){
 pinMode (whichPin, INPUT_PULLUP);
 switch (whichPin){
 case 2:
 attachInterrupt(0, switchPressedExt0, CHANGE);
 instances [0] = this;
 break;
 case 3:
 attachInterrupt(1, switchPressedExt1, CHANGE);
 instances [1] = this;
 break;
 }
 }
 void switchPressed(){
 switchChanged = true;
 }
};

When I try to compile this, I get :

In file included from MotorEncoderMaster.ino:1:0:
/home/marcel/dev/Arduino/encoders/Encoders.h: In static member function ‘static void Encoders::switchPressedExt0()’:
/home/marcel/dev/Arduino/encoders/Encoders.h:7:34: error: ‘NULL’ was not declared in this scope
 if(Encoders::instances [0] != NULL){
 ^
/home/marcel/dev/Arduino/encoders/Encoders.h: In static member function ‘static void Encoders::switchPressedExt1()’:
/home/marcel/dev/Arduino/encoders/Encoders.h:13:35: error: ‘NULL’ was not declared in this scope
 if (Encoders::instances [1] != NULL){
 ^
/home/marcel/dev/Arduino/encoders/Encoders.h: In member function ‘void Encoders::begin(int)’:
/home/marcel/dev/Arduino/encoders/Encoders.h:21:24: error: ‘INPUT_PULLUP’ was not declared in this scope
 pinMode (whichPin, INPUT_PULLUP);
 ^
/home/marcel/dev/Arduino/encoders/Encoders.h:21:36: error: ‘pinMode’ was not declared in this scope
 pinMode (whichPin, INPUT_PULLUP);
 ^
/home/marcel/dev/Arduino/encoders/Encoders.h:24:45: error: ‘CHANGE’ was not declared in this scope
 attachInterrupt(0, switchPressedExt0, CHANGE);
 ^
/home/marcel/dev/Arduino/encoders/Encoders.h:24:51: error: ‘attachInterrupt’ was not declared in this scope
 attachInterrupt(0, switchPressedExt0, CHANGE);
 ^
Marcel
  • 181
  • 4
  • 11
lang-cpp

AltStyle によって変換されたページ (->オリジナル) /