Skip to content

Timer interrupts within classes #3465

Closed
@VishalDhayalan

Description

@VishalDhayalan

Hardware:

Board: DOIT ESP32 DEVKIT V1
Core Installation version: Arduino-ESP32 v1.04 / Espressif 32 v1.11.1 in Platform.io
IDE name: Arduino IDE / Platform.io
Flash Frequency: 80Mhz
PSRAM enabled: ?no? ?yes?
Upload Speed: 921600
Computer OS: Windows 10

Description:

I'm trying to use timer interrupts and alarms inside a class (in the class definition). The function to call is a method in the class. But when passing that into timerAttachInterrupt() I'm getting this error: argument of type "void (Motor::*)()" is incompatible with parameter of type "void (*)()" .

I've tried using <FunctionalInterrupt.h> by passing the method with std::bind(), like it's done in the functional interrupts example but that doesn't work either, giving the error: no suitable conversion function from "std::_Bind<std::_Mem_fn<void (Motor::*)()> (Motor *)>" to "void (*)()" exists .

How can timer interrupts be done within classes? I can't make the timer ISR method static as I want it to be object dependant to process the attribute values for the particular object.

Sketch: (leave the backquotes for code formatting)

//Change the code below by your sketch
#include <Arduino.h>
#include <FunctionalInterrupt.h>

class Motor {
  private:
    int pwm_ch, IN1, IN2;
    float _PPR, reduction_ratio;
    volatile unsigned long enc_pulse;
    hw_timer_t * RPM_timer = NULL;

    void IRAM_ATTR encoder_ISR() {
      enc_pulse++;
    }

    void IRAM_ATTR calc_RPM() {
      // RPM calculation code
    }

  public:
    Motor(int pwm_channel, int pwm_pin, int IN1_pin, int IN2_pin, int enc_pin, float PPR, float ratio) {
      pwm_ch = pwm_channel;
      IN1 = IN1_pin;
      IN2 = IN2_pin;
      _PPR = PPR;
      reduction_ratio = ratio;
      enc_pulse = 0;

      ledcSetup(pwm_ch, 5000, 8);
      ledcAttachPin(pwm_pin, pwm_ch);
      pinMode(IN1, OUTPUT);
      pinMode(IN2, OUTPUT);
      coast();

      pinMode(enc_pin, INPUT);
      attachInterrupt(digitalPinToInterrupt(enc_pin), std::bind(&Motor::encoder_ISR, this), FALLING);
      RPM_timer = timerBegin(0, 80, true);
      timerAttachInterrupt(RPM_timer, std::bind(&Motor::calc_RPM, this), true);   // THIS DOESN'T WORK
      timerAlarmWrite(RPM_timer, 1000000, true);
      timerAlarmEnable(RPM_timer);
    }
    
    void forward(int pwm_speed) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      ledcWrite(pwm_ch, pwm_speed);
    }

    void reverse(int pwm_speed) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      ledcWrite(pwm_ch, pwm_speed);
    }

    void coast() {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      ledcWrite(pwm_ch, 0);
    }
};

Motor drive_R = Motor(0, 23, 18, 19, 35, 11, 34.02);
Motor drive_L = Motor(1, 5, 16, 17, 34, 11, 34.02);

void setup() {
   Serial.begin(115200);
}

void loop() {
   // Some project specific code
}

Debug Messages:

src\RC-CONTROL-WORKING.cpp: In constructor 'Motor::Motor(int, int, int, int, int, float, float)':
src\RC-CONTROL-WORKING.cpp:88:78: error: cannot convert 'std::_Bind_helper<false, void (Motor::*)(), Motor*>::type {aka std::_Bind<std::_Mem_fn<void (Motor::*)()>(Motor*)>}' to 'void (*)()' for argument '2' to 'void timerAttachInterrupt(hw_timer_t*, void (*)(), bool)'
       timerAttachInterrupt(RPM_timer, std::bind(&Motor::calc_RPM, this), true);
                                                                              ^

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: StaleIssue is stale stage (outdated/stuck)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions