IntervalTimer Function Pointer

Status
Not open for further replies.

Cosford

Well-known member
Hi Guys,

Just a C question really. I have a class which owns an IntervalTimer object, which will be used to call a function from that class. It looks something like this:

Header
Code:
class IRTrans
{
    private:
        IntervalTimer txTimer;
        void isr();

    public:
        void init();
};

extern IRTrans IRtx;

.cpp
Code:
void IRTrans::init()
{
    txTimer.begin(isr, 100);
}

void IRTrans::isr()
{
    //Whatever.
}

IRTrans IRtx;


Compiler gives me the following error message (using visual micro):
Code:
Compiling 'phaserp_test_sketch' for 'Teensy 3.1'
IRTrans.cpp:In member function 'void IRTrans::send(uint8_t, uint8_t, bool)'
IRTrans.cpp:114:50: error: no matching function for call to 'IntervalTimer::begin(<unresolved overloaded function type>, double)'
IRTrans.cpp:candidates are
WProgram.h:In file included from
Arduino.h:from
IRTrans.h:from
IRTrans.cpp:from
IntervalTimer.h:ISR, unsigned int)
IntervalTimer.h:ISR {aka void (*)()}'
IntervalTimer.h:ISR, int)
IntervalTimer.h:ISR {aka void (*)()}'
IntervalTimer.h:ISR, long unsigned int)
IntervalTimer.h:ISR {aka void (*)()}'
IntervalTimer.h:ISR, long int)
IntervalTimer.h:ISR {aka void (*)()}'
IntervalTimer.h:ISR, float)
IntervalTimer.h:ISR {aka void (*)()}'
IntervalTimer.h:ISR, double)
IntervalTimer.h:ISR {aka void (*)()}'
Error compiling

Any ideas how to resolve this? Function pointers are something that are relatively new to me.

-- Iestyn.
 
You need to include IntervalTimer.h in both your .cpp file and in the .ino/.pde file. In the .cpp file, you also need to include the .h file after IntervalTimer.h has been included. In terms of includes, your .ino/.pde file needs to include all library files that are used in the sketch, even if the library is not used in the module (the IDE scans the .ino/.pde file for the libraries to include when building the program).
 
Because the isr member function is declared within the class hierarchy, internally it has an extra argument to pass the class pointer, and therefore would not match signature for the begin function.

You would need to declare a stand alone function that then calls into the class. The isr function within the class needs to be a public function. Something like:

The header file:
Code:
class IRTrans
{
    private:
        IntervalTimer txTimer;

    public:
        void isr();
        void init();
};

extern IRTrans IRtx;

The C++ file:
Code:
static void isr_outer();

void IRTrans::init()
{
    txTimer.begin(isr_outer, 100);
}

void IRTrans::isr()
{
    //Whatever.
}

IRTrans IRtx;

static void isr_outer ()
{
  IRtx.isr ();
}
 
You need to include IntervalTimer.h in both your .cpp file and in the .ino/.pde file. In the .cpp file, you also need to include the .h file after IntervalTimer.h has been included. In terms of includes, your .ino/.pde file needs to include all library files that are used in the sketch, even if the library is not used in the module (the IDE scans the .ino/.pde file for the libraries to include when building the program).

Yes, apologies. It is there, was a result of me clipping out much of the class as it wasn't relevant to the issue.
EDIT: Scratch that, I misread your post. I couldn't find an IntervalTimer.h to include, but it seems to compile fine without including anything?

Thanks for your reply, will give it a shot and report back.

Update: It compiles fine now. Thanks for that.
 
Last edited:
Note, after I made my initial reply, I realized I answered the wrong question and went in and re-did the reply. Please re-read my new reply.
 
Yeah, I gathered that. The IntervalTimer stuff all seems to be compiling now. Thanks for that.
The issue I'm now having, is a linker error with the Wire library.

Code:
Compiling 'phaserp_test_sketch' for 'Teensy 3.1'
IRTrans.cpp.o:In function `IRTrans::setStrength(unsigned char)'
IRTrans.cpp:beginTransmission(int)'
IRTrans.cpp:endTransmission()'
IRTrans.cpp:undefined reference to `Wire'
collect2.exe*:error: ld returned 1 exit status
Error creating .elf

What I have is something like this:
->Sketch
-> IRTrans.h
-> IRTrans.cpp
-> PCA9536.h
-> PCA9536.cpp

Both of these libraries use Wire.h

IRTrans.h
Code:
#ifndef _IRTRANS_h
#define _IRTRANS_h

#include "Arduino.h"
#include <C:\Users\Admin\Desktop\arduino-1.6.3\libraries\Wire\Wire.h>

//****IRTrans class*****

#endif



IRTrans.cpp
Code:
#include <C:\Users\Admin\Desktop\arduino-1.6.3\libraries\Wire\Wire.h>
#include "IRTrans.h"

//*****IRTrans function definitions******



PCA9536.h
Code:
#ifndef _PCA9536_h
#define _PCA9536_h

#include "Arduino.h"
#include <C:\Users\Admin\Desktop\arduino-1.6.3\libraries\Wire\Wire.h>

//******PCA9536 class******



PCA9536.cpp
Code:
#include <C:\Users\Admin\Desktop\arduino-1.6.3\libraries\Wire\Wire.h>
#include "PCA9536.h"

//*******PCA9536 function definitions******


sketch.ino
Code:
#include <C:\Users\Admin\Desktop\arduino-1.6.3\libraries\Wire\Wire.h>

#include "IRTrans.h"
#include "PCA9536.h"

void setup()
{
//setup
}

void loop()
{
//loop
}


What have I messed up with regard to includes here? Interestingly, if I comment out the calls to Wire in IRTrans.cpp, it compiles fine despite the fact my include setup is identical for the PCA9536 class which compiles fine?

Thanks in advance.
 
As I said in my original reply (that I deleted), you need to include Wire.h in the .ino file, even though you do not use Wire in the .ino part. This is because the IDE scans the .ino file for libraries to include. You also should just use <Wire.h> and not a full pathname. Something like:

IRTrans.h:
Code:
#ifndef _IRTRANS_h
#define _IRTRANS_h

#include "Arduino.h"
#include <Wire.h>

//****IRTrans class*****

#endif

IRTrans.cpp:
Code:
#include <Wire.h>
#include "IRTrans.h"

//*****IRTrans function definitions******

PCA9536.h:
Code:
#ifndef _PCA9536_h
#define _PCA9536_h

#include "Arduino.h"
#include <Wire.h>

//******PCA9536 class******

PCA9536.cpp:

Code:
#ifndef _PCA9536_h
#define _PCA9536_h

#include "Arduino.h"
#include <Wire.h>

//******PCA9536 class******

sketch.ino:

Code:
#include <Wire.h>
#include "IRTrans.h"
#include "PCA9536.h"

void setup()
{
  //setup
}

void loop()
{
  //loop
}
 
Thanks again,

I've used the full path name due to, for some reason, Visual Micro pointing back to an older installation of Teensyduino which is still present on my computer. I have a few sketchbooks, so in order to ensure it's pointing to the most up-to-date version, I just used the full path name.

As you'll see in my above post, I did infact include Wire.h within the .ino file before the other includes; albeit using the full file path (although I didn't believe that should cause any issue?).

Regards

Update: Switched all my full path names for just <Wire.h> and it seems to be compiling, although Visual Micro/Studio is telling me that it's pointing back to the version included in my Teensyduino 1.20 installation. Quite possible that is reporting incorrectly though.

Update2: As I suspected, it seems to be including them from an older installation. Renaming that installation throws a bunch of errors:
Code:
Process: C:\Users\Admin\Desktop\teensyduino 1.20\hardware\tools\arm-none-eabi\bin\arm-none-eabi-g++ -c -g -Os -fno-exceptions -ffunction-sections -fdata-sections -w -mcpu=cortex-m4 -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=106 -felide-constructors -std=gnu++0x -I"C:\Users\Admin\Desktop\teensyduino 1.20\hardware\teensy\cores\teensy3" -I"C:\Users\Admin\Desktop\teensyduino 1.20\libraries\Wire" -I"C:\Users\Admin\Desktop\teensyduino 1.20\libraries" -I"C:\Users\Admin\Desktop\teensyduino 1.20\hardware\teensy\libraries" -I"C:\Program Files (x86)\Visual Micro\Visual Micro for Arduino\Micro Platforms\default\debuggers" -I"C:\Users\Admin\Dropbox\Arduino Sketchbook\libraries" -o "C:\Users\Admin\AppData\Local\VMicro\Arduino\Builds\phaserp_test_sketch\teensy31\IRSig.cpp.o"  "C:\Users\Admin\AppData\Local\VMicro\Arduino\Builds\phaserp_test_sketch\teensy31\IRSig.cpp"  -DF_CPU=96000000 -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH -DVISUALMICRO_COMPILER_VER=1  -mthumb -nostdlib -D__MK20DX256__ -DTEENSYDUINO=120  -fno-rtti
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\Admin\Desktop\teensyduino 1.20\libraries\Wire'.

Any ideas on this? I set Visual Micro up with a teensy configuration, pointing to a fresh installation of Arduino 1.6.3 with Teensyduino 1.22, so a bit bemused why it's looking for a folder totally seperate.
 
Last edited:
I only use the Arduino IDE for Teensy's (and only use Linux), so I can't help you with Visual Studio. Perhaps you need to update the defaults in VS?
 
I imagine it's something along those lines.
Think what I'll do is sit down and clean up my development environment. Has become a bit of a mess as of late.

Thanks for all your help today.
 
I would call the isr function and IntervalTimer instance as static in your class if you only want one instance of the IntervalTimer?
 
Hi Duff,
I'll only ever be calling on the single instance of IntervalTimer in that class, although I may need to create other instances elsewhere. What benefit would declaring both as static bring?
 
if someone calls your class more than once then there would be mulitple instances of the intervalTimer. Its just how I use core componets in my libraries. Maybe something like this:

IRTrans.h
Code:
#include "Arduino.h"
class IRTrans
{
    private:
        static IntervalTimer txTimer;


    public:
        static void isr();
        void init();
};

IRTrans.cpp
Code:
#include "IRTrans.h"


IntervalTimer IRTrans::txTimer;


void IRTrans::init()
{
    txTimer.begin(isr, 100);
}


void IRTrans::isr()
{
    //Whatever.
}
 
I did infact include Wire.h within the .ino file before the other includes; albeit using the full file path (although I didn't believe that should cause any issue?).

Using the full path is indeed causing an issue, because you've used the wrong full path.

That's Arduino's copy of the Wire library, which does not have any code for Teensy 3.1. It just won't work. You need to use the copy Teensyduino installs, which happens automatically from Arduino when you #include "Wire.h" without any pathname.
 
Using the full path is indeed causing an issue, because you've used the wrong full path.

That's Arduino's copy of the Wire library, which does not have any code for Teensy 3.1. It just won't work. You need to use the copy Teensyduino installs, which happens automatically from Arduino when you #include "Wire.h" without any pathname.

Of course. Whoops.

Took the time to clean up my installations and update to Arduino 1.6.3, latest version of teensyduino and reinstall newest beta of Visual Micro and all is working much better now (and finally my intellisense in visual studio is back, huzzah!). Many thanks all.
 
I have the same problem still in some code.
Getting error:
teemi_clock.cpp:51: undefined reference to `tc'

teemi_clock.cpp:
#include "teemi_clock.h"
#include <Arduino.h>

static void isr_outer();

TeemiClock::TeemiClock(void)
{
this->state = CLOCK_IDLE;
this->tick_count = 0;

this->ppqn = 48;
this->bpm = 120;
}

int8_t TeemiClock::setBPM(uint16_t bpm)
{
if(bpm >= 1 && bpm <= 999)
{
this->bpm = bpm;
return 0;
}
return -1;
};

int8_t TeemiClock::setPPQN(uint16_t ppqn)
{
if(ppqn >= 12 && ppqn <= 384)
{
this->ppqn = ppqn;
}
return -1;
};

uint32_t TeemiClock::getTick(void)
{
return this->tick_count;
};

int16_t TeemiClock::getPPQN(void)
{
return this->ppqn;
};

bool TeemiClock::isRunning(void)
{
return(this->state == CLOCK_RUNNING ? 1 : 0);
};

static void isr_outer ()
{
tc.tick();
};

void TeemiClock::tick(void)
{
__disable_irq();
if(this->state == CLOCK_RUNNING)
tick_count++;
__enable_irq();
};

int8_t TeemiClock::start(void)
{
this->tick_count = 0;
internalClock.begin(isr_outer, (60 / (bpm * 24)) / (ppqn/24));
internalClock.priority(0); // We want most precise timing, so highest prio
this->state = CLOCK_RUNNING;
return -1;
};

int8_t TeemiClock::pause(void)
{
this->state = CLOCK_PAUSED;
return -1;
};

int8_t TeemiClock::stop(void)
{
internalClock.end();
this->tick_count = 0;
return -1;
};

teemi_clock.h:
#include <stdint.h>
#include <Arduino.h>

typedef enum {
CLOCK_IDLE = 0,
CLOCK_PAUSED,
CLOCK_RUNNING
} clock_state_t;

class TeemiClock
{
public:
TeemiClock();
int8_t setBPM(uint16_t bpm);
int8_t setPPQN(uint16_t ppqn);
int16_t getPPQN(void);
uint32_t getTick(void);
int8_t setTick(uint32_t);
bool isRunning(void);
int8_t start(void);
int8_t pause(void);
int8_t stop(void);

void tick();
uint32_t tick_count;

private:
int8_t state;

uint16_t ppqn;
uint16_t bpm;

IntervalTimer internalClock;
};

extern TeemiClock tc;
 
Where is an instance of tc defined?

You have an extern defined in the header file. And you have one reference to it in the header file. But I don't see anywhere that actually creates tc...
 
Where is an instance of tc defined?

You have an extern defined in the header file. And you have one reference to it in the header file. But I don't see anywhere that actually creates tc...

You're right. Declared a instance and seems all to work fine, as far as I can see. Thanks!
 
Status
Not open for further replies.
Back
Top