Использование классов таймеров внутри классов

Я пытаюсь разработать класс для насоса, работающего на шаговом двигателе. Он должен быть простым, но работает не так, как я думал. Как только я перемещаю объект таймера в класс, код не компилируется. Я пробовал много вещей, но, похоже, ничего не работает правильно. Целью всего этого является заставить шаговый двигатель работать самостоятельно на основе вызовов объекта таймера.

насос.h

#include "TimerObject.h"`
#ifndef Pump_h
#define Pump_h

class Pump
{
  public:
     Pump(char pin_, char dir_);
    void pumpstep(void);
  private:
    char pin;
    char dir;
    TimerObject *pumptimer;
};

#endif

pump.cpp

Pump::Pump(char pin_, char dir_)
{
    pin = pin_;
    dir = dir_;
    pumptimer = new TimerObject(100, &this->pumpStep); //ПРОБЛЕМА ЗДЕСЬ

  pinMode(pin, OUTPUT);
  pinMode(dir, OUTPUT);
}

void Pump::pumpstep(void) {
     Serial.println("Stepping");
}

мой .ino просто создает класс, передавая необходимые параметры, но все привязывается, когда я пытаюсь скомпилировать из-за обратного вызова в конструкторе для таймера, по какой-то причине он не позволяет мне использовать адрес нестатического здесь, но я не могу сделать метод статическим, каждый метод pumpstep() должен быть отдельным в зависимости от того, какой насос работает. Я пробовал использовать &Pump::pumpstep, &(Pump::pumpstep) и многие другие указатели, но, похоже, не нашел того, который мне нужен.

вне этого класса таймер работал отлично. Я использовал эту строку ниже:

pumptimer = new TimerObject(100, &pumpStep);

Библиотеку таймера можно найти здесь: https://playground.arduino.cc/Code/ArduinoTimerObject

Будем очень благодарны за любую помощь.

, 👍0


1 ответ


Лучший ответ:

0

Прототип функции-члена полностью отличается от прототипа глобальной функции. Эти два понятия не являются взаимозаменяемыми.

Есть способы обойти эту проблему, например «перенаправить» обратный вызов через глобальную функцию, но они запутаны.

Однако в этой ситуации лучше просто отказаться от TimerObjects.h и сделать это вручную — это не так уж сложно:

#ifndef Pump_h
#define Pump_h

class Pump
{
  public:
     Pump(char pin_, char dir_);
     void pumpstep(void);
     uint32_t ts;
     void run()
  private:
    char pin;
    char dir;
};

#endif

Pump::Pump(char pin_, char dir_)
{
    pin = pin_;
    dir = dir_;
    ts = 0;
    pinMode(pin, OUTPUT);
    pinMode(dir, OUTPUT);
}

void Pump::pumpstep(void) {
     Serial.println("Stepping");
}

void Pump::run() {
    if (millis() - ts >= 100) {
        ts += 100;
        pumpStep();
    }
}

Затем в цикле вызов:

myPump.run();

Конечно, вы можете просто объединить run() и pumpstep() в одну функцию.

,