Interrupt in a Libray

I am attempting to set up an interrupt within a class. The class is a library for an HC SR04 sonic distance measurer. An instance of the class will take a trigger port and an interrupt port. When the trigger goes HIGH you wait for an interrupt on the input port. The time between the two events is the echo time and you do the math to get the distance. I am setting up the class to house this logic and am having difficulty getting the thing to compile.

Header:
#ifndef HCSR04_H
#define HCSR04_H

#include “spark_wiring.h”

class HCSR04 {

public:

HCSR04(uint16_t pinTrigger, uint16_t pinEcho);

void echoEvent();

private:

HCSR04();


uint16_t pinTrigger;
uint16_t pinEcho;

};

#endif

CPP:
#include “spark_wiring_hcsr04.h”

HCSR04::HCSR04()
{
this->pinTrigger = 0;
this->pinEcho = 0;
}

HCSR04::HCSR04(uint16_t pinTrigger, uint16_t pinEcho)
{
this->pinTrigger = pinTrigger;
this->pinEcho = pinEcho;

pinMode(pinTrigger, OUTPUT);
digitalWrite(pinTrigger, LOW);

pinMode(pinEcho, INPUT);
attachInterrupt(pinEcho, echoEvent, RISING);

}

void HCSR04::echoEvent()
{

}

I keep getting this error when verifying:

spark_wiring_hcsr04.cpp: In constructor ‘HCSR04::HCSR04(uint16_t, uint16_t)’:
spark_wiring_hcsr04.cpp:18:31: error: invalid use of member function (did you forget the ‘()’ ?)
make: *** [spark_wiring_hcsr04.o] Error 1

Can I set up an interrupt within a class or does it have to be in the main program?

You should be able to, be hardware initialization is not working from constructors at the moment.

Workaround: Create an ::init() method and call it from setup()

void HCSR04::init() {
  pinMode(pinTrigger, OUTPUT);
  digitalWrite(pinTrigger, LOW);

  pinMode(pinEcho, INPUT);
  attachInterrupt(pinEcho, echoEvent, RISING);
}

Tried to set it up in a method and in init()… no joy. I am also dusting off my C from a long time on the shelf and might be missing some nuance on what you have suggested.

spark_wiring_hcsr04.cpp: In member function 'void HCSR04::init()':
spark_wiring_hcsr04.cpp:32:47: error: cannot convert 'HCSR04::echoEvent' from type 'void (HCSR04::)()' to type 'voidFuncPtr {aka void (*)()}'
make: *** [spark_wiring_hcsr04.o] Error 1



#include "spark_wiring_hcsr04.h"

HCSR04::HCSR04() 
{
    this->pinTrigger = 0;
    this->pinEcho = 0;
}

HCSR04::HCSR04(uint16_t pinTrigger, uint16_t pinEcho)
{
    this->pinTrigger = pinTrigger;
    this->pinEcho = pinEcho;
    
    //pinMode(pinTrigger, OUTPUT);
    //digitalWrite(pinTrigger, LOW);
    
    //pinMode(pinEcho, INPUT);
}

void HCSR04::echoEvent()
{
        

}

void HCSR04::init() 
{
    pinMode(pinTrigger, OUTPUT);
    digitalWrite(pinTrigger, LOW);

    pinMode(pinEcho, INPUT);
    attachInterrupt(pinEcho, echoEvent, RISING);
}

double HCSR04::ping()
{
    //attachInterrupt(pinEcho, echoEvent, RISING);
    
    return 0.0;
}

Ok, apparently not… the attachInterrupt() routine needs a specific type of function pointer. This works, but obviously is not super pretty like if it was all wrapped up in a Class. I’m sure there’s a way to do it… just not thinking of it right now.

#include <application.h>

/* ===== PROTOTYPES ===== */

void HCSR04echoEvent();

/* ===== HCSR04.h ===== */

class HCSR04 {
  public:
    HCSR04();
    HCSR04(uint16_t pinTrigger, uint16_t pinEcho);
    void echoEvent();
    void init();
    double ping();
  private:
    uint16_t _pinTrigger;
    uint16_t _pinEcho;
};

/* ===== HCSR04.cpp ===== */

HCSR04::HCSR04() 
{
  _pinTrigger = 0;
  _pinEcho = 0;
}

HCSR04::HCSR04(uint16_t pinTrigger, uint16_t pinEcho)
{
  _pinTrigger = pinTrigger;
  _pinEcho = pinEcho;
}

void HCSR04::init() {
  pinMode(_pinTrigger, OUTPUT);
  digitalWrite(_pinTrigger, LOW);

  pinMode(_pinEcho, INPUT);
  attachInterrupt(_pinEcho, HCSR04echoEvent, RISING);
}

double HCSR04::ping()
{
  return 0.0;
}

/* ===== ISR ===== */

void HCSR04echoEvent()
{

}

/* ===== application.cpp ===== */

HCSR04 myPing(D2, D3);

void setup() {
  myPing.init();
}

void loop() {

}

Thanks for looking at it… going to try a few more things… is this considered a bug or feature yet to be implemented???

Curious.

Chris

Well your initial problem (referencing the method from a Class in the attachInterrupt() ) is probably a feature request.

The other thing I was originally thinking you had a problem with was things like pinMode() and digitalWrite() not working in Class constructors. I guess that would have been your next problem. I would call this a bug.

cc: @Dave

Thanks! We’ve started talking about how best to accommodate initializing hardware before setup, we’ll let you know when we have a good path for fixing this.

Thanks!
David

1 Like

Fixed in commit: Fixed in commit: https://github.com/spark/core-firmware/commit/6e1a7d726cfb8c29b9d9a8660c1249c5a1aac5cb

1 Like

satishgn, this is a big one! Can’t wait to test it. :slight_smile: