update Code
This commit is contained in:
parent
3c47103b39
commit
a641fad56c
119 changed files with 10997 additions and 5 deletions
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* TaskScheduler Test
|
||||
*
|
||||
* Initially only tasks 1 and 2 are enabled
|
||||
* Task1 runs every 2 seconds 10 times and then stops
|
||||
* Task2 runs every 3 seconds indefinitely
|
||||
* Task1 enables Task3 at its first run
|
||||
* Task3 run every 5 seconds
|
||||
* Task1 disables Task3 on its last iteration and changed Task2 to run every 1/2 seconds
|
||||
* At the end Task2 is the only task running every 1/2 seconds
|
||||
*/
|
||||
|
||||
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
// Callback methods prototypes
|
||||
void t1Callback();
|
||||
void t2Callback();
|
||||
void t3Callback();
|
||||
|
||||
//Tasks
|
||||
Task t4();
|
||||
Task t1(2000, 10, &t1Callback);
|
||||
Task t2(3000, TASK_FOREVER, &t2Callback);
|
||||
Task t3(5000, TASK_FOREVER, &t3Callback);
|
||||
|
||||
Scheduler runner;
|
||||
|
||||
|
||||
void t1Callback() {
|
||||
Serial.print("t1: ");
|
||||
Serial.println(millis());
|
||||
|
||||
if (t1.isFirstIteration()) {
|
||||
runner.addTask(t3);
|
||||
t3.enable();
|
||||
Serial.println("t1: enabled t3 and added to the chain");
|
||||
}
|
||||
|
||||
if (t1.isLastIteration()) {
|
||||
t3.disable();
|
||||
runner.deleteTask(t3);
|
||||
t2.setInterval(500);
|
||||
Serial.println("t1: disable t3 and delete it from the chain. t2 interval set to 500");
|
||||
}
|
||||
}
|
||||
|
||||
void t2Callback() {
|
||||
Serial.print("t2: ");
|
||||
Serial.println(millis());
|
||||
|
||||
}
|
||||
|
||||
void t3Callback() {
|
||||
Serial.print("t3: ");
|
||||
Serial.println(millis());
|
||||
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scheduler TEST");
|
||||
|
||||
runner.init();
|
||||
Serial.println("Initialized scheduler");
|
||||
|
||||
runner.addTask(t1);
|
||||
Serial.println("added t1");
|
||||
|
||||
runner.addTask(t2);
|
||||
Serial.println("added t2");
|
||||
|
||||
delay(5000);
|
||||
|
||||
t1.enable();
|
||||
Serial.println("Enabled t1");
|
||||
t2.enable();
|
||||
Serial.println("Enabled t2");
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
runner.execute();
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler runner;
|
||||
// Callback methods prototypes
|
||||
void t1Callback();
|
||||
void t2Callback();
|
||||
void t3Callback();
|
||||
|
||||
// Tasks
|
||||
Task t4();
|
||||
Task t1(2000, 10, &t1Callback, &runner, true); //adding task to the chain on creation
|
||||
Task t2(3000, TASK_FOREVER, &t2Callback, &runner, true); //adding task to the chain on creation
|
||||
Task t3(5000, TASK_FOREVER, &t3Callback);
|
||||
|
||||
// Test
|
||||
// Initially only tasks 1 and 2 are enabled
|
||||
// Task1 runs every 2 seconds 10 times and then stops
|
||||
// Task2 runs every 3 seconds indefinitely
|
||||
// Task1 enables Task3 at its first run
|
||||
// Task3 run every 5 seconds
|
||||
// loop() runs every 1 second (a default scheduler delay, if no shorter tasks' interval is detected)
|
||||
// Task1 disables Task3 on its last iteration and changed Task2 to run every 1/2 seconds
|
||||
// Because Task2 interval is shorter than Scheduler default tick, loop() executes ecery 1/2 seconds now
|
||||
// At the end Task2 is the only task running every 1/2 seconds
|
||||
//
|
||||
// NOTE that t1 and t2 are affected by the delay() function in the setup() method and are scheduled immediately twice to "catch up" with millis().
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void t1Callback() {
|
||||
Serial.print("t1: ");
|
||||
Serial.println(millis());
|
||||
|
||||
if (t1.isFirstIteration()) {
|
||||
runner.addTask(t3);
|
||||
t3.enable();
|
||||
Serial.println("t1: enabled t3 and added to the chain");
|
||||
}
|
||||
|
||||
if (t1.isLastIteration()) {
|
||||
t3.disable();
|
||||
runner.deleteTask(t3);
|
||||
t2.setInterval(500);
|
||||
Serial.println("t1: disable t3 and delete it from the chain. t2 interval set to 500");
|
||||
}
|
||||
}
|
||||
|
||||
void t2Callback() {
|
||||
Serial.print("t2: ");
|
||||
Serial.println(millis());
|
||||
|
||||
}
|
||||
|
||||
void t3Callback() {
|
||||
Serial.print("t3: ");
|
||||
Serial.println(millis());
|
||||
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
Serial.println("Scheduler TEST");
|
||||
|
||||
runner.startNow(); // set point-in-time for scheduling start
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
|
||||
runner.execute();
|
||||
|
||||
// Serial.println("Loop ticks at: ");
|
||||
// Serial.println(millis());
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* TaskScheduler Test of OnEnable and OnDisable methods and illustration of using wrapper tasks for timout purposes
|
||||
*
|
||||
* A wrapper task runs every 10 seconds and initiates the test case
|
||||
* Another task is run once for 5 seconds, and serves as a LED blinking timeout - 5 seconds
|
||||
* Finally, a dedicated task which controls LED is running periodically until stopped, and makes the LED blink with 0.5 to 1 second interval.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#ifndef LED_BUILTIN
|
||||
#define LED_BUILTIN 13 // define appropriate pin for your board
|
||||
#endif
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void WrapperCallback();
|
||||
bool BlinkOnEnable();
|
||||
void BlinkOnDisable();
|
||||
void LEDOn();
|
||||
void LEDOff();
|
||||
|
||||
// Tasks
|
||||
Task tWrapper(10000L, TASK_FOREVER, &WrapperCallback, &ts, true);
|
||||
Task tBlink(5000, TASK_ONCE, NULL, &ts, false, &BlinkOnEnable, &BlinkOnDisable);
|
||||
Task tLED(0, TASK_FOREVER, NULL, &ts, false, NULL, &LEDOff);
|
||||
|
||||
void WrapperCallback() {
|
||||
tBlink.restartDelayed(); // LED blinking is initiated
|
||||
//every 30 seconds for 5 seconds
|
||||
}
|
||||
|
||||
|
||||
// Upon being enabled, tBlink will define the parameters
|
||||
// and enable LED blinking task, which actually controls
|
||||
// the hardware (LED in this example)
|
||||
bool BlinkOnEnable() {
|
||||
tLED.setInterval( 200 + random(801) );
|
||||
tLED.setCallback( &LEDOn);
|
||||
tLED.enable();
|
||||
|
||||
return true; // Task should be enabled
|
||||
}
|
||||
|
||||
// tBlink does not really need a callback function
|
||||
// since it just waits for 5 seconds for the first
|
||||
// and only iteration to occur. Once the iteration
|
||||
// takes place, tBlink is disabled by the Scheduler,
|
||||
// thus executing its OnDisable method below.
|
||||
|
||||
void BlinkOnDisable() {
|
||||
tLED.disable();
|
||||
}
|
||||
|
||||
void LEDOn () {
|
||||
digitalWrite(LED_BUILTIN , HIGH);
|
||||
tLED.setCallback( &LEDOff);
|
||||
}
|
||||
|
||||
void LEDOff () {
|
||||
digitalWrite(LED_BUILTIN , LOW);
|
||||
tLED.setCallback( &LEDOn);
|
||||
}
|
||||
|
||||
// Note that LEDOff method serves as OnDisable method
|
||||
// to make sure the LED is turned off when the tBlink
|
||||
// task finishes (or disabled ahead of time)
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
pinMode(LED_BUILTIN , OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/** This test demonstrates interaction between three simple tasks via StatusRequest object.
|
||||
* Task T1 runs every 5 seconds and signals completion of a status request st.
|
||||
* Tasks T2 and T3 are waiting on the same request (st)
|
||||
* Task T3 does not renew its interest in status request st, so it is only invoked once (first iteration)
|
||||
* Task T2 is invoked every time st completes, because it renews its interest in status of status request object st every iteration of T1
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_STATUS_REQUEST
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
StatusRequest st;
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void Callback1();
|
||||
void Disable1();
|
||||
void Callback2();
|
||||
void Callback3();
|
||||
void PrepareStatus();
|
||||
|
||||
// Tasks
|
||||
Task t1(5000, TASK_ONCE, &Callback1, &ts, true, NULL, &Disable1);
|
||||
Task t2(&Callback2, &ts);
|
||||
Task t3(&Callback3, &ts);
|
||||
|
||||
/** T1 callback
|
||||
* T1 just signals completion of st every 5 seconds
|
||||
*/
|
||||
void Callback1() {
|
||||
Serial.println("T1: Signaling completion of ST");
|
||||
st.signalComplete();
|
||||
}
|
||||
|
||||
/** T1 On Disable callback
|
||||
* This callback renews the status request and restarts T1 delayed to run again in 5 seconds
|
||||
*/
|
||||
void Disable1() {
|
||||
PrepareStatus();
|
||||
t1.restartDelayed();
|
||||
}
|
||||
|
||||
/** T2 callback
|
||||
* Invoked when status request st completes
|
||||
*/
|
||||
void Callback2() {
|
||||
Serial.println("T2: Invoked due to completion of ST");
|
||||
}
|
||||
|
||||
|
||||
/** T3 callback
|
||||
* Invoked when status request st completes.
|
||||
* This is only run once since T3 does not renew its interest in the status request st after first iteration
|
||||
*/
|
||||
void Callback3() {
|
||||
Serial.println("T3: Invoked due to completion of ST");
|
||||
|
||||
}
|
||||
|
||||
/** Prepare Status request st for another iteration
|
||||
*
|
||||
*/
|
||||
void PrepareStatus() {
|
||||
st.setWaiting(); // set the statusrequest object for waiting
|
||||
t2.waitFor(&st); // request tasks 1 & 2 to wait on the object st
|
||||
}
|
||||
|
||||
|
||||
/** Main Arduino code
|
||||
* Not much to do here. Just init Serial and set the initial status request
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
Serial.println("TaskScheduler: Status Request Test 1. Simple Test.");
|
||||
|
||||
ts.startNow();
|
||||
PrepareStatus();
|
||||
t3.waitFor(&st);
|
||||
|
||||
t1.delay();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
ts.execute();
|
||||
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/** This test emulates querying 3 sensors once every 10 seconds, each could respond with a different delay
|
||||
* (ultrasonic sensors for instance) and printing a min value of the three when all three have reported their values.
|
||||
* The overall timeout of 1 second is setup as well.
|
||||
* An error message needs to be printed if a timeout occurred instead of a value.
|
||||
*/
|
||||
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_STATUS_REQUEST
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_STM32F1
|
||||
#define A0 3
|
||||
#endif
|
||||
|
||||
StatusRequest measure;
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void CycleCallback();
|
||||
void MeasureCallback();
|
||||
bool MeasureEnable();
|
||||
void MeasureDisable();
|
||||
void CalcCallback();
|
||||
void S1Callback(); bool S1Enable();
|
||||
void S2Callback(); bool S2Enable();
|
||||
void S3Callback(); bool S3Enable();
|
||||
|
||||
// Tasks
|
||||
Task tCycle(10000, TASK_FOREVER, &CycleCallback, &ts, true);
|
||||
Task tMeasure(1000, TASK_ONCE, &MeasureCallback, &ts, false, &MeasureEnable, &MeasureDisable);
|
||||
Task tCalculate(&CalcCallback, &ts);
|
||||
Task tSensor1(0, TASK_ONCE, &S1Callback, &ts, false, &S1Enable);
|
||||
Task tSensor2(0, TASK_ONCE, &S2Callback, &ts, false, &S2Enable);
|
||||
Task tSensor3(0, TASK_ONCE, &S3Callback, &ts, false, &S3Enable);
|
||||
|
||||
|
||||
long distance, d1, d2, d3;
|
||||
|
||||
void CycleCallback() {
|
||||
Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");
|
||||
|
||||
tMeasure.restartDelayed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MeasureEnable() {
|
||||
Serial.println("MeasureEnable: Activating sensors");
|
||||
|
||||
distance = 0;
|
||||
measure.setWaiting(3); // Set the StatusRequest to wait for 3 signals.
|
||||
tCalculate.waitFor(&measure);
|
||||
|
||||
tSensor1.restartDelayed();
|
||||
tSensor2.restartDelayed();
|
||||
tSensor3.restartDelayed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeasureCallback() {
|
||||
Serial.println("MeasureCallback: Invoked by calculate task or one second later");
|
||||
|
||||
if (measure.pending()) {
|
||||
tCalculate.disable();
|
||||
measure.signalComplete(-1); // signal error
|
||||
Serial.println("MeasureCallback: Timeout!");
|
||||
}
|
||||
else {
|
||||
Serial.print("MeasureCallback: Min distance=");Serial.println(distance);
|
||||
}
|
||||
}
|
||||
|
||||
void MeasureDisable() {
|
||||
Serial.println("MeasureDisable: Cleaning up");
|
||||
|
||||
tSensor1.disable();
|
||||
tSensor2.disable();
|
||||
tSensor3.disable();
|
||||
}
|
||||
|
||||
|
||||
void CalcCallback() {
|
||||
Serial.println("CalcCallback: calculating");
|
||||
distance = -1;
|
||||
if ( measure.getStatus() >= 0) { // only calculate if statusrequest ended successfully
|
||||
distance = d1 < d2 ? d1 : d2;
|
||||
distance = d3 < distance ? d3 : distance;
|
||||
tMeasure.forceNextIteration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Simulation code for sensor 1
|
||||
* ----------------------------
|
||||
*/
|
||||
bool S1Enable() {
|
||||
Serial.print("S1Enable: Triggering sensor1. Delay=");
|
||||
|
||||
tSensor1.setInterval( random(1200) ); // Simulating sensor delay, which could go over 1 second and cause timeout
|
||||
d1 = 0;
|
||||
|
||||
Serial.println( tSensor1.getInterval() );
|
||||
return true;
|
||||
}
|
||||
|
||||
void S1Callback() {
|
||||
Serial.print("S1Callback: Emulating measurement. d1=");
|
||||
d1 = random(501); // pick a value from 0 to 500 "centimeters" simulating a measurement
|
||||
measure.signal();
|
||||
|
||||
Serial.println(d1);
|
||||
}
|
||||
|
||||
|
||||
/** Simulation code for sensor 2
|
||||
* ----------------------------
|
||||
*/
|
||||
bool S2Enable() {
|
||||
Serial.print("S2Enable: Triggering sensor2. Delay=");
|
||||
|
||||
tSensor2.setInterval( random(1200) ); // Simulating sensor delay, which could go over 1 second and cause timeout
|
||||
d2 = 0;
|
||||
|
||||
Serial.println( tSensor2.getInterval() );
|
||||
return true;
|
||||
}
|
||||
|
||||
void S2Callback() {
|
||||
Serial.print("S2Callback: Emulating measurement. d2=");
|
||||
d2 = random(501); // pick a value from 0 to 500 "centimeters" simulating a measurement
|
||||
measure.signal();
|
||||
|
||||
Serial.println(d2);
|
||||
}
|
||||
|
||||
|
||||
/** Simulation code for sensor 3
|
||||
* ----------------------------
|
||||
*/
|
||||
bool S3Enable() {
|
||||
Serial.print("S3Enable: Triggering sensor3. Delay=");
|
||||
|
||||
tSensor3.setInterval( random(1200) ); // Simulating sensor delay, which could go over 1 second and cause timeout
|
||||
d3 = 0;
|
||||
|
||||
Serial.println( tSensor3.getInterval() );
|
||||
return true;
|
||||
}
|
||||
|
||||
void S3Callback() {
|
||||
Serial.print("S3Callback: Emulating measurement. d3=");
|
||||
d3 = random(501); // pick a value from 0 to 500 "centimeters" simulating a measurement
|
||||
measure.signal();
|
||||
|
||||
Serial.println(d3);
|
||||
}
|
||||
|
||||
|
||||
/** Main Arduino code
|
||||
* Not much is left here - everything is taken care of by the framework
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("TaskScheduler StatusRequest Sensor Emulation Test. Complex Test.");
|
||||
|
||||
#ifdef ARDUINO_ARCH_STM32F1
|
||||
pinMode(A0, INPUT_ANALOG);
|
||||
#endif
|
||||
|
||||
randomSeed(analogRead(A0)+millis());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
ts.execute();
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
|
||||
/**
|
||||
* This is a test to prove that processor really goes into IDLE sleep.
|
||||
* For this setup:
|
||||
*
|
||||
*
|
||||
|
||||
Task c(10, -1, &Count, &ts);
|
||||
Task t(10000, 1, NULL, &ts, true, &tOn, &tOff);
|
||||
|
||||
The result are:
|
||||
|
||||
1): With #define _TASK_SLEEP_ON_IDLE_RUN enabled
|
||||
On Arduino Uno:
|
||||
Start
|
||||
c1=10771 - v2.5.0 (v1.9.0: same)
|
||||
c2=1001
|
||||
|
||||
On Teensy 3.5 (120MHz ARM):
|
||||
Start
|
||||
c1=21065
|
||||
c2=1001
|
||||
|
||||
On esp8266 (80 MHz)
|
||||
Start
|
||||
c1=10492
|
||||
c2=1001
|
||||
|
||||
On STM32F103RCBT6 (Maple Mini @72 MHz)
|
||||
Start
|
||||
c1=21004
|
||||
c2=1001
|
||||
|
||||
and
|
||||
|
||||
2): With #define _TASK_SLEEP_ON_IDLE_RUN disabled (commented out)
|
||||
Arduino Uno:
|
||||
Start
|
||||
c1=722426 - v3.0.2
|
||||
c1=635735 - v2.5.0
|
||||
c1=551947 - v1.9.0
|
||||
c2=1001
|
||||
|
||||
On Teensy 3.5 (120MHz ARM):
|
||||
Start
|
||||
c1=2690322
|
||||
c2=1001
|
||||
|
||||
On esp8266 (80 MHz)
|
||||
Start
|
||||
c1=351085 (689833 at 160Mhz)
|
||||
c2=1001
|
||||
|
||||
On STM32F103RCBT6 (Maple Mini @72 MHz)
|
||||
Start
|
||||
c1=4665019
|
||||
c2=1001
|
||||
|
||||
C1 in scenario 2) is much higher than in scenario 1) because processor is put to sleep for 1), but not for 2)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Compile and run once with _TASK_SLEEP_ON_IDLE_RUN enabled, then with _TASK_SLEEP_ON_IDLE_RUN disabled.
|
||||
* Compare the results.
|
||||
*/
|
||||
|
||||
//#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void Count();
|
||||
bool tOn(); void tOff();
|
||||
|
||||
// Tasks
|
||||
Task c(10, TASK_FOREVER, &Count, &ts);
|
||||
Task t(10000, TASK_ONCE, NULL, &ts, true, &tOn, &tOff);
|
||||
|
||||
|
||||
volatile unsigned long c1, c2;
|
||||
bool tOn() {
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c.enable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tOff() {
|
||||
c.disable();
|
||||
Serial.print("c1=");Serial.println(c1);
|
||||
Serial.print("c2=");Serial.println(c2);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
Serial.println("Start");
|
||||
|
||||
ts.startNow();
|
||||
t.delay();
|
||||
}
|
||||
|
||||
void Count() {
|
||||
c2++;
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
ts.execute();
|
||||
c1++;
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/**
|
||||
* TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks
|
||||
* THIS SKETCH RUNS ON AVR BOARDS ONLY
|
||||
* Test case:
|
||||
* Watchdog timer is set to 2 seconds (interrupt + reset)
|
||||
* A hearbeat task (resetting the watchdog timer) is scheduled with 500 ms interval
|
||||
* A number of tasks are running every 1 second and "rolling the dice" 0..19. If 5, task is made to enter infinite loop
|
||||
* Device should reset in 2 seconds after a task enters infinite loop
|
||||
* A task id and a control point number are saved to EEPROM prior to device reset, and are displayed after reboot.
|
||||
* In real life, device might chose to NOT activate certain tasks which failed previously (failed sensors for instance)
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_WDT_IDS
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#include <EEPROM.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void TaskCB();
|
||||
void HB(); bool HBOn(); void HBOff();
|
||||
|
||||
// Three tasks emulating accidental infinite loop
|
||||
Task tTask1(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
|
||||
Task tTask2(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
|
||||
Task tTask3(TASK_SECOND, TASK_FOREVER, &TaskCB, &ts, true);
|
||||
|
||||
// Heartbeat task - resetting the watchdog timer periodically
|
||||
// Initiates WDT on enable, and deactivates it on disable
|
||||
Task tHB(500, TASK_FOREVER, &HB, &ts, false, &HBOn, &HBOff);
|
||||
|
||||
/**
|
||||
* Emulating task callback function
|
||||
* Prints task id and randomly "hangs" in two places.
|
||||
* Control points are stored on the task prior to section which might hang,
|
||||
* making this information available to the WDT interrupt handler
|
||||
*/
|
||||
void TaskCB() {
|
||||
Task& T = ts.currentTask();
|
||||
|
||||
Serial.print("Task #:");
|
||||
Serial.print(T.getId());
|
||||
Serial.print(" current iteration = ");
|
||||
Serial.println(T.getRunCounter());
|
||||
|
||||
// Hang if random number between 0 and 19 is 5 (5% probability)
|
||||
T.setControlPoint(10);
|
||||
if (random(20) == 5) for(;;);
|
||||
|
||||
// Hang if random number between 0 and 99 is more that 95 (5% probability)
|
||||
T.setControlPoint(95);
|
||||
if (random(100) > 94) for(;;);
|
||||
}
|
||||
|
||||
/**
|
||||
* This On Enable method sets up the WDT
|
||||
* for interrupt and reset after 2 seconds
|
||||
*/
|
||||
bool HBOn() {
|
||||
|
||||
//disable interrupts
|
||||
cli();
|
||||
//reset watchdog
|
||||
wdt_reset();
|
||||
//set up WDT interrupt
|
||||
WDTCSR = (1<<WDCE)|(1<<WDE);
|
||||
//Start watchdog timer with aDelay prescaller
|
||||
WDTCSR = (1<<WDIE)|(1<<WDE)|(WDTO_2S & 0x2F);
|
||||
// WDTCSR = (1<<WDIE)|(WDTO_2S & 0x2F); // interrupt only without reset
|
||||
//Enable global interrupts
|
||||
sei();
|
||||
}
|
||||
|
||||
/**
|
||||
* This On Disable method disables WDT
|
||||
*/
|
||||
void HBOff() {
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a periodic reset of WDT
|
||||
*/
|
||||
void HB() {
|
||||
wdt_reset();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Watchdog timeout ISR
|
||||
*
|
||||
*/
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
Task& T = ts.currentTask();
|
||||
|
||||
digitalWrite(13, HIGH);
|
||||
EEPROM.write(0, (byte)T.getId());
|
||||
EEPROM.write(1, (byte)T.getControlPoint());
|
||||
digitalWrite(13, LOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard arduino setup routine
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
randomSeed(analogRead(0)+analogRead(5));
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
digitalWrite(13, LOW);
|
||||
|
||||
|
||||
Serial.println("WDT heartbeat test");
|
||||
Serial.print("Last task before reset="); Serial.println(EEPROM.read(0));
|
||||
Serial.print("Last control point before reset="); Serial.println(EEPROM.read(1));
|
||||
|
||||
delay(2000);
|
||||
|
||||
tHB.enableDelayed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not much is left for the loop()
|
||||
*/
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
* TaskScheduler Test sketch - use of task's Local Task Storage pointer
|
||||
* Test case:
|
||||
* Overall test runs for 5 seconds
|
||||
* A number of calculator tasks run every one second, and update their respective variables using Local Task Storage pointer
|
||||
* All calculator tasks use the same callback code, which obtains reference to appropriate variables via LTS pointer
|
||||
* Calculaotr tasks perform simple calculation (as an example):
|
||||
* adding task id number to itself
|
||||
* multiplying task id number by 10
|
||||
*
|
||||
* Upon completion of the overall test, all results are printed out.
|
||||
* Test could be repeated with various number of calculator tasks.
|
||||
* All that needs to change is data definitions - code is completely agnostic of number of tasks
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Compile with support for entering IDLE SLEEP state for 1 ms if not tasks are scheduled to run
|
||||
#define _TASK_WDT_IDS // Compile with support for Task IDs and Watchdog timer
|
||||
#define _TASK_LTS_POINTER // Compile with support for Local Task Storage pointer
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
// Overall number of calculator tasks:
|
||||
#define NO_TASKS 3
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void Calculate(); bool CalcOn();
|
||||
bool WrapperOn(); void WrapperOff();
|
||||
|
||||
// Tasks
|
||||
// Calculator tasks.
|
||||
// Note that all three tasks use the same callback methods
|
||||
// They will be updating specific variables based on the
|
||||
// Locat Task Storage pointers
|
||||
Task t1(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn);
|
||||
Task t2(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn);
|
||||
Task t3(TASK_SECOND, TASK_FOREVER, &Calculate, &ts, false, &CalcOn);
|
||||
// add more calc tasks here if necessary
|
||||
|
||||
Task tWrapper(5*TASK_SECOND, TASK_ONCE, NULL, &ts, false, &WrapperOn, &WrapperOff);
|
||||
|
||||
// The below structure is an object referenced by LTS pointer
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
long sum;
|
||||
long product;
|
||||
} task_var;
|
||||
|
||||
// These are actual structures which hold tasks specific values
|
||||
task_var v1;
|
||||
task_var v2;
|
||||
task_var v3;
|
||||
|
||||
// Arrays below allow indexed access to specific tasks and tasks variables
|
||||
Task *tasks[] = { &t1, &t2, &t3 };
|
||||
task_var *vars[] = { &v1, &v2, &v3 };
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when a wrapper task is enabled
|
||||
* The purpose is to supply LTS pointers to all the tasks
|
||||
*/
|
||||
bool WrapperOn() {
|
||||
|
||||
for (int i=0; i < NO_TASKS; i++) {
|
||||
Task& T = *tasks[i];
|
||||
T.setLtsPointer( vars[i] );
|
||||
T.enableDelayed();
|
||||
}
|
||||
|
||||
return true; // Signal that Task could be enabled
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when Wrapper task is disabled (after first and only iteration is executed)
|
||||
* For each of the calculor tasks the results are printed out.
|
||||
*/
|
||||
void WrapperOff() {
|
||||
Serial.println("Finished processing");
|
||||
|
||||
ts.disableAll();
|
||||
|
||||
for (int i=0; i < NO_TASKS; i++) {
|
||||
Serial.print("ID: "); Serial.println(vars[i]->id);
|
||||
Serial.print("Sum: "); Serial.println(vars[i]->sum);
|
||||
Serial.print("Product: "); Serial.println(vars[i]->product);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is executed when each calculator task is enabled
|
||||
* The purpose is to initiate all local variables
|
||||
*/
|
||||
bool CalcOn() {
|
||||
Task& T = ts.currentTask();
|
||||
task_var& var = *((task_var*) T.getLtsPointer());
|
||||
|
||||
// Initialize local variables
|
||||
var.id = T.getId();
|
||||
var.sum = 0;
|
||||
var.product = var.id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method performs simple calculations on task's local variables
|
||||
*/
|
||||
void Calculate() {
|
||||
Task& T = ts.currentTask();
|
||||
// Another way to get to LTS pointer:
|
||||
task_var& var = *((task_var*) ts.currentLts());
|
||||
|
||||
|
||||
Serial.print("Calculating for task: ");
|
||||
Serial.print(T.getId());
|
||||
Serial.print("; Task id per LTS is: ");
|
||||
Serial.println( var.id );
|
||||
|
||||
var.sum += T.getId();
|
||||
var.product = var.product * 10;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Standard Arduino setup and loop methods
|
||||
*/
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
randomSeed(analogRead(0)+analogRead(5));
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
digitalWrite(13, LOW);
|
||||
|
||||
Serial.println("Local Task Storage pointer test");
|
||||
|
||||
tWrapper.enableDelayed();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* TaskScheduler Test
|
||||
* Illustration of use of Time Critical Information
|
||||
*
|
||||
* Task1 runs every 1 second indefinitely
|
||||
* On each run it reports how delayed the invokation of the callback method was,
|
||||
* and what was the scheduling overun.
|
||||
* Each run task 1 is dealyed randomly for up to 2 seconds, thus simulating scheduling overrun
|
||||
*/
|
||||
|
||||
#define _TASK_TIMECRITICAL
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
// Callback methods prototypes
|
||||
void t1Callback();
|
||||
|
||||
|
||||
//Tasks
|
||||
Task t1(1000, -1, &t1Callback);
|
||||
|
||||
Scheduler runner;
|
||||
|
||||
|
||||
void t1Callback() {
|
||||
Serial.print(millis());
|
||||
Serial.print(": overrun = ");
|
||||
Serial.print(t1.getOverrun());
|
||||
Serial.print(", start delayed by ");
|
||||
Serial.println(t1.getStartDelay());
|
||||
|
||||
int i = random(2000);
|
||||
Serial.print("Delaying for "); Serial.println(i);
|
||||
delay(i);
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scheduler TimeCritical TEST");
|
||||
|
||||
runner.init();
|
||||
Serial.println("Initialized scheduler");
|
||||
|
||||
runner.addTask(t1);
|
||||
Serial.println("added t1. Waiting for 5 seconds.");
|
||||
|
||||
delay(5000);
|
||||
|
||||
t1.enable();
|
||||
|
||||
Serial.println("Enabled t1");
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
runner.execute();
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
/**
|
||||
* This is a test to benchmark TaskScheduler execution.
|
||||
*
|
||||
* This test executes 1,000,000 cycles of a task with empty callback method
|
||||
* Compiled with different options, you can assess the impact of each on the size of the Task object
|
||||
* and the execution overhead of the main execution pass route.
|
||||
*
|
||||
* Sample execution times (in milliseconds per 1M iterations) are provided below.
|
||||
* The test board is Arduino UNO 16MHz processor.
|
||||
*
|
||||
|
||||
TaskScheduler 2.1.0:
|
||||
No modifiers
|
||||
Duration=19869
|
||||
|
||||
with SLEEP
|
||||
Duration=20058
|
||||
|
||||
with status request:
|
||||
Duration=20058
|
||||
|
||||
with time critical:
|
||||
Duration=27289
|
||||
|
||||
|
||||
TaskScheduler 1.9.0:
|
||||
No modifiers
|
||||
Duration=15656
|
||||
|
||||
with SLEEP
|
||||
Duration=16285
|
||||
|
||||
with status request:
|
||||
Duration=16600
|
||||
|
||||
with rollover fix:
|
||||
Duration=18109
|
||||
|
||||
|
||||
TaskScheduler 1.8.5:
|
||||
Duration=15719
|
||||
|
||||
with SLEEP
|
||||
Duration=16348
|
||||
|
||||
with status request:
|
||||
Duration=18360
|
||||
|
||||
with rollover fix:
|
||||
Duration=18423
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//#define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
//#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
//#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
//#define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
//#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
//#define _TASK_MICRO_RES
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
bool tOn(); void tOff();
|
||||
void callback();
|
||||
|
||||
// Tasks
|
||||
Task t(TASK_IMMEDIATE, 1000000, &callback, &ts, false, &tOn, &tOff);
|
||||
|
||||
unsigned long c1, c2;
|
||||
|
||||
bool tOn() {
|
||||
c1 = millis();
|
||||
c2 = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tOff() {
|
||||
c2 = millis();
|
||||
Serial.println("done.");
|
||||
Serial.print("Tstart =");Serial.println(c1);
|
||||
Serial.print("Tfinish=");Serial.println(c2);
|
||||
Serial.print("Duration=");Serial.println(c2-c1);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
Serial.print("Start...");
|
||||
|
||||
t.enable();
|
||||
}
|
||||
|
||||
void callback() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* This is a test of TaskScheduler layered priority funtionality
|
||||
*
|
||||
* Current test employs two priority layers:
|
||||
* Base scheduler runs tasks t1, t2 and t3
|
||||
* High priority scheduler runs tasks t4 and t5
|
||||
*
|
||||
* Sequence of task scheduling (not execution!) is:
|
||||
* 4, 5, 1, 4, 5, 2, 4, 5, 3 = one base scheduler pass
|
||||
*
|
||||
* Scheduling overhead (at 20 micros per one pass) is: (B + B * H) * T = (3 + 3 * 2) * 18 = 162 micros
|
||||
* where
|
||||
* B - number of tasks in the base scheduler's chain
|
||||
* H - number of tasks in the high priority scheduler's chain
|
||||
* T - scheduling overhead for 1 pass (~15-18 microseconds)
|
||||
*
|
||||
* Actual task execution order:
|
||||
|
||||
Scheduler Priority Test
|
||||
Task: 40: 0 Start delay = 0
|
||||
Task: 50: 10 Start delay = 10
|
||||
Task: 1: 21 Start delay = 21
|
||||
Task: 2: 31 Start delay = 31
|
||||
Task: 3: 41 Start delay = 41
|
||||
|
||||
Task: 40: 500 Start delay = 0
|
||||
Task: 40: 1000 Start delay = 0
|
||||
Task: 50: 1010 Start delay = 10
|
||||
Task: 1: 1021 Start delay = 20
|
||||
Task: 40: 1500 Start delay = 0
|
||||
Task: 40: 2000 Start delay = 0
|
||||
Task: 50: 2011 Start delay = 11
|
||||
Task: 1: 2022 Start delay = 21
|
||||
Task: 2: 2032 Start delay = 32
|
||||
Task: 40: 2500 Start delay = 0
|
||||
Task: 40: 3000 Start delay = 0
|
||||
Task: 50: 3010 Start delay = 10
|
||||
Task: 1: 3021 Start delay = 20
|
||||
Task: 3: 3032 Start delay = 32
|
||||
|
||||
Task: 40: 3500 Start delay = 0
|
||||
Task: 40: 4000 Start delay = 0
|
||||
Task: 50: 4011 Start delay = 11
|
||||
Task: 1: 4022 Start delay = 21
|
||||
Task: 2: 4032 Start delay = 32
|
||||
Task: 40: 4500 Start delay = 0
|
||||
Task: 40: 5000 Start delay = 0
|
||||
Task: 50: 5010 Start delay = 10
|
||||
Task: 1: 5021 Start delay = 20
|
||||
Task: 40: 5500 Start delay = 0
|
||||
Task: 40: 6000 Start delay = 0
|
||||
Task: 50: 6010 Start delay = 10
|
||||
Task: 1: 6022 Start delay = 21
|
||||
Task: 2: 6032 Start delay = 32
|
||||
Task: 3: 6043 Start delay = 42
|
||||
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_PRIORITY
|
||||
#define _TASK_WDT_IDS
|
||||
#define _TASK_TIMECRITICAL
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler r, hpr;
|
||||
|
||||
// Callback methods prototypes
|
||||
void tCallback();
|
||||
|
||||
// Tasks
|
||||
Task t1(1000, TASK_FOREVER, &tCallback, &r); //adding task to the chain on creation
|
||||
Task t2(2000, TASK_FOREVER, &tCallback, &r);
|
||||
Task t3(3000, TASK_FOREVER, &tCallback, &r);
|
||||
|
||||
Task t4(500, TASK_FOREVER, &tCallback, &hpr); //adding task to the chain on creation
|
||||
Task t5(1000, TASK_FOREVER, &tCallback, &hpr); //adding task to the chain on creation
|
||||
|
||||
void tCallback() {
|
||||
Scheduler &s = Scheduler::currentScheduler();
|
||||
Task &t = s.currentTask();
|
||||
|
||||
Serial.print("Task: "); Serial.print(t.getId());Serial.print(":\t");
|
||||
Serial.print(millis()); Serial.print("\tStart delay = "); Serial.println(t.getStartDelay());
|
||||
delay(10);
|
||||
|
||||
if (t.getId() == 3) Serial.println();
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scheduler Priority Test");
|
||||
|
||||
t4.setId(40);
|
||||
t5.setId(50);
|
||||
|
||||
r.setHighPriorityScheduler(&hpr);
|
||||
r.enableAll(true); // this will recursively enable the higher priority tasks as well
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
|
||||
r.execute();
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* This is a test of TaskScheduler layered priority funtionality
|
||||
*
|
||||
* Current test employs three priority layers:
|
||||
* Base scheduler runs tasks t1, t2 and t3
|
||||
* High priority scheduler runs tasks t4 and t5
|
||||
* Highest priority scheduler runs tasks t6 and t7
|
||||
*
|
||||
* Sequence of task scheduling (not execution!) is:
|
||||
* 6, 7, 4, 6, 7, 5, 1, 6, 7, 4, 6, 7, 5, 2, 6, 7, 4, 6, 7, 5, 3 = one base scheduler pass
|
||||
*
|
||||
* Scheduling overhead (at 20 micros per one pass) is: (B + B * H + B * H * C) * T = (3 + 3 * 2 + 3 * 2 * 2) * 18 = 378 micros
|
||||
* where
|
||||
* B - number of tasks in the base scheduler's chain
|
||||
* H - number of tasks in the high priority scheduler's chain
|
||||
* C - number of tasks in the critical priority scheduler's chain
|
||||
* T - scheduling overhead for 1 pass (~15-18 microseconds)
|
||||
*
|
||||
* Actual task execution order:
|
||||
|
||||
Scheduler Priority Test
|
||||
Task: 600: 0 Start delay = 0
|
||||
Task: 700: 10 Start delay = 10
|
||||
Task: 40: 21 Start delay = 21
|
||||
Task: 50: 31 Start delay = 31
|
||||
Task: 1: 43 Start delay = 41
|
||||
Task: 2: 53 Start delay = 53
|
||||
Task: 3: 63 Start delay = 63
|
||||
|
||||
Task: 600: 500 Start delay = 0
|
||||
Task: 40: 510 Start delay = 10
|
||||
Task: 600: 1000 Start delay = 0
|
||||
Task: 700: 1010 Start delay = 10
|
||||
Task: 40: 1021 Start delay = 21
|
||||
Task: 50: 1032 Start delay = 32
|
||||
Task: 1: 1043 Start delay = 43
|
||||
Task: 600: 1500 Start delay = 0
|
||||
Task: 40: 1510 Start delay = 10
|
||||
Task: 600: 2000 Start delay = 0
|
||||
Task: 700: 2011 Start delay = 11
|
||||
Task: 40: 2022 Start delay = 22
|
||||
Task: 50: 2032 Start delay = 32
|
||||
Task: 1: 2043 Start delay = 43
|
||||
Task: 2: 2054 Start delay = 54
|
||||
Task: 600: 2500 Start delay = 0
|
||||
Task: 40: 2510 Start delay = 10
|
||||
Task: 600: 3000 Start delay = 0
|
||||
Task: 700: 3010 Start delay = 10
|
||||
Task: 40: 3021 Start delay = 21
|
||||
Task: 50: 3032 Start delay = 32
|
||||
Task: 1: 3043 Start delay = 43
|
||||
Task: 3: 3053 Start delay = 53
|
||||
|
||||
Task: 600: 3500 Start delay = 0
|
||||
Task: 40: 3510 Start delay = 10
|
||||
Task: 600: 4000 Start delay = 0
|
||||
Task: 700: 4011 Start delay = 11
|
||||
Task: 40: 4022 Start delay = 22
|
||||
Task: 50: 4032 Start delay = 32
|
||||
Task: 1: 4043 Start delay = 43
|
||||
Task: 2: 4054 Start delay = 54
|
||||
Task: 600: 4500 Start delay = 0
|
||||
Task: 40: 4510 Start delay = 10
|
||||
Task: 600: 5000 Start delay = 0
|
||||
Task: 700: 5010 Start delay = 10
|
||||
Task: 40: 5021 Start delay = 21
|
||||
Task: 50: 5031 Start delay = 31
|
||||
Task: 1: 5043 Start delay = 43
|
||||
Task: 600: 5500 Start delay = 0
|
||||
Task: 40: 5511 Start delay = 11
|
||||
Task: 600: 6000 Start delay = 0
|
||||
Task: 700: 6010 Start delay = 10
|
||||
Task: 40: 6022 Start delay = 22
|
||||
Task: 50: 6032 Start delay = 32
|
||||
Task: 1: 6043 Start delay = 43
|
||||
Task: 2: 6053 Start delay = 53
|
||||
Task: 3: 6065 Start delay = 65
|
||||
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_PRIORITY
|
||||
#define _TASK_WDT_IDS
|
||||
#define _TASK_TIMECRITICAL
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler r;
|
||||
Scheduler hpr;
|
||||
Scheduler cpr;
|
||||
|
||||
// Callback methods prototypes
|
||||
void tCallback();
|
||||
|
||||
// Tasks
|
||||
Task t1(1000, TASK_FOREVER, &tCallback, &r); //adding task to the chain on creation
|
||||
Task t2(2000, TASK_FOREVER, &tCallback, &r);
|
||||
Task t3(3000, TASK_FOREVER, &tCallback, &r);
|
||||
|
||||
Task t4(500, TASK_FOREVER, &tCallback, &hpr); //adding task to the chain on creation
|
||||
Task t5(1000, TASK_FOREVER, &tCallback, &hpr); //adding task to the chain on creation
|
||||
|
||||
Task t6(500, TASK_FOREVER, &tCallback, &cpr); //adding task to the chain on creation
|
||||
Task t7(1000, TASK_FOREVER, &tCallback, &cpr); //adding task to the chain on creation
|
||||
|
||||
void tCallback() {
|
||||
Scheduler &s = Scheduler::currentScheduler();
|
||||
Task &t = s.currentTask();
|
||||
|
||||
Serial.print("Task: "); Serial.print(t.getId());Serial.print(":\t");
|
||||
Serial.print(millis()); Serial.print("\tStart delay = "); Serial.println(t.getStartDelay());
|
||||
delay(10);
|
||||
|
||||
if (t.getId() == 3) Serial.println();
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scheduler Priority Test");
|
||||
|
||||
t4.setId(40);
|
||||
t5.setId(50);
|
||||
|
||||
t6.setId(600);
|
||||
t7.setId(700);
|
||||
|
||||
r.setHighPriorityScheduler(&hpr);
|
||||
hpr.setHighPriorityScheduler(&cpr);
|
||||
r.enableAll(true); // this will recursively enable the higher priority tasks as well
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
|
||||
r.execute();
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* TaskScheduler Test of microsecond scheduling resolution
|
||||
*
|
||||
* Task 1 runs starting with 211 microseconds intervals, doubling the interval on every iteration
|
||||
* until it wraps when interval reaches about 72 minutes mark
|
||||
*
|
||||
* Task 2 provides heartbeat at a steady 5 seconds intervals
|
||||
*
|
||||
*/
|
||||
|
||||
#define _TASK_MICRO_RES
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#define T1_INIT (211L)
|
||||
|
||||
Scheduler runner;
|
||||
// Callback methods prototypes
|
||||
void t1Callback();
|
||||
void t1OnDisable();
|
||||
void t2Callback();
|
||||
|
||||
|
||||
unsigned long t1_interval = T1_INIT;
|
||||
|
||||
// Tasks
|
||||
Task t1(t1_interval, 1, &t1Callback, &runner, true, NULL, &t1OnDisable); //adding task to the chain on creation
|
||||
Task t2(5 * TASK_SECOND, TASK_FOREVER, &t2Callback, &runner, true); //adding task to the chain on creation
|
||||
|
||||
|
||||
|
||||
void t1Callback() {
|
||||
unsigned long t = micros();
|
||||
Serial.print("t1: ");
|
||||
Serial.println(t);
|
||||
}
|
||||
|
||||
void t1OnDisable() {
|
||||
t1_interval += t1_interval;
|
||||
if (t1_interval < T1_INIT) t1_interval = T1_INIT;
|
||||
t1.setInterval(t1_interval);
|
||||
t1.restartDelayed();
|
||||
}
|
||||
|
||||
void t2Callback() {
|
||||
unsigned long t = micros();
|
||||
Serial.print("t2: ");
|
||||
Serial.print(t);
|
||||
Serial.println(" heartbeat");
|
||||
}
|
||||
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Scheduler TEST Microsecond Resolution");
|
||||
|
||||
Serial.println("5 seconds delay");
|
||||
delay(5000);
|
||||
|
||||
runner.startNow(); // This creates a new scheduling starting point for all ACTIVE tasks.
|
||||
// PLEASE NOTE - THIS METHOD DOES NOT ACTIVATE TASKS, JUST RESETS THE START TIME
|
||||
t1.delay(); // Tasks which need to start delayed, need to be delayed again after startNow();
|
||||
|
||||
// Alternatively, tasks should be just enabled at the bottom of setup() method
|
||||
// runner.enableAll();
|
||||
// t1.delay();
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
runner.execute();
|
||||
}
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
This test illustrates the use if yield methods and internal StatusRequest objects
|
||||
THIS TEST HAS BEEN TESTED ON NODEMCU V.2 (ESP8266)
|
||||
|
||||
The WiFi initialization and NTP update is executed in parallel to blinking the onboard LED
|
||||
and an external LED connected to D2 (GPIO04)
|
||||
Try running with and without correct WiFi parameters to observe the difference in behaviour
|
||||
*/
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_STATUS_REQUEST
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void connectInit();
|
||||
void ledCallback();
|
||||
bool ledOnEnable();
|
||||
void ledOnDisable();
|
||||
void ledOn();
|
||||
void ledOff();
|
||||
void ntpUpdateInit();
|
||||
|
||||
// Tasks
|
||||
|
||||
Task tConnect (TASK_SECOND, TASK_FOREVER, &connectInit, &ts, true);
|
||||
Task tLED (TASK_IMMEDIATE, TASK_FOREVER, &ledCallback, &ts, false, &ledOnEnable, &ledOnDisable);
|
||||
|
||||
// Tasks running on events
|
||||
Task tNtpUpdate (&ntpUpdateInit, &ts);
|
||||
|
||||
// Replace with WiFi parameters of your Access Point/Router:
|
||||
const char *ssid = "wifi_network";
|
||||
const char *pwd = "wifi_password";
|
||||
|
||||
long ledDelayOn, ledDelayOff;
|
||||
|
||||
#define LEDPIN D0 // Onboard LED pin - linked to WiFi
|
||||
#define LEDPIN2 D2 // External LED
|
||||
#define CONNECT_TIMEOUT 30 // Seconds
|
||||
#define CONNECT_OK 0 // Status of successful connection to WiFi
|
||||
#define CONNECT_FAILED (-99) // Status of failed connection to WiFi
|
||||
|
||||
// NTP Related Definitions
|
||||
#define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message
|
||||
|
||||
IPAddress timeServerIP; // time.nist.gov NTP server address
|
||||
const char* ntpServerName = "time.nist.gov";
|
||||
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
|
||||
unsigned long epoch;
|
||||
|
||||
WiFiUDP udp; // A UDP instance to let us send and receive packets over UDP
|
||||
|
||||
#define LOCAL_NTP_PORT 2390 // Local UDP port for NTP update
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(74880);
|
||||
Serial.println(F("TaskScheduler test #14 - Yield and internal StatusRequests"));
|
||||
Serial.println(F("=========================================================="));
|
||||
Serial.println();
|
||||
|
||||
pinMode (LEDPIN, OUTPUT);
|
||||
pinMode (LEDPIN2, OUTPUT);
|
||||
|
||||
tNtpUpdate.waitFor( tConnect.getInternalStatusRequest() ); // NTP Task will start only after connection is made
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute(); // Only Scheduler should be executed in the loop
|
||||
}
|
||||
|
||||
/**
|
||||
Initiate connection to the WiFi network
|
||||
*/
|
||||
void connectInit() {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": connectInit."));
|
||||
Serial.println(F("WiFi parameters: "));
|
||||
Serial.print(F("SSID: ")); Serial.println(ssid);
|
||||
Serial.print(F("PWD : ")); Serial.println(pwd);
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.hostname("esp8266");
|
||||
WiFi.begin(ssid, pwd);
|
||||
yield();
|
||||
|
||||
ledDelayOn = TASK_SECOND / 2;
|
||||
ledDelayOff = TASK_SECOND / 4;
|
||||
tLED.enable();
|
||||
|
||||
tConnect.yield(&connectCheck); // This will pass control back to Scheduler and then continue with connection checking
|
||||
}
|
||||
|
||||
/**
|
||||
Periodically check if connected to WiFi
|
||||
Re-request connection every 5 seconds
|
||||
Stop trying after a timeout
|
||||
*/
|
||||
void connectCheck() {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": connectCheck."));
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) { // Connection established
|
||||
Serial.print(millis());
|
||||
Serial.print(F(": Connected to AP. Local ip: "));
|
||||
Serial.println(WiFi.localIP());
|
||||
tConnect.disable();
|
||||
}
|
||||
else {
|
||||
|
||||
if (tConnect.getRunCounter() % 5 == 0) { // re-request connection every 5 seconds
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": Re-requesting connection to AP..."));
|
||||
|
||||
WiFi.disconnect(true);
|
||||
yield(); // This is an esp8266 standard yield to allow linux wifi stack run
|
||||
WiFi.hostname("esp8266");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, pwd);
|
||||
yield(); // This is an esp8266 standard yield to allow linux wifi stack run
|
||||
}
|
||||
|
||||
if (tConnect.getRunCounter() == CONNECT_TIMEOUT) { // Connection Timeout
|
||||
tConnect.getInternalStatusRequest()->signal(CONNECT_FAILED); // Signal unsuccessful completion
|
||||
tConnect.disable();
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": connectOnDisable."));
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": Unable to connect to WiFi."));
|
||||
|
||||
ledDelayOn = TASK_SECOND / 16; // Blink LEDs quickly due to error
|
||||
ledDelayOff = TASK_SECOND / 16;
|
||||
tLED.enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initiate NTP update if connection was established
|
||||
*/
|
||||
void ntpUpdateInit() {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": ntpUpdateInit."));
|
||||
|
||||
if ( tConnect.getInternalStatusRequest()->getStatus() != CONNECT_OK ) { // Check status of the Connect Task
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": cannot update NTP - not connected."));
|
||||
return;
|
||||
}
|
||||
|
||||
udp.begin(LOCAL_NTP_PORT);
|
||||
if ( WiFi.hostByName(ntpServerName, timeServerIP) ) { //get a random server from the pool
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.print(F(": timeServerIP = "));
|
||||
Serial.println(timeServerIP);
|
||||
|
||||
sendNTPpacket(timeServerIP); // send an NTP packet to a time server
|
||||
}
|
||||
else {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": NTP server address lookup failed."));
|
||||
tLED.disable();
|
||||
udp.stop();
|
||||
tNtpUpdate.disable();
|
||||
return;
|
||||
}
|
||||
|
||||
ledDelayOn = TASK_SECOND / 8;
|
||||
ledDelayOff = TASK_SECOND / 8;
|
||||
tLED.enable();
|
||||
|
||||
tNtpUpdate.set( TASK_SECOND, CONNECT_TIMEOUT, &ntpCheck );
|
||||
tNtpUpdate.enableDelayed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if NTP packet was received
|
||||
* Re-request every 5 seconds
|
||||
* Stop trying after a timeout
|
||||
*/
|
||||
void ntpCheck() {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": ntpCheck."));
|
||||
|
||||
if ( tNtpUpdate.getRunCounter() % 5 == 0) {
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": Re-requesting NTP update..."));
|
||||
|
||||
udp.stop();
|
||||
yield();
|
||||
udp.begin(LOCAL_NTP_PORT);
|
||||
sendNTPpacket(timeServerIP);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( doNtpUpdateCheck()) {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": NTP Update successful"));
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.print(F(": Unix time = "));
|
||||
Serial.println(epoch);
|
||||
|
||||
tLED.disable();
|
||||
tNtpUpdate.disable();
|
||||
udp.stop();
|
||||
}
|
||||
else {
|
||||
if ( tNtpUpdate.isLastIteration() ) {
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": NTP Update failed"));
|
||||
tLED.disable();
|
||||
udp.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send NTP packet to NTP server
|
||||
*/
|
||||
unsigned long sendNTPpacket(IPAddress & address)
|
||||
{
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": sendNTPpacket."));
|
||||
|
||||
// set all bytes in the buffer to 0
|
||||
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
||||
// Initialize values needed to form NTP request
|
||||
// (see URL above for details on the packets)
|
||||
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||
packetBuffer[1] = 0; // Stratum, or type of clock
|
||||
packetBuffer[2] = 6; // Polling Interval
|
||||
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||
// 8 bytes of zero for Root Delay & Root Dispersion
|
||||
packetBuffer[12] = 49;
|
||||
packetBuffer[13] = 0x4E;
|
||||
packetBuffer[14] = 49;
|
||||
packetBuffer[15] = 52;
|
||||
|
||||
// all NTP fields have been given values, now
|
||||
// you can send a packet requesting a timestamp:
|
||||
udp.beginPacket(address, 123); //NTP requests are to port 123
|
||||
udp.write(packetBuffer, NTP_PACKET_SIZE);
|
||||
udp.endPacket();
|
||||
yield();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a packet was recieved.
|
||||
* Process NTP information if yes
|
||||
*/
|
||||
bool doNtpUpdateCheck() {
|
||||
|
||||
Serial.print(millis());
|
||||
Serial.println(F(": doNtpUpdateCheck."));
|
||||
|
||||
yield();
|
||||
int cb = udp.parsePacket();
|
||||
if (cb) {
|
||||
// We've received a packet, read the data from it
|
||||
udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
|
||||
//the timestamp starts at byte 40 of the received packet and is four bytes,
|
||||
// or two words, long. First, esxtract the two words:
|
||||
|
||||
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
|
||||
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
|
||||
// combine the four bytes (two words) into a long integer
|
||||
// this is NTP time (seconds since Jan 1 1900):
|
||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||
|
||||
// now convert NTP time into everyday time:
|
||||
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
|
||||
const unsigned long seventyYears = 2208988800UL;
|
||||
// subtract seventy years:
|
||||
epoch = secsSince1900 - seventyYears;
|
||||
return (epoch != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the LED state based on the current state
|
||||
*/
|
||||
bool ledState;
|
||||
void ledCallback() {
|
||||
if ( ledState ) ledOff();
|
||||
else ledOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the LED starts lit
|
||||
*/
|
||||
bool ledOnEnable() {
|
||||
ledOn();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure LED ends dimmed
|
||||
*/
|
||||
void ledOnDisable() {
|
||||
ledOff();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn LEDs on.
|
||||
* Set appropriate delay.
|
||||
* PLEASE NOTE: NodeMCU onbaord LED is active-low
|
||||
*/
|
||||
void ledOn() {
|
||||
ledState = true;
|
||||
digitalWrite(LEDPIN, LOW);
|
||||
digitalWrite(LEDPIN2, HIGH);
|
||||
tLED.delay( ledDelayOn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn LEDs off.
|
||||
* Set appropriate delay.
|
||||
* PLEASE NOTE: NodeMCU onbaord LED is active-low
|
||||
*/
|
||||
void ledOff() {
|
||||
ledState = false;
|
||||
digitalWrite(LEDPIN, HIGH);
|
||||
digitalWrite(LEDPIN2, LOW);
|
||||
tLED.delay( ledDelayOff );
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* TaskScheduler Test sketch - Showing how to use std::function
|
||||
* to get acces to variables from within the task callback function
|
||||
*
|
||||
* Support for std::function is only available for ESP8266 architecture
|
||||
*/
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#define _TASK_STD_FUNCTION // Compile with support for std::function
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler ts;
|
||||
int counter = 0;
|
||||
|
||||
class Calculator {
|
||||
public:
|
||||
int cumSum = 0; // cumulative sum
|
||||
Calculator(int b) {
|
||||
// Pass the this pointer, so that we get access to this->cumSum
|
||||
// Also pass a copy of b
|
||||
calculateTask.set(TASK_SECOND, TASK_FOREVER, [this, b]() {
|
||||
counter++;
|
||||
Serial.printf("%u. %u: cumSum = %u + %u\t", counter, millis(), cumSum, b);
|
||||
cumSum += b;
|
||||
Serial.printf("Resulting cumulative sum: %u\n", cumSum);
|
||||
});
|
||||
ts.addTask(calculateTask);
|
||||
calculateTask.enable();
|
||||
}
|
||||
|
||||
Task calculateTask;
|
||||
};
|
||||
|
||||
Calculator calc1(2);
|
||||
Calculator calc2(4);
|
||||
Calculator calc3(8);
|
||||
|
||||
// Disable tasks after 10 seconds
|
||||
Task tWrapper(10*TASK_SECOND, TASK_ONCE, []() {
|
||||
ts.disableAll();
|
||||
}, &ts);
|
||||
|
||||
/**
|
||||
* Standard Arduino setup and loop methods
|
||||
*/
|
||||
void setup() {
|
||||
Serial.begin(74880);
|
||||
Serial.println("std::function test");
|
||||
tWrapper.enableDelayed();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//This file is intentionally left blank.
|
||||
//
|
||||
//Arduino IDE plays some dirty tricks on the main sketch .ino file:
|
||||
//it rearranges #includes, blindly creates forward definitions,
|
||||
//includes every file in the project that does not have .c or .cpp
|
||||
//file extension.
|
||||
//
|
||||
//Usually it all turns well if you have only one source file and you are either
|
||||
//inexperienced or really expert C++ Arduino programmer.
|
||||
//For the folks with the middle ground skills level, when you want
|
||||
//to split your code into several .cpp files, it is best to leave
|
||||
//this main sketch empty.
|
||||
//
|
||||
//It doesn't matter where you define the void loop() and void setup().
|
||||
//Just make sure there is exactly one definition of each.
|
||||
//
|
||||
//And if you want to use standard Arduino functions
|
||||
//like digitalWrite or the Serial object - just add #include<Arduino.h>.
|
|
@ -0,0 +1,31 @@
|
|||
#include <Arduino.h>
|
||||
#include "header.hpp"
|
||||
|
||||
|
||||
//Declare the functions we want to use before we are ready to define them
|
||||
void t1Callback();
|
||||
|
||||
|
||||
// Tasks
|
||||
Task t1(2000, 10, &t1Callback, &runner, true); //adding task to the chain on creation
|
||||
Task t3(5000, TASK_FOREVER, &t3Callback);
|
||||
|
||||
|
||||
void t1Callback() {
|
||||
Serial.print("t1: ");
|
||||
Serial.println(millis());
|
||||
|
||||
if (t1.isFirstIteration()) {
|
||||
runner.addTask(t3);
|
||||
t3.enable();
|
||||
Serial.println("t1: enabled t3 and added to the chain");
|
||||
}
|
||||
|
||||
if (t1.isLastIteration()) {
|
||||
t3.disable();
|
||||
runner.deleteTask(t3);
|
||||
t2.setInterval(500);
|
||||
Serial.println("t1: disable t3 and delete it from the chain. t2 interval set to 500");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Test the same as example#2:
|
||||
// Initially only tasks 1 and 2 are enabled
|
||||
// Task1 runs every 2 seconds 10 times and then stops
|
||||
// Task2 runs every 3 seconds indefinitely
|
||||
// Task1 enables Task3 at its first run
|
||||
// Task3 run every 5 seconds
|
||||
// loop() runs every 1 second (a default scheduler delay, if no shorter tasks' interval is detected)
|
||||
// Task1 disables Task3 on its last iteration and changed Task2 to run every 1/2 seconds
|
||||
// Because Task2 interval is shorter than Scheduler default tick, loop() executes ecery 1/2 seconds now
|
||||
// At the end Task2 is the only task running every 1/2 seconds
|
||||
|
||||
|
||||
//Header that declares all shared objects between .cpp files
|
||||
#include "header.hpp"
|
||||
|
||||
#include <Arduino.h> //for Serial and delay
|
||||
|
||||
Scheduler runner; //Let the scheduler live here, in the main file, ok?
|
||||
|
||||
|
||||
//Pretend, that the t2 task is a special task,
|
||||
//that needs to live in file2 object file.
|
||||
void t2Callback() {
|
||||
Serial.print("t2: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
Task t2(3000, TASK_FOREVER, &t2Callback, &runner, true);
|
||||
|
||||
//Lets define t3Callback here. We are going to use it in file1
|
||||
//for Task 1.
|
||||
void t3Callback() {
|
||||
Serial.print("t3: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void setup () {
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
Serial.println("Scheduler TEST (multi-tab)");
|
||||
|
||||
runner.startNow(); // set point-in-time for scheduling start
|
||||
}
|
||||
|
||||
|
||||
void loop () {
|
||||
runner.execute();
|
||||
|
||||
// Serial.println("Loop ticks at: ");
|
||||
// Serial.println(millis());
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//This is the place to declare every single function
|
||||
//and global variable that is going to be reused between cpp files.
|
||||
|
||||
|
||||
//We are going to use the TaskScheduler, but only the declarations part.
|
||||
//Remember to put customization macros before the #include:
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
|
||||
//Let the runner object be a global, single instance shared between object files.
|
||||
extern Scheduler runner;
|
||||
extern Task t2; //the t2 is defined in file2, but we need to access it from file1.
|
||||
|
||||
//This function needs to be shared (between file2 and file1).
|
||||
void t3Callback();
|
|
@ -0,0 +1,20 @@
|
|||
//This is the only .cpp file that gets the #include<TaskScheduler.h>.
|
||||
//Without it, the linker would not find necessary TaskScheduler's compiled code.
|
||||
//
|
||||
//Remember to put customization macros here as well.
|
||||
//
|
||||
//And don't import any common headers (here: header.hpp)
|
||||
//
|
||||
//Really. This file needs to be short. All stuff is in TaskScheduler.h.
|
||||
|
||||
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
// #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
// #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
// #define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
// #define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
// #define _TASK_MICRO_RES // Support for microsecond resolution
|
||||
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 ONLY)
|
||||
// #define _TASK_DEBUG // Make all methods and variables public for debug purposes
|
||||
|
||||
#include <TaskScheduler.h>
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
This eaxmple illustrates the use of overall Task timeout functionality:
|
||||
|
||||
Task 1 - runs every 1 seconds and times out in 10 seconds
|
||||
Task 2 - runs every 5 seconds and resets the timeout every run, so runs continuosly even though the timeout is set to 10 seconds
|
||||
*/
|
||||
|
||||
|
||||
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
//#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
// #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
// #define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
// #define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
// #define _TASK_MICRO_RES // Support for microsecond resolution
|
||||
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 ONLY)
|
||||
// #define _TASK_DEBUG // Make all methods and variables public for debug purposes
|
||||
// #define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
|
||||
#define _TASK_TIMEOUT
|
||||
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
void task1Callback();
|
||||
void task1OnDisable();
|
||||
void task2Callback();
|
||||
void task2OnDisable();
|
||||
|
||||
Task t1(1 * TASK_SECOND, TASK_FOREVER, &task1Callback, &ts, false, NULL, &task1OnDisable);
|
||||
Task t2(5 * TASK_SECOND, TASK_FOREVER, &task2Callback, &ts, false, NULL, &task2OnDisable);
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("TaskScheduler Timeout example");
|
||||
Serial.println("=============================");
|
||||
|
||||
t1.setTimeout(10 * TASK_SECOND);
|
||||
t2.setTimeout(10 * TASK_SECOND);
|
||||
|
||||
ts.enableAll();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
ts.execute();
|
||||
}
|
||||
|
||||
|
||||
void task1Callback() {
|
||||
Serial.print("Task 1:\t");
|
||||
Serial.print(millis());
|
||||
Serial.print(": t/out=");
|
||||
Serial.print(t1.getTimeout());
|
||||
Serial.print("\tms until t/out=");
|
||||
Serial.println( t1.untilTimeout());
|
||||
|
||||
}
|
||||
void task1OnDisable() {
|
||||
if (t1.timedOut()) {
|
||||
Serial.println("Task 1 has timed out. Restarting");
|
||||
t1.setInterval(1 * TASK_SECOND);
|
||||
t1.setIterations(15);
|
||||
t1.setTimeout(TASK_NOTIMEOUT);
|
||||
t1.enable();
|
||||
}
|
||||
else {
|
||||
Serial.println("Task 1 has been disabled");
|
||||
}
|
||||
}
|
||||
|
||||
void task2Callback() {
|
||||
Serial.print("Task 2:\t");
|
||||
Serial.print(millis());
|
||||
Serial.print(": t/out=");
|
||||
Serial.print(t2.getTimeout());
|
||||
Serial.print("\tms until t/out=");
|
||||
Serial.println( t2.untilTimeout());
|
||||
t2.resetTimeout();
|
||||
}
|
||||
void task2OnDisable() {
|
||||
if (t2.timedOut()) {
|
||||
Serial.println("Task 2 has timed out");
|
||||
}
|
||||
else {
|
||||
Serial.println("Task 2 has been disabled");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
This is example 5 rewritten with Timeout, LTS and WDT functioanlity:
|
||||
- 1 second timeout is set for the main calculation task
|
||||
- LTS is used to address individual array elements for each sensor sinlce the callback code is shared
|
||||
- WDT is used to set the Task ID and use that as an index for array of distances (alternative to LTS)
|
||||
|
||||
Original description:
|
||||
====================
|
||||
This test emulates querying 3 sensors once every 10 seconds, each could respond with a different delay
|
||||
(ultrasonic sensors for instance) and printing a min value of the three when all three have reported their values.
|
||||
The overall timeout of 1 second is setup as well.
|
||||
An error message needs to be printed if a timeout occurred instead of a value.
|
||||
|
||||
Example5:
|
||||
Sketch uses 6066 bytes (18%) of program storage space. Maximum is 32256 bytes.
|
||||
Global variables use 1039 bytes (50%) of dynamic memory, leaving 1009 bytes for local variables. Maximum is 2048 bytes.
|
||||
Example 18:
|
||||
Sketch uses 5142 bytes (15%) of program storage space. Maximum is 32256 bytes.
|
||||
Global variables use 878 bytes (42%) of dynamic memory, leaving 1170 bytes for local variables. Maximum is 2048 bytes.
|
||||
*/
|
||||
|
||||
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
// #define _TASK_MICRO_RES // Support for microsecond resolution
|
||||
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 and ESP32 ONLY)
|
||||
#define _TASK_DEBUG // Make all methods and variables public for debug purposes
|
||||
#define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
StatusRequest measure;
|
||||
|
||||
Scheduler ts, hts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void CycleCallback();
|
||||
void CalcCallback();
|
||||
bool CalcEnable();
|
||||
void CalcDisable();
|
||||
void SCallback(); bool SEnable();
|
||||
|
||||
// Tasks
|
||||
Task tSensor1(0, TASK_ONCE, &SCallback, &ts, false, &SEnable); // task ID = 1
|
||||
Task tSensor2(0, TASK_ONCE, &SCallback, &ts, false, &SEnable); // task ID = 2
|
||||
Task tSensor3(0, TASK_ONCE, &SCallback, &ts, false, &SEnable); // task ID = 3
|
||||
|
||||
Task tCycle(10000, TASK_FOREVER, &CycleCallback, &hts);
|
||||
Task tCalculate(TASK_IMMEDIATE , TASK_ONCE, &CalcCallback, &hts, false, &CalcEnable, &CalcDisable);
|
||||
|
||||
#define NO_OF_SENSORS 3
|
||||
long distance, d[NO_OF_SENSORS + 1], d_lts[NO_OF_SENSORS]; // d[] will be populated via task ID used as array indexes, d_lts will be addressed via LTS pointers
|
||||
|
||||
void CycleCallback() {
|
||||
Serial.println();
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");
|
||||
|
||||
distance = 0;
|
||||
measure.setWaiting(NO_OF_SENSORS); // Set the StatusRequest to wait for 3 signals.
|
||||
tCalculate.waitFor(&measure);
|
||||
}
|
||||
|
||||
bool CalcEnable() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcEnable: OnEnable");
|
||||
Serial.println("Activating sensors and setting timeout");
|
||||
|
||||
tSensor1.restartDelayed();
|
||||
tSensor2.restartDelayed();
|
||||
tSensor3.restartDelayed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CalcDisable() {
|
||||
if (tCalculate.timedOut()) {
|
||||
measure.signalComplete(-1); // signal error
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("MeasureCallback: ***** Timeout *****");
|
||||
// tSensor1.disable();
|
||||
// tSensor2.disable();
|
||||
// tSensor3.disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CalcCallback() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcCallback: calculating");
|
||||
distance = -1;
|
||||
if ( measure.getStatus() >= 0) { // only calculate if statusrequest ended successfully
|
||||
distance = d[1] < d[2] ? d[1] : d[2];
|
||||
distance = d[3] < distance ? d[3] : distance;
|
||||
Serial.print("CalcCallback: Min distance="); Serial.println(distance);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Simulation code for all sensors
|
||||
-------------------------------
|
||||
*/
|
||||
bool SEnable() {
|
||||
Task &t = ts.currentTask();
|
||||
int i = t.getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SEnable: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Triggering sensor. Delay=");
|
||||
|
||||
t.setInterval( random(1200) ); // Simulating sensor delay, which could go over 1 second and cause timeout
|
||||
// One way to update the 3 distances with one codebase - use task id as an index
|
||||
d[i] = 0;
|
||||
|
||||
// Another way to update the 3 distances with one codebase - use LTS pointers
|
||||
int *pd = (int*) t.getLtsPointer();
|
||||
*pd = 0;
|
||||
|
||||
Serial.println( t.getInterval() );
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCallback() {
|
||||
Task &t = ts.currentTask();
|
||||
int i = t.getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SCallback: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Emulating measurement. d=");
|
||||
|
||||
d[i] = random(501); // pick a value from 0 to 500 "centimeters" simulating a measurement
|
||||
int *pd = (int*) t.getLtsPointer();
|
||||
*pd = d[i];
|
||||
|
||||
measure.signal();
|
||||
|
||||
Serial.print(d[i]);
|
||||
Serial.print("\t");
|
||||
Serial.println(*pd);
|
||||
}
|
||||
|
||||
/** Main Arduino code
|
||||
Not much is left here - everything is taken care of by the framework
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("TaskScheduler StatusRequest Sensor Emulation Test. Complex Test.");
|
||||
randomSeed(analogRead(A0) + millis());
|
||||
|
||||
tSensor1.setLtsPointer(&d_lts[0]);
|
||||
tSensor2.setLtsPointer(&d_lts[1]);
|
||||
tSensor3.setLtsPointer(&d_lts[2]);
|
||||
|
||||
ts.setHighPriorityScheduler(&hts);
|
||||
|
||||
tCalculate.setTimeout(1 * TASK_SECOND);
|
||||
tCycle.enable();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
ts.execute();
|
||||
|
||||
}
|
|
@ -0,0 +1,540 @@
|
|||
/**
|
||||
TaskScheduler Test sketch - test of Task destructor
|
||||
Test case:
|
||||
Main task runs every 100 milliseconds 100 times and in 50% cases generates a task object
|
||||
which runs 1 to 10 times with 100 ms to 5 s interval, and then destroyed.
|
||||
|
||||
This sketch uses a FreeMemory library: https://github.com/McNeight/MemoryFree
|
||||
*/
|
||||
|
||||
#define _TASK_WDT_IDS // To enable task unique IDs
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Compile with support for entering IDLE SLEEP state for 1 ms if not tasks are scheduled to run
|
||||
#define _TASK_LTS_POINTER // Compile with support for Local Task Storage pointer
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#include <MemoryFree.h>
|
||||
|
||||
Scheduler ts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void MainLoop();
|
||||
|
||||
// Statis task
|
||||
Task tMain(100*TASK_MILLISECOND, 100, MainLoop, &ts, true);
|
||||
|
||||
|
||||
void Iteration();
|
||||
bool OnEnable();
|
||||
void OnDisable();
|
||||
|
||||
int noOfTasks = 0;
|
||||
|
||||
void MainLoop() {
|
||||
Serial.print(millis()); Serial.print("\t");
|
||||
Serial.print("MainLoop run: ");
|
||||
int i = tMain.getRunCounter();
|
||||
Serial.print(i); Serial.print(F(".\t"));
|
||||
|
||||
if ( random(0, 101) > 50 ) { // generate a new task only in 50% of cases
|
||||
// Generating another task
|
||||
long p = random(100, 5001); // from 100 ms to 5 seconds
|
||||
long j = random(1, 11); // from 1 to 10 iterations)
|
||||
Task *t = new Task(p, j, Iteration, &ts, false, OnEnable, OnDisable);
|
||||
|
||||
Serial.print(F("Generated a new task:\t")); Serial.print(t->getId()); Serial.print(F("\tInt, Iter = \t"));
|
||||
Serial.print(p); Serial.print(", "); Serial.print(j); Serial.print(F("\tFree mem="));
|
||||
Serial.print(freeMemory()); Serial.print(F("\tNo of tasks=")); Serial.println(++noOfTasks);
|
||||
t->enable();
|
||||
}
|
||||
else {
|
||||
Serial.println(F("Skipped generating a task"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Iteration() {
|
||||
Task &t = ts.currentTask();
|
||||
|
||||
Serial.print(millis()); Serial.print("\t");
|
||||
Serial.print("Task N"); Serial.print(t.getId()); Serial.print(F("\tcurrent iteration: "));
|
||||
int i = t.getRunCounter();
|
||||
Serial.println(i);
|
||||
}
|
||||
|
||||
bool OnEnable() {
|
||||
// to-do: think of something to put in here.
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
Task *t = &ts.currentTask();
|
||||
unsigned int tid = t->getId();
|
||||
|
||||
delete t;
|
||||
Serial.print(millis()); Serial.print("\t");
|
||||
Serial.print("Task N"); Serial.print(tid); Serial.print(F("\tfinished and destroyed.\tFree mem="));
|
||||
Serial.print(freeMemory());Serial.print(F("\tNo of tasks=")); Serial.println(--noOfTasks);
|
||||
}
|
||||
|
||||
/**
|
||||
Standard Arduino setup and loop methods
|
||||
*/
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
randomSeed(analogRead(0) + analogRead(5));
|
||||
noOfTasks = 0;
|
||||
|
||||
Serial.println(F("Dynamic Task Creation/Destruction Example"));
|
||||
Serial.println();
|
||||
Serial.print(F("Free mem="));
|
||||
Serial.print(freeMemory()); Serial.print(F("\tNo of tasks=")); Serial.println(noOfTasks);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
||||
|
||||
|
||||
/* Output on Arduino Uno:
|
||||
*
|
||||
* Compile:
|
||||
|
||||
Sketch uses 5312 bytes (16%) of program storage space. Maximum is 32256 bytes.
|
||||
Global variables use 282 bytes (13%) of dynamic memory, leaving 1766 bytes for local variables. Maximum is 2048 bytes.
|
||||
|
||||
* Execution:
|
||||
|
||||
Dynamic Task Creation/Destruction Example
|
||||
|
||||
Free mem=1758 No of tasks=0
|
||||
|
||||
1 MainLoop run: 1. Generated a new task: 2 Int, Iter = 421, 3 Free mem=1701 No of tasks=1
|
||||
8 Task N2 current iteration: 1
|
||||
100 MainLoop run: 2. Generated a new task: 3 Int, Iter = 4099, 9 Free mem=1656 No of tasks=2
|
||||
102 Task N3 current iteration: 1
|
||||
200 MainLoop run: 3. Skipped generating a task
|
||||
300 MainLoop run: 4. Generated a new task: 4 Int, Iter = 1795, 1 Free mem=1611 No of tasks=3
|
||||
302 Task N4 current iteration: 1
|
||||
305 Task N4 finished and destroyed. Free mem=1613 No of tasks=2
|
||||
400 MainLoop run: 5. Skipped generating a task
|
||||
429 Task N2 current iteration: 2
|
||||
500 MainLoop run: 6. Skipped generating a task
|
||||
600 MainLoop run: 7. Skipped generating a task
|
||||
700 MainLoop run: 8. Generated a new task: 5 Int, Iter = 4623, 7 Free mem=1611 No of tasks=3
|
||||
702 Task N5 current iteration: 1
|
||||
800 MainLoop run: 9. Generated a new task: 6 Int, Iter = 4987, 4 Free mem=1566 No of tasks=4
|
||||
802 Task N6 current iteration: 1
|
||||
850 Task N2 current iteration: 3
|
||||
850 Task N2 finished and destroyed. Free mem=1568 No of tasks=3
|
||||
900 MainLoop run: 10. Generated a new task: 7 Int, Iter = 600, 4 Free mem=1566 No of tasks=4
|
||||
902 Task N7 current iteration: 1
|
||||
1000 MainLoop run: 11. Skipped generating a task
|
||||
1100 MainLoop run: 12. Generated a new task: 8 Int, Iter = 2530, 1 Free mem=1521 No of tasks=5
|
||||
1102 Task N8 current iteration: 1
|
||||
1105 Task N8 finished and destroyed. Free mem=1523 No of tasks=4
|
||||
1200 MainLoop run: 13. Skipped generating a task
|
||||
1300 MainLoop run: 14. Generated a new task: 9 Int, Iter = 2215, 7 Free mem=1521 No of tasks=5
|
||||
1302 Task N9 current iteration: 1
|
||||
1400 MainLoop run: 15. Skipped generating a task
|
||||
1500 MainLoop run: 16. Skipped generating a task
|
||||
1502 Task N7 current iteration: 2
|
||||
1600 MainLoop run: 17. Skipped generating a task
|
||||
1700 MainLoop run: 18. Skipped generating a task
|
||||
1800 MainLoop run: 19. Skipped generating a task
|
||||
1900 MainLoop run: 20. Skipped generating a task
|
||||
2000 MainLoop run: 21. Generated a new task: 10 Int, Iter = 189, 10 Free mem=1476 No of tasks=6
|
||||
2002 Task N10 current iteration: 1
|
||||
2100 MainLoop run: 22. Generated a new task: 11 Int, Iter = 2898, 9 Free mem=1431 No of tasks=7
|
||||
2102 Task N7 current iteration: 3
|
||||
2105 Task N11 current iteration: 1
|
||||
2191 Task N10 current iteration: 2
|
||||
2200 MainLoop run: 23. Generated a new task: 12 Int, Iter = 1691, 6 Free mem=1386 No of tasks=8
|
||||
2202 Task N12 current iteration: 1
|
||||
2300 MainLoop run: 24. Generated a new task: 13 Int, Iter = 1448, 7 Free mem=1341 No of tasks=9
|
||||
2304 Task N13 current iteration: 1
|
||||
2380 Task N10 current iteration: 3
|
||||
2400 MainLoop run: 25. Generated a new task: 14 Int, Iter = 3919, 7 Free mem=1296 No of tasks=10
|
||||
2403 Task N14 current iteration: 1
|
||||
2500 MainLoop run: 26. Generated a new task: 15 Int, Iter = 3745, 5 Free mem=1251 No of tasks=11
|
||||
2503 Task N15 current iteration: 1
|
||||
2569 Task N10 current iteration: 4
|
||||
2600 MainLoop run: 27. Skipped generating a task
|
||||
2700 MainLoop run: 28. Skipped generating a task
|
||||
2702 Task N7 current iteration: 4
|
||||
2702 Task N7 finished and destroyed. Free mem=1253 No of tasks=10
|
||||
2758 Task N10 current iteration: 5
|
||||
2800 MainLoop run: 29. Generated a new task: 16 Int, Iter = 2144, 1 Free mem=1251 No of tasks=11
|
||||
2803 Task N16 current iteration: 1
|
||||
2806 Task N16 finished and destroyed. Free mem=1253 No of tasks=10
|
||||
2900 MainLoop run: 30. Generated a new task: 17 Int, Iter = 4618, 10 Free mem=1251 No of tasks=11
|
||||
2904 Task N17 current iteration: 1
|
||||
2947 Task N10 current iteration: 6
|
||||
3000 MainLoop run: 31. Skipped generating a task
|
||||
3100 MainLoop run: 32. Generated a new task: 18 Int, Iter = 2885, 6 Free mem=1206 No of tasks=12
|
||||
3103 Task N18 current iteration: 1
|
||||
3136 Task N10 current iteration: 7
|
||||
3200 MainLoop run: 33. Skipped generating a task
|
||||
3300 MainLoop run: 34. Skipped generating a task
|
||||
3325 Task N10 current iteration: 8
|
||||
3400 MainLoop run: 35. Skipped generating a task
|
||||
3500 MainLoop run: 36. Generated a new task: 19 Int, Iter = 2250, 4 Free mem=1161 No of tasks=13
|
||||
3503 Task N19 current iteration: 1
|
||||
3514 Task N10 current iteration: 9
|
||||
3518 Task N9 current iteration: 2
|
||||
3600 MainLoop run: 37. Skipped generating a task
|
||||
3700 MainLoop run: 38. Generated a new task: 20 Int, Iter = 1689, 7 Free mem=1116 No of tasks=14
|
||||
3703 Task N10 current iteration: 10
|
||||
3706 Task N20 current iteration: 1
|
||||
3709 Task N10 finished and destroyed. Free mem=1118 No of tasks=13
|
||||
3750 Task N13 current iteration: 2
|
||||
3800 MainLoop run: 39. Generated a new task: 21 Int, Iter = 2607, 5 Free mem=1116 No of tasks=14
|
||||
3803 Task N21 current iteration: 1
|
||||
3893 Task N12 current iteration: 2
|
||||
3900 MainLoop run: 40. Generated a new task: 22 Int, Iter = 1390, 6 Free mem=1071 No of tasks=15
|
||||
3903 Task N22 current iteration: 1
|
||||
4000 MainLoop run: 41. Generated a new task: 23 Int, Iter = 3340, 8 Free mem=1026 No of tasks=16
|
||||
4003 Task N23 current iteration: 1
|
||||
4100 MainLoop run: 42. Skipped generating a task
|
||||
4200 MainLoop run: 43. Skipped generating a task
|
||||
4201 Task N3 current iteration: 2
|
||||
4300 MainLoop run: 44. Skipped generating a task
|
||||
4400 MainLoop run: 45. Generated a new task: 24 Int, Iter = 4083, 2 Free mem=981 No of tasks=17
|
||||
4403 Task N24 current iteration: 1
|
||||
4500 MainLoop run: 46. Generated a new task: 25 Int, Iter = 4510, 1 Free mem=936 No of tasks=18
|
||||
4503 Task N25 current iteration: 1
|
||||
4506 Task N25 finished and destroyed. Free mem=938 No of tasks=17
|
||||
4600 MainLoop run: 47. Generated a new task: 26 Int, Iter = 4782, 10 Free mem=936 No of tasks=18
|
||||
4603 Task N26 current iteration: 1
|
||||
4700 MainLoop run: 48. Generated a new task: 27 Int, Iter = 641, 6 Free mem=891 No of tasks=19
|
||||
4702 Task N27 current iteration: 1
|
||||
4800 MainLoop run: 49. Generated a new task: 28 Int, Iter = 695, 5 Free mem=846 No of tasks=20
|
||||
4802 Task N28 current iteration: 1
|
||||
4900 MainLoop run: 50. Generated a new task: 29 Int, Iter = 3520, 3 Free mem=801 No of tasks=21
|
||||
4903 Task N29 current iteration: 1
|
||||
5000 MainLoop run: 51. Generated a new task: 30 Int, Iter = 3091, 9 Free mem=756 No of tasks=22
|
||||
5002 Task N11 current iteration: 2
|
||||
5006 Task N30 current iteration: 1
|
||||
5100 MainLoop run: 52. Skipped generating a task
|
||||
5198 Task N13 current iteration: 3
|
||||
5200 MainLoop run: 53. Skipped generating a task
|
||||
5293 Task N22 current iteration: 2
|
||||
5300 MainLoop run: 54. Generated a new task: 31 Int, Iter = 4359, 9 Free mem=711 No of tasks=23
|
||||
5303 Task N31 current iteration: 1
|
||||
5325 Task N5 current iteration: 2
|
||||
5343 Task N27 current iteration: 2
|
||||
5392 Task N20 current iteration: 2
|
||||
5400 MainLoop run: 55. Generated a new task: 32 Int, Iter = 837, 4 Free mem=666 No of tasks=24
|
||||
5403 Task N32 current iteration: 1
|
||||
5497 Task N28 current iteration: 2
|
||||
5501 MainLoop run: 56. Generated a new task: 33 Int, Iter = 274, 8 Free mem=621 No of tasks=25
|
||||
5505 Task N33 current iteration: 1
|
||||
5584 Task N12 current iteration: 3
|
||||
5600 MainLoop run: 57. Generated a new task: 34 Int, Iter = 923, 7 Free mem=576 No of tasks=26
|
||||
5603 Task N34 current iteration: 1
|
||||
5700 MainLoop run: 58. Generated a new task: 35 Int, Iter = 1007, 8 Free mem=531 No of tasks=27
|
||||
5703 Task N35 current iteration: 1
|
||||
5732 Task N9 current iteration: 3
|
||||
5753 Task N19 current iteration: 2
|
||||
5778 Task N33 current iteration: 2
|
||||
5789 Task N6 current iteration: 2
|
||||
5800 MainLoop run: 59. Skipped generating a task
|
||||
5900 MainLoop run: 60. Generated a new task: 36 Int, Iter = 608, 4 Free mem=486 No of tasks=28
|
||||
5903 Task N36 current iteration: 1
|
||||
5984 Task N27 current iteration: 3
|
||||
5988 Task N18 current iteration: 2
|
||||
6000 MainLoop run: 61. Generated a new task: 37 Int, Iter = 4043, 3 Free mem=441 No of tasks=29
|
||||
6003 Task N37 current iteration: 1
|
||||
6052 Task N33 current iteration: 3
|
||||
6100 MainLoop run: 62. Skipped generating a task
|
||||
6192 Task N28 current iteration: 3
|
||||
6200 MainLoop run: 63. Skipped generating a task
|
||||
6239 Task N32 current iteration: 2
|
||||
6248 Task N15 current iteration: 2
|
||||
6300 MainLoop run: 64. Skipped generating a task
|
||||
6322 Task N14 current iteration: 2
|
||||
6326 Task N33 current iteration: 4
|
||||
6400 MainLoop run: 65. Skipped generating a task
|
||||
6410 Task N21 current iteration: 2
|
||||
6500 MainLoop run: 66. Skipped generating a task
|
||||
6510 Task N36 current iteration: 2
|
||||
6525 Task N34 current iteration: 2
|
||||
6600 MainLoop run: 67. Skipped generating a task
|
||||
6600 Task N33 current iteration: 5
|
||||
6625 Task N27 current iteration: 4
|
||||
6646 Task N13 current iteration: 4
|
||||
6683 Task N22 current iteration: 3
|
||||
6700 MainLoop run: 68. Generated a new task: 38 Int, Iter = 1907, 9 Free mem=396 No of tasks=30
|
||||
6703 Task N38 current iteration: 1
|
||||
6709 Task N35 current iteration: 2
|
||||
6800 MainLoop run: 69. Skipped generating a task
|
||||
6874 Task N33 current iteration: 6
|
||||
6887 Task N28 current iteration: 4
|
||||
6900 MainLoop run: 70. Generated a new task: 39 Int, Iter = 2697, 1 Free mem=351 No of tasks=31
|
||||
6903 Task N39 current iteration: 1
|
||||
6906 Task N39 finished and destroyed. Free mem=353 No of tasks=30
|
||||
7000 MainLoop run: 71. Generated a new task: 40 Int, Iter = 2849, 4 Free mem=351 No of tasks=31
|
||||
7003 Task N40 current iteration: 1
|
||||
7076 Task N32 current iteration: 3
|
||||
7081 Task N20 current iteration: 3
|
||||
7100 MainLoop run: 72. Skipped generating a task
|
||||
7118 Task N36 current iteration: 3
|
||||
7148 Task N33 current iteration: 7
|
||||
7200 MainLoop run: 73. Skipped generating a task
|
||||
7266 Task N27 current iteration: 5
|
||||
7275 Task N12 current iteration: 4
|
||||
7300 MainLoop run: 74. Generated a new task: 41 Int, Iter = 4466, 4 Free mem=306 No of tasks=32
|
||||
7303 Task N41 current iteration: 1
|
||||
7343 Task N23 current iteration: 2
|
||||
7400 MainLoop run: 75. Skipped generating a task
|
||||
7422 Task N33 current iteration: 8
|
||||
7422 Task N33 finished and destroyed. Free mem=308 No of tasks=31
|
||||
7448 Task N34 current iteration: 3
|
||||
7500 MainLoop run: 76. Generated a new task: 42 Int, Iter = 2133, 3 Free mem=306 No of tasks=32
|
||||
7503 Task N42 current iteration: 1
|
||||
7522 Task N17 current iteration: 2
|
||||
7582 Task N28 current iteration: 5
|
||||
7582 Task N28 finished and destroyed. Free mem=308 No of tasks=31
|
||||
7600 MainLoop run: 77. Skipped generating a task
|
||||
7700 MainLoop run: 78. Skipped generating a task
|
||||
7716 Task N35 current iteration: 3
|
||||
7726 Task N36 current iteration: 4
|
||||
7726 Task N36 finished and destroyed. Free mem=353 No of tasks=30
|
||||
7800 MainLoop run: 79. Generated a new task: 43 Int, Iter = 4113, 6 Free mem=351 No of tasks=31
|
||||
7803 Task N43 current iteration: 1
|
||||
7898 Task N11 current iteration: 3
|
||||
7900 MainLoop run: 80. Skipped generating a task
|
||||
7907 Task N27 current iteration: 6
|
||||
7907 Task N27 finished and destroyed. Free mem=353 No of tasks=30
|
||||
7913 Task N32 current iteration: 4
|
||||
7913 Task N32 finished and destroyed. Free mem=398 No of tasks=29
|
||||
7947 Task N9 current iteration: 4
|
||||
8000 MainLoop run: 81. Skipped generating a task
|
||||
8003 Task N19 current iteration: 3
|
||||
8073 Task N22 current iteration: 4
|
||||
8093 Task N30 current iteration: 2
|
||||
8094 Task N13 current iteration: 5
|
||||
8100 MainLoop run: 82. Skipped generating a task
|
||||
8200 MainLoop run: 83. Generated a new task: 44 Int, Iter = 3389, 1 Free mem=396 No of tasks=30
|
||||
8203 Task N44 current iteration: 1
|
||||
8206 Task N44 finished and destroyed. Free mem=398 No of tasks=29
|
||||
8300 MainLoop run: 84. Generated a new task: 45 Int, Iter = 3548, 10 Free mem=396 No of tasks=30
|
||||
8303 Task N3 current iteration: 3
|
||||
8306 Task N45 current iteration: 1
|
||||
8371 Task N34 current iteration: 4
|
||||
8400 MainLoop run: 85. Skipped generating a task
|
||||
8422 Task N29 current iteration: 2
|
||||
8485 Task N24 current iteration: 2
|
||||
8485 Task N24 finished and destroyed. Free mem=398 No of tasks=29
|
||||
8500 MainLoop run: 86. Generated a new task: 46 Int, Iter = 4962, 2 Free mem=396 No of tasks=30
|
||||
8503 Task N46 current iteration: 1
|
||||
8600 MainLoop run: 87. Skipped generating a task
|
||||
8609 Task N38 current iteration: 2
|
||||
8700 MainLoop run: 88. Skipped generating a task
|
||||
8723 Task N35 current iteration: 4
|
||||
8770 Task N20 current iteration: 4
|
||||
8800 MainLoop run: 89. Skipped generating a task
|
||||
8873 Task N18 current iteration: 3
|
||||
8900 MainLoop run: 90. Skipped generating a task
|
||||
8966 Task N12 current iteration: 5
|
||||
9000 MainLoop run: 91. Skipped generating a task
|
||||
9017 Task N21 current iteration: 3
|
||||
9100 MainLoop run: 92. Skipped generating a task
|
||||
9200 MainLoop run: 93. Skipped generating a task
|
||||
9294 Task N34 current iteration: 5
|
||||
9300 MainLoop run: 94. Skipped generating a task
|
||||
9385 Task N26 current iteration: 2
|
||||
9400 MainLoop run: 95. Generated a new task: 47 Int, Iter = 3556, 9 Free mem=351 No of tasks=31
|
||||
9403 Task N47 current iteration: 1
|
||||
9463 Task N22 current iteration: 5
|
||||
9500 MainLoop run: 96. Generated a new task: 48 Int, Iter = 1226, 3 Free mem=306 No of tasks=32
|
||||
9503 Task N48 current iteration: 1
|
||||
9542 Task N13 current iteration: 6
|
||||
9600 MainLoop run: 97. Generated a new task: 49 Int, Iter = 2850, 9 Free mem=261 No of tasks=33
|
||||
9603 Task N49 current iteration: 1
|
||||
9635 Task N42 current iteration: 2
|
||||
9661 Task N31 current iteration: 2
|
||||
9700 MainLoop run: 98. Skipped generating a task
|
||||
9730 Task N35 current iteration: 5
|
||||
9800 MainLoop run: 99. Generated a new task: 50 Int, Iter = 2782, 10 Free mem=216 No of tasks=34
|
||||
9803 Task N50 current iteration: 1
|
||||
9851 Task N40 current iteration: 2
|
||||
9900 MainLoop run: 100. Skipped generating a task
|
||||
9948 Task N5 current iteration: 3
|
||||
9993 Task N15 current iteration: 3
|
||||
10045 Task N37 current iteration: 2
|
||||
10162 Task N9 current iteration: 5
|
||||
10217 Task N34 current iteration: 6
|
||||
10241 Task N14 current iteration: 3
|
||||
10253 Task N19 current iteration: 4
|
||||
10253 Task N19 finished and destroyed. Free mem=218 No of tasks=33
|
||||
10459 Task N20 current iteration: 5
|
||||
10516 Task N38 current iteration: 3
|
||||
10657 Task N12 current iteration: 6
|
||||
10657 Task N12 finished and destroyed. Free mem=263 No of tasks=32
|
||||
10683 Task N23 current iteration: 3
|
||||
10728 Task N48 current iteration: 2
|
||||
10737 Task N35 current iteration: 6
|
||||
10776 Task N6 current iteration: 3
|
||||
10796 Task N11 current iteration: 4
|
||||
10853 Task N22 current iteration: 6
|
||||
10853 Task N22 finished and destroyed. Free mem=308 No of tasks=31
|
||||
10990 Task N13 current iteration: 7
|
||||
10990 Task N13 finished and destroyed. Free mem=353 No of tasks=30
|
||||
11140 Task N34 current iteration: 7
|
||||
11140 Task N34 finished and destroyed. Free mem=398 No of tasks=29
|
||||
11184 Task N30 current iteration: 3
|
||||
11624 Task N21 current iteration: 4
|
||||
11744 Task N35 current iteration: 7
|
||||
11758 Task N18 current iteration: 4
|
||||
11768 Task N41 current iteration: 2
|
||||
11768 Task N42 current iteration: 3
|
||||
11769 Task N42 finished and destroyed. Free mem=443 No of tasks=28
|
||||
11851 Task N45 current iteration: 2
|
||||
11915 Task N43 current iteration: 2
|
||||
11942 Task N29 current iteration: 3
|
||||
11942 Task N29 finished and destroyed. Free mem=488 No of tasks=27
|
||||
11954 Task N48 current iteration: 3
|
||||
11954 Task N48 finished and destroyed. Free mem=533 No of tasks=26
|
||||
12140 Task N17 current iteration: 3
|
||||
12148 Task N20 current iteration: 6
|
||||
12377 Task N9 current iteration: 6
|
||||
12399 Task N3 current iteration: 4
|
||||
12423 Task N38 current iteration: 4
|
||||
12452 Task N49 current iteration: 2
|
||||
12585 Task N50 current iteration: 2
|
||||
12700 Task N40 current iteration: 3
|
||||
12751 Task N35 current iteration: 8
|
||||
12751 Task N35 finished and destroyed. Free mem=578 No of tasks=25
|
||||
12958 Task N47 current iteration: 2
|
||||
13464 Task N46 current iteration: 2
|
||||
13464 Task N46 finished and destroyed. Free mem=623 No of tasks=24
|
||||
13694 Task N11 current iteration: 5
|
||||
13739 Task N15 current iteration: 4
|
||||
13837 Task N20 current iteration: 7
|
||||
13837 Task N20 finished and destroyed. Free mem=668 No of tasks=23
|
||||
14020 Task N31 current iteration: 3
|
||||
14023 Task N23 current iteration: 4
|
||||
14088 Task N37 current iteration: 3
|
||||
14088 Task N37 finished and destroyed. Free mem=713 No of tasks=22
|
||||
14160 Task N14 current iteration: 4
|
||||
14167 Task N26 current iteration: 3
|
||||
14231 Task N21 current iteration: 5
|
||||
14231 Task N21 finished and destroyed. Free mem=758 No of tasks=21
|
||||
14275 Task N30 current iteration: 4
|
||||
14330 Task N38 current iteration: 5
|
||||
14571 Task N5 current iteration: 4
|
||||
14592 Task N9 current iteration: 7
|
||||
14592 Task N9 finished and destroyed. Free mem=803 No of tasks=20
|
||||
14643 Task N18 current iteration: 5
|
||||
15302 Task N49 current iteration: 3
|
||||
15367 Task N50 current iteration: 3
|
||||
15399 Task N45 current iteration: 3
|
||||
15549 Task N40 current iteration: 4
|
||||
15549 Task N40 finished and destroyed. Free mem=848 No of tasks=19
|
||||
15763 Task N6 current iteration: 4
|
||||
15763 Task N6 finished and destroyed. Free mem=893 No of tasks=18
|
||||
16028 Task N43 current iteration: 3
|
||||
16234 Task N41 current iteration: 3
|
||||
16237 Task N38 current iteration: 6
|
||||
16498 Task N3 current iteration: 5
|
||||
16514 Task N47 current iteration: 3
|
||||
16592 Task N11 current iteration: 6
|
||||
16758 Task N17 current iteration: 4
|
||||
17363 Task N23 current iteration: 5
|
||||
17366 Task N30 current iteration: 5
|
||||
17483 Task N15 current iteration: 5
|
||||
17483 Task N15 finished and destroyed. Free mem=938 No of tasks=17
|
||||
17528 Task N18 current iteration: 6
|
||||
17528 Task N18 finished and destroyed. Free mem=983 No of tasks=16
|
||||
18079 Task N14 current iteration: 5
|
||||
18144 Task N38 current iteration: 7
|
||||
18149 Task N50 current iteration: 4
|
||||
18152 Task N49 current iteration: 4
|
||||
18379 Task N31 current iteration: 4
|
||||
18947 Task N45 current iteration: 4
|
||||
18949 Task N26 current iteration: 4
|
||||
19194 Task N5 current iteration: 5
|
||||
19490 Task N11 current iteration: 7
|
||||
20051 Task N38 current iteration: 8
|
||||
20070 Task N47 current iteration: 4
|
||||
20141 Task N43 current iteration: 4
|
||||
20457 Task N30 current iteration: 6
|
||||
20597 Task N3 current iteration: 6
|
||||
20700 Task N41 current iteration: 4
|
||||
20700 Task N41 finished and destroyed. Free mem=1028 No of tasks=15
|
||||
20703 Task N23 current iteration: 6
|
||||
20931 Task N50 current iteration: 5
|
||||
21002 Task N49 current iteration: 5
|
||||
21376 Task N17 current iteration: 5
|
||||
21958 Task N38 current iteration: 9
|
||||
21958 Task N38 finished and destroyed. Free mem=1073 No of tasks=14
|
||||
21998 Task N14 current iteration: 6
|
||||
22388 Task N11 current iteration: 8
|
||||
22495 Task N45 current iteration: 5
|
||||
22738 Task N31 current iteration: 5
|
||||
23548 Task N30 current iteration: 7
|
||||
23626 Task N47 current iteration: 5
|
||||
23713 Task N50 current iteration: 6
|
||||
23731 Task N26 current iteration: 5
|
||||
23817 Task N5 current iteration: 6
|
||||
23852 Task N49 current iteration: 6
|
||||
24043 Task N23 current iteration: 7
|
||||
24254 Task N43 current iteration: 5
|
||||
24696 Task N3 current iteration: 7
|
||||
25286 Task N11 current iteration: 9
|
||||
25286 Task N11 finished and destroyed. Free mem=1118 No of tasks=13
|
||||
25917 Task N14 current iteration: 7
|
||||
25917 Task N14 finished and destroyed. Free mem=1163 No of tasks=12
|
||||
25994 Task N17 current iteration: 6
|
||||
26043 Task N45 current iteration: 6
|
||||
26496 Task N50 current iteration: 7
|
||||
26639 Task N30 current iteration: 8
|
||||
26702 Task N49 current iteration: 7
|
||||
27097 Task N31 current iteration: 6
|
||||
27182 Task N47 current iteration: 6
|
||||
27383 Task N23 current iteration: 8
|
||||
27383 Task N23 finished and destroyed. Free mem=1208 No of tasks=11
|
||||
28367 Task N43 current iteration: 6
|
||||
28367 Task N43 finished and destroyed. Free mem=1253 No of tasks=10
|
||||
28440 Task N5 current iteration: 7
|
||||
28440 Task N5 finished and destroyed. Free mem=1298 No of tasks=9
|
||||
28513 Task N26 current iteration: 6
|
||||
28795 Task N3 current iteration: 8
|
||||
29277 Task N50 current iteration: 8
|
||||
29552 Task N49 current iteration: 8
|
||||
29591 Task N45 current iteration: 7
|
||||
29730 Task N30 current iteration: 9
|
||||
29730 Task N30 finished and destroyed. Free mem=1343 No of tasks=8
|
||||
30612 Task N17 current iteration: 7
|
||||
30738 Task N47 current iteration: 7
|
||||
31456 Task N31 current iteration: 7
|
||||
32059 Task N50 current iteration: 9
|
||||
32402 Task N49 current iteration: 9
|
||||
32402 Task N49 finished and destroyed. Free mem=1388 No of tasks=7
|
||||
32894 Task N3 current iteration: 9
|
||||
32894 Task N3 finished and destroyed. Free mem=1433 No of tasks=6
|
||||
33139 Task N45 current iteration: 8
|
||||
33295 Task N26 current iteration: 7
|
||||
34294 Task N47 current iteration: 8
|
||||
34841 Task N50 current iteration: 10
|
||||
34841 Task N50 finished and destroyed. Free mem=1478 No of tasks=5
|
||||
35230 Task N17 current iteration: 8
|
||||
35815 Task N31 current iteration: 8
|
||||
36687 Task N45 current iteration: 9
|
||||
37850 Task N47 current iteration: 9
|
||||
37850 Task N47 finished and destroyed. Free mem=1523 No of tasks=4
|
||||
38077 Task N26 current iteration: 8
|
||||
39848 Task N17 current iteration: 9
|
||||
40174 Task N31 current iteration: 9
|
||||
40174 Task N31 finished and destroyed. Free mem=1568 No of tasks=3
|
||||
40235 Task N45 current iteration: 10
|
||||
40235 Task N45 finished and destroyed. Free mem=1613 No of tasks=2
|
||||
42859 Task N26 current iteration: 9
|
||||
44466 Task N17 current iteration: 10
|
||||
44466 Task N17 finished and destroyed. Free mem=1658 No of tasks=1
|
||||
47641 Task N26 current iteration: 10
|
||||
47641 Task N26 finished and destroyed. Free mem=1703 No of tasks=0
|
||||
|
||||
*/
|
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
This is example 5 rewritten with Timeout, LTS, WDT functioanlity + multitab and extra classes
|
||||
- 1 second timeout is set for the main calculation task
|
||||
- LTS is used to address task-specific sensor class object
|
||||
- WDT is used to set the Task ID and use that for identifying the tasks (debug)
|
||||
|
||||
Original description:
|
||||
====================
|
||||
This test emulates querying 1 to 10 sensors once every 10 seconds, each could respond with a different delay
|
||||
(ultrasonic sensors for instance) and printing a max value of them when all have reported their values.
|
||||
The overall timeout of 1 second is setup as well.
|
||||
An error message needs to be printed if a timeout occurred instead of a distance value.
|
||||
|
||||
Task and SuperSensor objects are dynamically created and destroyed as needed every 10 seconds
|
||||
*/
|
||||
|
||||
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
// #define _TASK_MICRO_RES // Support for microsecond resolution
|
||||
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 and ESP32 ONLY)
|
||||
#define _TASK_DEBUG // Make all methods and variables public for debug purposes
|
||||
#define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
|
||||
#include <TaskScheduler.h>
|
||||
#include "SuperSensor.h"
|
||||
|
||||
StatusRequest measure;
|
||||
|
||||
Scheduler ts, hts;
|
||||
|
||||
// Callback methods prototypes
|
||||
void CycleCallback();
|
||||
void CalcCallback();
|
||||
bool CalcEnable();
|
||||
void CalcDisable();
|
||||
void SCallback();
|
||||
bool SEnable();
|
||||
void SDisable();
|
||||
|
||||
// Tasks
|
||||
|
||||
Task tCycle(10000, TASK_FOREVER, &CycleCallback, &hts);
|
||||
Task tCalculate(TASK_IMMEDIATE , TASK_ONCE, &CalcCallback, &hts, false, &CalcEnable, &CalcDisable);
|
||||
|
||||
int numberSensors;
|
||||
long distance;
|
||||
int pins[] = { 1, 9, 3, 7, 5, 6, 4, 8, 2, 10 };
|
||||
|
||||
void CycleCallback() {
|
||||
Serial.println();Serial.println();Serial.println();
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");
|
||||
Serial.print("Number of sensors=");
|
||||
|
||||
numberSensors = random(1, 11); // 1 to 10 sensors, randomly
|
||||
distance = 0;
|
||||
Serial.println(numberSensors);
|
||||
|
||||
measure.setWaiting(numberSensors); // Set the StatusRequest to wait for 3 signals.
|
||||
tCalculate.waitFor(&measure);
|
||||
tCalculate.setTimeout(1000 * TASK_MILLISECOND);
|
||||
}
|
||||
|
||||
bool CalcEnable() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcEnable: OnEnable");
|
||||
Serial.println("Activating sensors");
|
||||
|
||||
|
||||
for (int i = 0; i < numberSensors; i++) {
|
||||
Task *t = new Task(TASK_MILLISECOND, TASK_FOREVER, &SCallback, &ts, false, &SEnable, &SDisable);
|
||||
SuperSensor *s = new SuperSensor( pins[i] );
|
||||
t->setLtsPointer( (void*) s);
|
||||
t->setId(i + 1);
|
||||
|
||||
s->begin();
|
||||
|
||||
t->restartDelayed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CalcDisable() {
|
||||
if (tCalculate.timedOut()) {
|
||||
measure.signalComplete(-1); // signal error
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("MeasureCallback: ***** Timeout *****");
|
||||
}
|
||||
ts.disableAll(false); // only disable tasks in the ts scheduler
|
||||
}
|
||||
|
||||
|
||||
void CalcCallback() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcCallback: calculating");
|
||||
if ( measure.getStatus() >= 0) { // only calculate if statusrequest ended successfully
|
||||
Serial.print("CalcCallback: Max distance="); Serial.println(distance);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Simulation code for all sensors
|
||||
-------------------------------
|
||||
*/
|
||||
bool SEnable() {
|
||||
Task &t = ts.currentTask();
|
||||
int i = t.getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SEnable: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Triggering sensor. Delay=");
|
||||
|
||||
|
||||
// Another way to update the distances with one codebase - use LTS pointers
|
||||
SuperSensor *s = (SuperSensor*) t.getLtsPointer();
|
||||
|
||||
long dly = s->trigger();
|
||||
|
||||
|
||||
Serial.println( dly );
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCallback() {
|
||||
Task &t = ts.currentTask();
|
||||
|
||||
SuperSensor *s = (SuperSensor*) t.getLtsPointer();
|
||||
if ( s->measurementReady() ) {
|
||||
int i = t.getId();
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SCallback: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Emulating measurement. d=");
|
||||
|
||||
long d = s->value();
|
||||
if ( d > distance ) distance = d;
|
||||
|
||||
Serial.println(d);
|
||||
|
||||
measure.signal();
|
||||
t.disable();
|
||||
}
|
||||
}
|
||||
|
||||
void SDisable() {
|
||||
Task &t = ts.currentTask();
|
||||
int i = t.getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SDisable: TaskID=");
|
||||
Serial.println(i);
|
||||
|
||||
SuperSensor *s = (SuperSensor*) ts.currentLts();
|
||||
s->stop();
|
||||
|
||||
delete s;
|
||||
delete &t;
|
||||
}
|
||||
|
||||
/** Main Arduino code
|
||||
Not much is left here - everything is taken care of by the framework
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("TaskScheduler StatusRequest Sensor Emulation Test. Complex Test.");
|
||||
randomSeed(analogRead(A0) + millis());
|
||||
|
||||
ts.setHighPriorityScheduler(&hts);
|
||||
|
||||
tCalculate.setTimeout(1 * TASK_SECOND);
|
||||
tCycle.enable();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#include "SuperSensor.h"
|
||||
|
||||
SuperSensor::SuperSensor(int aPin) {
|
||||
iPin = aPin;
|
||||
}
|
||||
|
||||
SuperSensor::~SuperSensor() {
|
||||
iValue = -1;
|
||||
}
|
||||
|
||||
void SuperSensor::begin() {
|
||||
iDelay = random(300, 1500);
|
||||
iValue = -1;
|
||||
}
|
||||
|
||||
void SuperSensor::stop() {
|
||||
//nothing to do
|
||||
}
|
||||
|
||||
long SuperSensor::trigger() {
|
||||
iStart = millis();
|
||||
return iDelay;
|
||||
}
|
||||
|
||||
bool SuperSensor::measurementReady() {
|
||||
if ( millis() - iStart > iDelay ) {
|
||||
iValue = random(501);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long SuperSensor::value() {
|
||||
return iValue;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _SUPER_SENSOR_H
|
||||
#define _SUPER_SENSOR_H
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
|
||||
class SuperSensor {
|
||||
public:
|
||||
SuperSensor(int aPin);
|
||||
~SuperSensor();
|
||||
void begin();
|
||||
void stop();
|
||||
long trigger();
|
||||
bool measurementReady();
|
||||
long value();
|
||||
|
||||
private:
|
||||
long iDelay;
|
||||
long iValue;
|
||||
int iPin;
|
||||
unsigned long iStart;
|
||||
};
|
||||
|
||||
#endif // _SUPER_SENSOR_H
|
|
@ -0,0 +1,66 @@
|
|||
#include "Calculator.h"
|
||||
#include "SuperSensor.h"
|
||||
|
||||
#if defined (ARDUINO_ARCH_AVR)
|
||||
#include <MemoryFree.h>
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
extern "C" char* sbrk(int incr);
|
||||
static int freeMemory() {
|
||||
char top = 't';
|
||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||
}
|
||||
|
||||
#endif
|
||||
Calculator::Calculator( Scheduler* aS, Scheduler* aSensors) : Task(aS) {
|
||||
iS = aSensors;
|
||||
setTimeout(1000 * TASK_MILLISECOND);
|
||||
}
|
||||
|
||||
bool Calculator::Callback() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcCallback: calculating");
|
||||
if ( getStatusRequest()->getStatus() >= 0) { // only calculate if statusrequest ended successfully
|
||||
Serial.print("CalcCallback: Max distance="); Serial.println(distance);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern int pins[];
|
||||
|
||||
bool Calculator::OnEnable() {
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CalcEnable: OnEnable");
|
||||
Serial.println("Activating sensors");
|
||||
|
||||
StatusRequest* sr = getStatusRequest();
|
||||
iNS = sr->getCount();
|
||||
|
||||
distance = 0;
|
||||
for (int i = 0; i < iNS; i++) {
|
||||
SuperSensor *s = new SuperSensor( iS, pins[i], this, sr);
|
||||
s->setId(i + 1);
|
||||
s->begin();
|
||||
s->restartDelayed();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Calculator::OnDisable() {
|
||||
if ( timedOut() ) {
|
||||
getStatusRequest()->signalComplete(-1); // signal error
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("MeasureCallback: ***** Timeout *****");
|
||||
}
|
||||
iS->disableAll(false); // only disable tasks in the ts scheduler
|
||||
#if defined (ARDUINO_ARCH_AVR) || defined(__arm__)
|
||||
Serial.print("Free mem = "); Serial.println(freeMemory()); Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Calculator::reportDistance(long aD) {
|
||||
if (distance < aD) distance = aD;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef _CALCULATOR_H
|
||||
#define _CALCULATOR_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
#define _TASK_OO_CALLBACKS // Support for dynamic callback method binding
|
||||
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
|
||||
class Calculator : public Task {
|
||||
public:
|
||||
Calculator( Scheduler* aS, Scheduler* aSensors);
|
||||
|
||||
void reportDistance(long aD);
|
||||
|
||||
bool Callback();
|
||||
bool OnEnable();
|
||||
void OnDisable();
|
||||
|
||||
private:
|
||||
Scheduler* iS;
|
||||
|
||||
long distance;
|
||||
int iNS;
|
||||
|
||||
};
|
||||
|
||||
#endif // _CALCULATOR_H
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
This is example 5 rewritten with dynamic binding of callback methods
|
||||
- 1 second timeout is set for the main calculation task
|
||||
- LTS is used to address task-specific sensor class object
|
||||
- WDT is used to set the Task ID and use that for identifying the tasks (debug)
|
||||
|
||||
Original description:
|
||||
====================
|
||||
This test emulates querying 1 to 10 sensors once every 10 seconds, each could respond with a different delay
|
||||
(ultrasonic sensors for instance) and printing a max value of them when all have reported their values.
|
||||
The overall timeout of 1 second is setup as well.
|
||||
An error message needs to be printed if a timeout occurred instead of a distance value.
|
||||
|
||||
Task and SuperSensor objects are dynamically created and destroyed as needed every 10 seconds
|
||||
|
||||
This sketch uses a FreeMemory library: https://github.com/McNeight/MemoryFree
|
||||
FreeMemory for ARM32 boards is based on: http://www.stm32duino.com/viewtopic.php?f=18&t=2065
|
||||
*/
|
||||
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
#define _TASK_OO_CALLBACKS
|
||||
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
#include "SuperSensor.h"
|
||||
#include "Calculator.h"
|
||||
#include "Ticker.h"
|
||||
|
||||
StatusRequest measure;
|
||||
|
||||
Scheduler ts, hts;
|
||||
|
||||
// Tasks
|
||||
|
||||
Calculator* tCalculate;
|
||||
Ticker* tCycle;
|
||||
|
||||
int pins[] = { 1, 9, 3, 7, 5, 6, 4, 8, 2, 10 };
|
||||
|
||||
#ifdef ARDUINO_ARCH_STM32F1
|
||||
#define A0 3
|
||||
#endif
|
||||
|
||||
/** Main Arduino code
|
||||
Not much is left here - everything is taken care of by the framework
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
while (!Serial) {}
|
||||
Serial.println("TaskScheduler StatusRequest Sensor Emulation Test. Complex Test.");
|
||||
|
||||
#ifdef ARDUINO_ARCH_STM32F1
|
||||
pinMode(A0, INPUT_ANALOG);
|
||||
#endif
|
||||
|
||||
randomSeed(analogRead(A0) + millis());
|
||||
|
||||
ts.setHighPriorityScheduler(&hts);
|
||||
|
||||
tCalculate = new Calculator (&hts, &ts);
|
||||
tCycle = new Ticker (&hts, (Task*) tCalculate, &measure);
|
||||
|
||||
tCalculate->setTimeout(1 * TASK_SECOND);
|
||||
tCycle->enable();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#include "SuperSensor.h"
|
||||
|
||||
SuperSensor::SuperSensor(Scheduler* aScheduler, int aPin, Calculator* aC, StatusRequest* aS) : Task(TASK_MILLISECOND, TASK_FOREVER, aScheduler, false) {
|
||||
iPin = aPin;
|
||||
iC = aC;
|
||||
iS = aS;
|
||||
}
|
||||
|
||||
SuperSensor::~SuperSensor() {
|
||||
iValue = -1;
|
||||
}
|
||||
|
||||
void SuperSensor::begin() {
|
||||
iDelay = random(300, 1500);
|
||||
iValue = -1;
|
||||
}
|
||||
|
||||
void SuperSensor::stop() {
|
||||
//nothing to do
|
||||
}
|
||||
|
||||
long SuperSensor::trigger() {
|
||||
iStart = millis();
|
||||
return iDelay;
|
||||
}
|
||||
|
||||
bool SuperSensor::measurementReady() {
|
||||
if ( millis() - iStart > iDelay ) {
|
||||
iValue = random(501);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long SuperSensor::value() {
|
||||
return iValue;
|
||||
}
|
||||
|
||||
bool SuperSensor::OnEnable() {
|
||||
int i = getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SEnable: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Triggering sensor. Delay=");
|
||||
|
||||
long dly = trigger();
|
||||
|
||||
Serial.println( dly );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SuperSensor::Callback() {
|
||||
|
||||
if ( measurementReady() ) {
|
||||
int i = getId();
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SCallback: TaskID=");
|
||||
Serial.println(i);
|
||||
Serial.print("Emulating measurement. d=");
|
||||
|
||||
long d = value();
|
||||
iC->reportDistance(d);
|
||||
|
||||
Serial.println(d);
|
||||
|
||||
iS->signal();
|
||||
disable();
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SuperSensor::OnDisable() {
|
||||
int i = getId();
|
||||
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.print("SDisable: TaskID=");
|
||||
Serial.println(i);
|
||||
|
||||
stop();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef _SUPER_SENSOR_H
|
||||
#define _SUPER_SENSOR_H
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
#define _TASK_OO_CALLBACKS
|
||||
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
#include "Calculator.h"
|
||||
|
||||
//class Calculator;
|
||||
|
||||
class SuperSensor : public Task {
|
||||
|
||||
public:
|
||||
SuperSensor(Scheduler* aScheduler, int aPin, Calculator* aC, StatusRequest* aS);
|
||||
~SuperSensor();
|
||||
|
||||
void begin();
|
||||
void stop();
|
||||
long trigger();
|
||||
bool measurementReady();
|
||||
long value();
|
||||
|
||||
bool Callback();
|
||||
bool OnEnable();
|
||||
void OnDisable();
|
||||
|
||||
private:
|
||||
long iDelay;
|
||||
long iValue;
|
||||
int iPin;
|
||||
unsigned long iStart;
|
||||
Calculator* iC;
|
||||
StatusRequest* iS;
|
||||
};
|
||||
|
||||
#endif // _SUPER_SENSOR_H
|
|
@ -0,0 +1,20 @@
|
|||
#include "Ticker.h"
|
||||
|
||||
Ticker::Ticker(Scheduler* aS, Task* aCalc, StatusRequest* aM) : Task(10000, TASK_FOREVER, aS, false) {
|
||||
iCalc = aCalc;
|
||||
iMeasure = aM;
|
||||
}
|
||||
|
||||
bool Ticker::Callback() {
|
||||
Serial.println(); Serial.println(); Serial.println();
|
||||
Serial.print(millis()); Serial.print(":\t");
|
||||
Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");
|
||||
|
||||
int numberSensors = random(1, 11); // 1 to 10 sensors, randomly
|
||||
Serial.print("Number of sensors=");
|
||||
Serial.println(numberSensors);
|
||||
|
||||
iMeasure->setWaiting(numberSensors); // Set the StatusRequest to wait for 1 to 10 signals.
|
||||
iCalc->waitFor(iMeasure);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef _TICKER_H
|
||||
#define _TICKER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
#define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
#define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
#define _TASK_TIMEOUT // Support for overall task timeout
|
||||
#define _TASK_OO_CALLBACKS
|
||||
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
|
||||
class Ticker : public Task {
|
||||
public:
|
||||
Ticker(Scheduler* aS, Task* aCalc, StatusRequest* aM);
|
||||
~Ticker() {};
|
||||
|
||||
bool Callback();
|
||||
|
||||
private:
|
||||
Task *iCalc;
|
||||
StatusRequest* iMeasure;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,78 @@
|
|||
// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
|
||||
// #define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass
|
||||
// #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
|
||||
// #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
|
||||
// #define _TASK_LTS_POINTER // Compile with support for local task storage pointer
|
||||
// #define _TASK_PRIORITY // Support for layered scheduling priority
|
||||
// #define _TASK_MICRO_RES // Support for microsecond resolution
|
||||
// #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 and ESP32 ONLY)
|
||||
// #define _TASK_DEBUG // Make all methods and variables public for debug purposes
|
||||
// #define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
|
||||
// #define _TASK_TIMEOUT // Support for overall task timeout
|
||||
// #define _TASK_OO_CALLBACKS // Support for dynamic callback method binding
|
||||
#include <TaskScheduler.h>
|
||||
|
||||
// Debug and Test options
|
||||
#define _DEBUG_
|
||||
//#define _TEST_
|
||||
|
||||
#ifdef _DEBUG_
|
||||
#define _PP(a) Serial.print(a);
|
||||
#define _PL(a) Serial.println(a);
|
||||
#else
|
||||
#define _PP(a)
|
||||
#define _PL(a)
|
||||
#endif
|
||||
|
||||
|
||||
// Scheduler
|
||||
Scheduler ts;
|
||||
|
||||
void task1Callback();
|
||||
void task2Callback();
|
||||
|
||||
/*
|
||||
Scheduling defines:
|
||||
TASK_MILLISECOND
|
||||
TASK_SECOND
|
||||
TASK_MINUTE
|
||||
TASK_HOUR
|
||||
TASK_IMMEDIATE
|
||||
TASK_FOREVER
|
||||
TASK_ONCE
|
||||
TASK_NOTIMEOUT
|
||||
*/
|
||||
|
||||
Task t1 (100 * TASK_MILLISECOND, TASK_FOREVER, &task1Callback, &ts, true);
|
||||
Task t2 (TASK_IMMEDIATE, 100, &task2Callback, &ts, true);
|
||||
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
#if defined(_DEBUG_) || defined(_TEST_)
|
||||
Serial.begin(115200);
|
||||
delay(2000);
|
||||
_PL("Scheduler Template: setup()");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ts.execute();
|
||||
}
|
||||
|
||||
|
||||
void task1Callback() {
|
||||
_PP(millis());
|
||||
_PL(": task1Callback()");
|
||||
|
||||
}
|
||||
|
||||
void task2Callback() {
|
||||
_PP(millis());
|
||||
_PL(": task2Callb()");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue