|
|
5 years ago | |
|---|---|---|
| .. | ||
| examples | 5 years ago | |
| src | 5 years ago | |
| LICENSE | 5 years ago | |
| README.md | 5 years ago | |
| keywords.txt | 5 years ago | |
| library.properties | 5 years ago | |
2019-01-03: v1.1.0 - Modifying start() which now fails if coroutine already started.
2018-04-30: v1.0.10 - library.properties adjustement.
2018-04-29: v1.0.9 - jm_Scheduler is now compatible with EPS32. 5 new Blink examples added.
2018-04-19: v1.0.8 - yield() function corrected.
2018-03-27: v1.0.7 - A Cooperative Scheduler Library for Arduino.
2018-02-08: v1.0.6 - Minor adjustments.
2017-10-17: v1.0.5 - Minor adjustments.
2017-05-08: v1.0.4 - Minor adjustments.
2017-05-08: v1.0.4 - Minor adjustments.
2017-05-05: v1.0.3 - Adding yield(),sleep(),rearm_async(). Removing void rearm(timestamp_t time, timestamp_t ival);
2017-04-26: v1.0.2 - Adding void rearm(timestamp_t time, timestamp_t ival);
2017-03-29: v1.0.1 - Minor adjustments.
2016-07-08: v1.0.0 - Initial commit.
jm_Scheduler schedules repeated and intervaled coroutines like the JavaScript setInterval() function does,
but with some improvements:
jm_Scheduler doesn't schedule like the official Scheduler Library for Arduino DUE and ZERO does,
yield() function which suspends a task is implemented, but
startLoop() function which allocates a stack to the new task is not implemented.
jm_Scheduler schedules tasks sequentially on the stack processor. The rules to yield and resume are:
return instruction.switch instruction. Or:static.// This example schedules a coroutine every second
#include <jm_Scheduler.h>
jm_Scheduler scheduler;
void coroutine()
{
Serial.print('.');
}
void setup(void)
{
Serial.begin(9600);
scheduler.start(coroutine, TIMESTAMP_1SEC); // Start immediately coroutine() and repeat it every second
}
void loop(void)
{
yield();
}
The timestamp is read from the Arduino function micros().
By design, the micros() function of Arduino UNO and Leonardo running at 16MHz returns a [us] timestamp with a resolution of [4us].
micros() declaration is:
unsigned long micros();
Look at https://www.arduino.cc/en/Reference/Micros for details.
timestamp is a 32bit [us] counter and overflows about every 70 minutes (precisely 1h+11m+34s+967ms+296us).
typedef uint32_t timestamp_t;
#define timestamp_read() ((timestamp_t)micros())
#define TIMESTAMP_DEAD (0x01CA0000) // coroutine dead time [30s + 15ms + 488us]
#define TIMESTAMP_TMAX (0xFE35FFFF) // [1h + 11m + 4s + 951ms + 808us - 1]
#define TIMESTAMP_1US (1UL) // [1us]
#define TIMESTAMP_1MS (1000*TIMESTAMP_1US) // [1ms]
#define TIMESTAMP_1SEC (1000*TIMESTAMP_1MS) // [1s]
#define TIMESTAMP_1MIN (60*TIMESTAMP_1SEC) // [1 minute]
#define TIMESTAMP_1HOUR (60*TIMESTAMP_1MIN) // [1 hour]
timestamp_tdefines the type of all timestamp values.
timestamp_read()returns the instantaneous timestamp. This function can also be used by interrupt coroutines to timestamp they data.
TIMESTAMP_DEADis the maximum allowed execution time of a coroutine to guarantee right scheduling. If the coroutine doesn't end before, the scheduler could miss very long scheduling (see next).
TIMESTAMP_TMAXis the maximum allowed scheduling time of a coroutine. In practice, don't use timestamp values greater than 1 hour.
// start coroutine immediately
void start(voidfuncptr_t func);
// start coroutine immediately and repeat it at fixed interval
void start(voidfuncptr_t func, timestamp_t ival);
// start coroutine on time and repeat it at fixed interval
void start(voidfuncptr_t func, timestamp_t time, timestamp_t ival);
// stop coroutine, current or scheduled, remove it from chain
void stop();
// rearm current coroutine and set or reset interval
void rearm(timestamp_t ival);
// rearm current coroutine, change coroutine function and set or reset interval
void rearm(voidfuncptr_t func, timestamp_t ival);
> `start()` initiates a scheduler variable, starts a coroutine function, immediately or on time, with or without repetitions.
`start()` is invoked once. Next `rearm()` allows changing scheduler values.
> `stop()` cancels further execution of a scheduled coroutine.
`stop()` can be invoked from inside coroutine or elsewhere.
If invoked from inside _coroutine_, `stop()` doesn't exit the function, just cancels further execution.
> `rearm()` changes values of a scheduler variable.
The new values are evaluated on exit coroutine function.
The main usage is to change _interval_ or _function_ or both or else cancel further execution.
static void cycle();
cycle()is the cornerstone of the scheduler and must be invoked as often as possible. Note thatcycle()is a static method. The right place is in Arduinoloop()function. Example:
void loop(void)
{
yield();
}
cycle()can also be invoked in Arduinosetup()function. Example:
void setup(void)
{
// here, some jm_Scheduler variables initialized...
Serial.begin(9600);
while (!Serial)
{
// wait for USB Serial ready...
yield();
}
// split long setup()...
yield();
// continue setup()...
}
cycle()can't be invoked from inside a coroutine function.
To guarantee a good scheduling of all tasks, the execution time of each function must be as short as possible.
Avoid Arduino delay() function, use jm_Scheduler rearm() method with appropriate arguments to split the coroutine in some serialized functions.
Use same technical for long calculations.
Here are some hacks that can be implemented by modifying the file jm_Scheduler.h.
millis().