Прерывание в классе, помогите разобраться!

Maxim Z.
Offline
Зарегистрирован: 12.01.2016

Всем привет.

Создаю класс, в котовом запускается прерывание и оно же обрабатывается:

class FlowSensor
{
byte sensorInterrupt;

volatile byte pulseCount = 0;  

unsigned int totalPulses = 0;

unsigned long oldTime = 0;

  public:
  FlowSensor(byte interrupt, byte pin)
  {
    sensorInterrupt = interrupt;
    
    pinMode(pin, INPUT_PULLUP);

    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }

  void Calculate()
  {
    if((millis() - oldTime) > 1000) 
    { 
      detachInterrupt(sensorInterrupt);

      oldTime = millis();

      totalPulses = totalPulses + pulseCount;
        
      Serial.print("  Total Pulses: ");
      Serial.println(totalPulses);

      pulseCount = 0;
    
      attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
    }
  }

  void pulseCounter()
  {
    pulseCount++;
  }

};

FlowSensor FlowSensor1(0, 2);

Помогите разобраться, как нужно правильно сделать?

Так вот при компиляции выскакивает ошибка:

In member function 'void FlowSensor::Calculate()':
36: error: cannot convert 'FlowSensor::pulseCounter' from type 'void (FlowSensor::)()' to type 'void (*)()'
cannot convert 'FlowSensor::pulseCounter' from type 'void (FlowSensor::)()' to type 'void (*)()'

Если переношу процедуру pulseCounter() за пределы класса, то все компилируется, но тогда теряется смысл от класса.

Что нужно сделать, чтобы все заработало в классе?

Datak
Offline
Зарегистрирован: 09.10.2014

Вот <тут> посмотрите - по-моему, как раз про это.

Maxim Z.
Offline
Зарегистрирован: 12.01.2016

Спасибо.

Похожа ситуация, да, но немного иная все же.

Когда указал:

static void pulseCounter()
	  {
	    pulseCount++;
	  }

полезли ошибки, как и у того человека, на саму переменную volatile byte pulseCount

Вот ошибки:

 In static member function 'static void FlowSensor::pulseCounter()':
 error: invalid use of member 'FlowSensor::pulseCount' in static member function
 error: from this location
 invalid use of member 'FlowSensor::pulseCount' in static member function

При этом, если вынести volatile byte pulseCount в основную программу, ошибки исчезают. Но опять же

то неприемлимо.

А как к ней можно обратиться напрямую, я так и не понял(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Обработчик прерывания в классе нужно объявить как static.

В обработчике надо где-то брать указатель на экземпляр класса, который вызвал прерывание и обращаться к свойствам класса через этот указатель.

Да, это неудлбно, но "эизнь такова, какова она есть, и больше никакова".

Maxim Z.
Offline
Зарегистрирован: 12.01.2016

ЕвгенийП пишет:

В обработчике надо где-то брать указатель на экземпляр класса, который вызвал прерывание и обращаться к свойствам класса через этот указатель.

Да, это неудлбно, но "эизнь такова, какова она есть, и больше никакова".

Можно пример в виде кода. На словах то оно понятно, но что и как конкретно, совершенно не ясно(

Datak
Offline
Зарегистрирован: 09.10.2014

Maxim Z., так <вот> же он, пример - там и для случая когда создаётся только один экземпляр класса, и для случая с несколькими экземплярами.

Всё правильно, обработчик прерывания всегда вызывается "независимо", то есть к конкретному экземпляру класса он не привязан. Но из него можно вызвать любую классовую функцию (метод) уже для конкретного экземпляра - или всегда одного, или одного из нескольких, в зависимости от каких-то условий.

Maxim Z.
Offline
Зарегистрирован: 12.01.2016

Datak пишет:

Maxim Z., так <вот> же он, пример - там и для случая когда создаётся только один экземпляр класса, и для случая с несколькими экземплярами.

Всё правильно, обработчик прерывания всегда вызывается "независимо", то есть к конкретному экземпляру класса он не привязан. Но из него можно вызвать любую классовую функцию (метод) уже для конкретного экземпляра - или всегда одного, или одного из нескольких, в зависимости от каких-то условий.

Спасибо.

Сразу не разглядел, Синтаксис другой, а я Классы пока только осваиваю.

В общем для себя нашел 3 решения:

1. Переменную pulseCount делать глобальной в скетче

2. Функцию pulseCounter() так же выносить за пределы класса, в функции записать FlowSensor1.pulseCount++; , а саму pulseCount перенести в сектор public: в классе

3. Сделать по примеру Datak

Для себя выбрал 2ой вариант, так как проверку на запуск нужного прерывания сделал в классе, а процедуры приращения вынес в основной код скетча. Тем самым проверка осуществляется только в момент запуска прерывания, что на мой взгляд жрет меньше процессорных ресурсов.

Соответсвенно процедур с приращениями и проверок в классе столько, сколько создается экземпляров класса.

Как я понял, уложить все в класс нереально :(

 

P.S. Если кто знает способ - делитесь!