In the next step, you can use a pointer to a function that will be executed when the timer starts or when the timer lapses. First write a function that (for above example) toggles the led
/*
toggle the built-in led
*/
void toggleLedBuiltin()
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
Next modify the struct and add a function pointer; in the below, I added a pointer to a function that will be executed when the timer is started and a pointer to a function that will be executed when the timer has lapsed.
struct MYTIMER
{
uint32_t startTime; // when delay is started
uint32_t duration; // how long
bool isRunning; // flag indicating if timer is running
void (*startFunction)(); // function to execute when timing starts
void (*endFunction)(); // function to execute when timing ends
};
// function prototypes
void toggleLedBuiltin();
// declare two timers
MYTIMER myTimers[] =
{
{0, 2000, false, NULL, toggleLedBuiltin},
{0, 1200, false, NULL, NULL},
};
In above example, there is only a function that will be called when myTimer[0] lapses. myTimer[1] can be used as a millis() based 'delay'.
To be able to use toggleLedBuitin in the timer declaration, the compiler needs to know about it existence. I'm still using IDE 1.8.5 where the automatic prototyping by the IDE fails and hence I'v e added the prototype; you will need to add all prototypes for functions that are references in the struct.
Next you can modify the runTimer() function to execute the functions at start and end
/*
execute a 'timer'
In:
number of timer (index in myTimers array)
Returns:
true if timer is running, else false
*/
bool runTimer(uint8_t whichTimer)
{
if (whichTimer >= NUMELEMENTS(myTimers))
{
// inform user about mistake
Serial.println("Invalid timer index");
// hang forever
for (;;);
}
// if the timer is not running, 'start' the timer
if (myTimers[whichTimer].isRunning == false)
{
// set the start time
myTimers[whichTimer].startTime = millis();
// indicate that the timer is running
myTimers[whichTimer].isRunning = true;
// execute the start function if set
if (myTimers[whichTimer].startFunction != NULL)
{
myTimers[whichTimer].startFunction();
}
}
// if duration has lapsed
if (millis() - myTimers[whichTimer].startTime >= myTimers[whichTimer].duration)
{
// reset isRunning flag
myTimers[whichTimer].isRunning = false;
// execute the end function if set
if (myTimers[whichTimer].endFunction != NULL)
{
myTimers[whichTimer].endFunction();
}
}
// indicate to caller if timer is running
return myTimers[whichTimer].isRunning;
}
Your loop() can no be modified as shown below
void loop()
{
runTimer(0);
}
I hope this gets you on the way; tested on a Leonardo.
For your convenience, the full code for this
// macro to determine number of elements in any type of array
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
// define a timer struct
struct MYTIMER
{
uint32_t startTime; // when delay is started
uint32_t duration; // how long
bool isRunning; // flag indicating if timer is running
void (*startFunction)(); // function to execute when timing starts
void (*endFunction)(); // function to execute when timing ends
};
// function prototypes
void toggleLedBuiltin();
// declare two timers
MYTIMER myTimers[] =
{
{0, 2000, false, NULL, toggleLedBuiltin},
{0, 1200, false, NULL, NULL},
};
void setup()
{
Serial.begin(57600);
while (!Serial);
Serial.print("Number of timers = ");
Serial.println(NUMELEMENTS(myTimers));
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
runTimer(0);
}
/*
execute a 'timer'
In:
number of timer (index in myTimers array)
Returns:
true if timer is running, else false
*/
bool runTimer(uint8_t whichTimer)
{
if (whichTimer >= NUMELEMENTS(myTimers))
{
// inform user about mistake
Serial.println("Invalid timer index");
// hang forever
for (;;);
}
// if the timer is not running, 'start' the timer
if (myTimers[whichTimer].isRunning == false)
{
// set the start time
myTimers[whichTimer].startTime = millis();
// indicate that the timer is running
myTimers[whichTimer].isRunning = true;
// execute the start function if set
if (myTimers[whichTimer].startFunction != NULL)
{
myTimers[whichTimer].startFunction();
}
}
// if duration has lapsed
if (millis() - myTimers[whichTimer].startTime >= myTimers[whichTimer].duration)
{
// reset isRunning flag
myTimers[whichTimer].isRunning = false;
// execute the end function if set
if (myTimers[whichTimer].endFunction != NULL)
{
myTimers[whichTimer].endFunction();
}
}
// indicate to caller if timer is running
return myTimers[whichTimer].isRunning;
}
/*
toggle the built-in led
*/
void toggleLedBuiltin()
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}