Переглянути джерело

v2.6.0 - Documentation update. Example 18 added.
* Updated documentation with some specifics of enable() vs. enableDelayed()
* Added example #18 which uses several compilation directives: TIMEOUT, LTS, WDT, etc.

BuildTools 8 роки тому
батько
коміт
188e9a112d

+ 170 - 0
examples/Scheduler_example18_StatusRequest_LTS_WDT_Timeout/Scheduler_example18_StatusRequest_LTS_WDT_Timeout.ino

@@ -0,0 +1,170 @@
+/** 
+ *  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;
+
+// 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, &ts);
+Task tCalculate(TASK_IMMEDIATE , TASK_ONCE, &CalcCallback, &ts, 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.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(A1) + millis());
+
+  tSensor1.setLtsPointer(&d_lts[0]);
+  tSensor2.setLtsPointer(&d_lts[1]);
+  tSensor3.setLtsPointer(&d_lts[2]);
+
+  tCalculate.setTimeout(1 * TASK_SECOND);
+
+  tCycle.enable();
+}
+
+void loop() {
+
+  ts.execute();
+
+}

BIN
extras/TaskScheduler.doc


BIN
extras/TaskScheduler.pdf


+ 2 - 2
src/TaskScheduler.h

@@ -787,7 +787,7 @@ bool Scheduler::execute() {
     bool     idleRun = true;
     register unsigned long m, i;  // millis, interval;
 
-#if defined (ARDUINO_ARCH_ESP8266) || defined (ARDUINO_ARCH_ESP32)
+#ifdef ARDUINO_ARCH_ESP8266
       unsigned long t1 = micros();
       unsigned long t2 = 0;
 #endif  // ARDUINO_ARCH_ESP8266
@@ -825,7 +825,7 @@ bool Scheduler::execute() {
 					iCurrent->disable();
                     break;
 				}
-#endif
+#endif // _TASK_TIMEOUT
                 
 #ifdef  _TASK_STATUS_REQUEST
     // If StatusRequest object was provided, and still pending, and task is waiting, this task should not run