I'm writing a library to support multiple callbacks using MsTimer2 to provide the internal heartbeat. I've got it working but have hit an odd difference in the timing of the heartbeat. A stripped-down version of the code with the bare essentials is here:
#include "MsTimer2.h"
const unsigned long DEFAULTHEARTBEAT = 1000; // mS heartbeat from MsTimer2
class WAKEUP {
public:
WAKEUP();
void timerISR();
void setHeartbeat(unsigned long heartbeat);
void wakeMe( void (*f)());
void (*_sleeper)();
};
WAKEUP::WAKEUP() {
setHeartbeat(DEFAULTHEARTBEAT); // Exhibit A: establish heartbeat in constructor
}
void WAKEUP::setHeartbeat(unsigned long heartbeat) {
MsTimer2::set(heartbeat, timerISRWrapper); // Set timer and function to call when done
MsTimer2::start(); // Start the timer
}
void WAKEUP::wakeMe( void (*f)()) {
_sleeper = f; // Store the function pointer to the sleeper
}
void WAKEUP::timerISR() {
_sleeper(); // Time's up; wake up the sleeper
}
WAKEUP wakeup; // Instantiate one instance
void timerISRWrapper() { // Use non-member function as stable function reference for MsTimer2::set call
wakeup.timerISR(); // See http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
}
void setup(void)
{
Serial.begin(9600);
wakeup.wakeMe(sleeper0); // Register function to be called on heartbeat
// wakeup.setHeartbeat(DEFAULTHEARTBEAT); // Exhibit B: establish heartbeat with call from main code. Commented out here
}
void sleeper0() {
Serial.println(millis());
}
void loop() {
}
This should result in a heartbeat of DEFAULTHEARTBEAT (1000mS) being set. However, when called from the class constructor (Exhibit A) the millis() readout from sleeper0 is every 2 seconds, not every 1 second.
If I then uncomment the heartbeat call at Exhibit B then the readout from sleeper0 is every 1 second, as intended.
On the face of it I'm calling the same member function (setHeartbeat) with the same value (verified with debug code, removed from the above), the only difference being what's called the function. I'm sure there's something I'm missing, but I can't see it.
Can anyone spot what I'm doing wrong?