0

I'm having trouble adding attachInterrupt in a library that I am creating. I researched a lot, and I noticed that this is a common mistake, but do not quite understand the answers I found.

The error in question is this:

sketch_nov04a.ino: In function 'void setup()':
sketch_nov04a:10: error: argument of type 'void (Teste::)()' does not match 'void (*)()'

My library is as follows:

Teste.h

#ifndef TESTE_H
#define TESTE_H
#include <Arduino.h>

class Teste
{
public:
    volatile long lastWindIRQ;
    volatile byte windClicks;

  void wspeedIRQ();
};
#endif

Teste.cpp

#include "Teste.h"

void Teste::wspeedIRQ()
{
  if (millis() - this.lastWindIRQ > 10)
  {
    this.lastWindIRQ = millis();
    this.windClicks++;
  }
}

my implementation

#include <Teste.h>

Teste teste;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  attachInterrupt(0, teste.wspeedIRQ, FALLING);
}

void loop()
{
  Serial.println(teste.windClicks);
  delay(3000);
}

EDIT: Updated the error and corrected the problem cited by Ignacio

4

The problem is that wspeedIRQ() is a member function (i.e. it's part of the Teste class), but attachInterrupt() expects a non-member function (i.e. a function which is static and/or not part of a class at all).

This is a very important distinction in C++ because it affects how the compiler calls the function behind-the-scenes. There is unfortunately no way to use a member function directly with attachInterrupt().

Various workarounds are possible though. The simplest is to write a wrapper function which calls the member function. For example:

Teste teste;

// This is a non-member function...
void isr()
{
    // ...which calls the member function:
    teste.wspeedIRQ();
}

void setup()
{
    //...

    // Setup interrupt to use a non-member function
    attachInterrupt(0, isr, FALLING);
}

As a side note, your implementation of wspeedIRQ() won't compile at the moment anyway. The reason is that this. is invalid. It's a pointer so the correct syntax is this->.

(In practice, you usually don't need to use this to access member data. C++ figures it out automatically, unless there's a naming conflict.)

-1

Normally you should use digitalPinToInterrupt(pin) to translate the actual digital pin to the specific interrupt number not the pin switch comparison attachInturrupt( , , )that is limited to pin 2,3 on an arduino uno ...or if you spend more money well... here's a list.

Board                              Digital Pins Usable For Interrupts
Uno,    Nano, Mini, other 328-based 2, 3
Mega,   Mega2560, MegaADK           2, 3, 18, 19, 20, 21
Micro, Leonardo, other 32u4-based   0, 1, 2, 3, 7
Zero                                all digital pins, except 4
MKR1000 Rev.1                       0, 1, 4, 5, 6, 7, 8, 9, A1, A2
Due                                 all digital pins
                                    all digital pins (Only pins 2, 5, 7, 8, 
                                    10,  11, 12, 13 work with CHANGE

delay() won't work b/c values won't return from millis() (don't ask why) https://www.arduino.cc/en/Reference/AttachInterrupt explains how to use inturrupts like let me recite the beggining

Interrupts are useful for making things happen automatically in microcontroller programs, and can help solve timing problems. Good tasks for using an interrupt may include reading a rotary encoder, or monitoring user input.... blah blah

what pete didn't mention is what Interrupt Service Routines were... and how these special functions have unique limitations other functions like in c++ do not.... from c-strings to structs to overloading to f-structs to t-templates. ISR's are as short as possible and should not return anything! if your cheap and don't want to spend more than $5 for a arduino you can use sketch to use multiple isr's you can set them up as priority

but your non member functions should be volatile and global... and millis() relies on interrupts to count, so it will never increment inside an ISR. Since delay() requires interrupts to work, it will not work if called inside an ISR. micros() works initially, but will start behaving erratically after 1-2 ms. delayMicroseconds() does not use any counter, so it will work as normal. and .... global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.