summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorAnatoli Arkhipenko <arkhipenko@hotmail.com>2015-10-22 23:17:45 -0400
committerAnatoli Arkhipenko <arkhipenko@hotmail.com>2015-10-22 23:17:45 -0400
commitccd1047d0286027ff98ee7f1dfdfa1f9d5e6e4e3 (patch)
tree2481326454d89e1977923475fda443ba3a78922c /examples
parentbb20df9c654cbed77bb5007814ae06f20f08ec36 (diff)
Support for taask IDs and Control Pointsv1.8.1
* Automatically and manually assigned task IDs * Manually assigned Control Points within task's callback function * Updated existing examples * New example sketches
Diffstat (limited to 'examples')
-rw-r--r--examples/Scheduler_example/Scheduler_example.ino29
-rw-r--r--examples/Scheduler_example3/Scheduler_example3.ino9
-rw-r--r--examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino159
-rw-r--r--examples/Scheduler_example6_IDLE/Scheduler_example6_IDLE.ino77
-rw-r--r--examples/Scheduler_example7_WDT/Scheduler_example7_WDT.ino128
5 files changed, 306 insertions, 96 deletions
diff --git a/examples/Scheduler_example/Scheduler_example.ino b/examples/Scheduler_example/Scheduler_example.ino
index dece85a..74b60f9 100644
--- a/examples/Scheduler_example/Scheduler_example.ino
+++ b/examples/Scheduler_example/Scheduler_example.ino
@@ -1,3 +1,16 @@
+/**
+ * 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>
Task t4();
@@ -5,18 +18,6 @@ Task t1(2000, 10, &t1Callback);
Task t2(3000, -1, &t2Callback);
Task t3(5000, -1, &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
-
-
Scheduler runner;
@@ -74,9 +75,5 @@ void setup () {
void loop () {
-
runner.execute();
-
- Serial.println("Loop ticks at: ");
- Serial.println(millis());
}
diff --git a/examples/Scheduler_example3/Scheduler_example3.ino b/examples/Scheduler_example3/Scheduler_example3.ino
index d683855..7111ac3 100644
--- a/examples/Scheduler_example3/Scheduler_example3.ino
+++ b/examples/Scheduler_example3/Scheduler_example3.ino
@@ -1,3 +1,12 @@
+/**
+ * TaskScheduler Test of OnEnable and OnDisable methods and illustration of using wrapper tasks for timout purposes
+ *
+ * A wrapper task runs every 30 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>
diff --git a/examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino b/examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino
index ffe4e3a..080de05 100644
--- a/examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino
+++ b/examples/Scheduler_example4_StatusRequest/Scheduler_example4_StatusRequest.ino
@@ -1,81 +1,80 @@
-/** 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;
-
-Task t1(5000, 1, &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);
- Serial.println("TaskScheduler: Status Request Test 1. Simple Test.");
- // put your setup code here, to run once:
- PrepareStatus();
- t3.waitFor(&st);
-
- t1.delay();
-}
-
-void loop() {
- // put your main code here, to run repeatedly:
- ts.execute();
-
+/** 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;
+
+Task t1(5000, 1, &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);
+ Serial.println("TaskScheduler: Status Request Test 1. Simple Test.");
+
+ PrepareStatus();
+ t3.waitFor(&st);
+
+ t1.delay();
+}
+
+void loop() {
+
+ ts.execute();
+
}
diff --git a/examples/Scheduler_example6_IDLE/Scheduler_example6_IDLE.ino b/examples/Scheduler_example6_IDLE/Scheduler_example6_IDLE.ino
new file mode 100644
index 0000000..f4df5d8
--- /dev/null
+++ b/examples/Scheduler_example6_IDLE/Scheduler_example6_IDLE.ino
@@ -0,0 +1,77 @@
+
+/**
+ * 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
+Start
+c1=10771
+c2=1001
+
+
+and
+
+2): With #define _TASK_SLEEP_ON_IDLE_RUN disabled (commented out)
+Start
+c1=529783
+c2=1001
+
+C1 is 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;
+
+Task c(10, -1, &Count, &ts);
+Task t(10000, 1, 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);
+ Serial.println("Start");
+ t.delay();
+ // ts.allowSleep(false);
+}
+
+void Count() {
+ c2++;
+}
+
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ ts.execute();
+ c1++;
+}
diff --git a/examples/Scheduler_example7_WDT/Scheduler_example7_WDT.ino b/examples/Scheduler_example7_WDT/Scheduler_example7_WDT.ino
new file mode 100644
index 0000000..ab880d2
--- /dev/null
+++ b/examples/Scheduler_example7_WDT/Scheduler_example7_WDT.ino
@@ -0,0 +1,128 @@
+/**
+ * TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks
+ * 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..9. 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;
+
+// Three tasks emulating accidental infinite loop
+Task tTask1(1000, -1, &TaskCB, &ts, true);
+Task tTask2(1000, -1, &TaskCB, &ts, true);
+Task tTask3(1000, -1, &TaskCB, &ts, true);
+
+// Heartbeat task - resetting the watchdog timer periodically
+// Initiates WDT on enable, and deactivates it on disable
+Task tHB(500, -1, &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 9 is 5 (10% probability)
+ T.setControlPoint(10);
+ if (random(10) == 5) for(;;);
+
+// Hang if random number between 0 and 99 is more that 85 (15% probability)
+ T.setControlPoint(85);
+ if (random(100) > 84) 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();
+}