diff options
| author | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-10-13 20:18:23 -0400 |
|---|---|---|
| committer | Anatoli Arkhipenko <arkhipenko@hotmail.com> | 2015-10-13 20:18:23 -0400 |
| commit | 07b0a9e49fd4c918821099aec940d0927c3f9ff5 (patch) | |
| tree | 03da52d7d6b20c71c6afbbbe1b61da1ab2874d71 /extras | |
| parent | 332d0cf661ff7d86640773168113ffe5e47de505 (diff) | |
TaskScheduler v1.7.0 with the following changes:
* introduced callback run counter - callback functions can branch on the
iteration number
* enableIfNot() - enable a task only if it is not already enabled.
Returns true if was already enabled, false if was disabled
* disable() returns previous enable state (true if was enabled, false if
was already disabled)
* introduced callback functions "on enable" and "on disable". On enable
runs every time enable is called, on disable runs only if task was
enabled
* new Task method: forceNextIteration() - makes next iteration happen
immediately during the next pass regardless how much time is left
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/TaskScheduler.doc | bin | 65024 -> 121856 bytes | |||
| -rw-r--r-- | extras/TaskScheduler.html | 386 | ||||
| -rw-r--r-- | extras/TaskScheduler_html.png | bin | 0 -> 41281 bytes |
3 files changed, 310 insertions, 76 deletions
diff --git a/extras/TaskScheduler.doc b/extras/TaskScheduler.doc Binary files differindex f6e88c7..a40aea7 100644 --- a/extras/TaskScheduler.doc +++ b/extras/TaskScheduler.doc diff --git a/extras/TaskScheduler.html b/extras/TaskScheduler.html index 7855c7f..96a605e 100644 --- a/extras/TaskScheduler.html +++ b/extras/TaskScheduler.html @@ -6,7 +6,7 @@ <META NAME="GENERATOR" CONTENT="LibreOffice 3.5 (Linux)"> <META NAME="CREATED" CONTENT="20150206;16300000"> <META NAME="CHANGEDBY" CONTENT="Anatoli Arkhipenko"> - <META NAME="CHANGED" CONTENT="20150921;21210000"> + <META NAME="CHANGED" CONTENT="20151012;23280000"> <META NAME="Info 1" CONTENT=""> <META NAME="Info 2" CONTENT=""> <META NAME="Info 3" CONTENT=""> @@ -15,57 +15,70 @@ <!-- @page { margin: 0.79in } P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 } - P.western { font-family: "Liberation Serif", "Times New Roman", serif; font-size: 12pt; so-language: en-US } + P.western { font-family: "Liberation Serif", "MS PMincho", serif; font-size: 12pt; so-language: en-US } P.cjk { font-family: "WenQuanYi Micro Hei", "MS Mincho"; font-size: 12pt; so-language: zh-CN } P.ctl { font-family: "Lohit Hindi", "MS Mincho"; font-size: 12pt; so-language: hi-IN } --> </STYLE> </HEAD> -<BODY LANG="en-US" TEXT="#000000" DIR="LTR"> +<BODY LANG="en-US" TEXT="#000000" BGCOLOR="#ffffff" DIR="LTR"> <P CLASS="western" STYLE="margin-bottom: 0in"><B>Task Scheduler – cooperative multitasking for Arduino microcontrollers</B></P> -<P CLASS="western" STYLE="margin-bottom: 0in"><B>Version 1.6.0: -2015-10-01</B></P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>Version 1.7.0: +2015-10-12</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> -<P CLASS="western" STYLE="margin-bottom: 0in"><B>REQUIREMENT</B>:</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P> <P CLASS="western" STYLE="margin-bottom: 0in">A lightweight -implementation of the task scheduling supporting:</P> +implementation of cooperative multitasking (task scheduling) +supporting:</P> <OL> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">execution period - (n times per second)</P> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">number of + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Periodic task + execution (with dynamic execution period in milliseconds)</P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Number of iterations (n times)</P> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">execution of tasks + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Execution of tasks in predefined sequence</P> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">dynamic change of - the execution parameters for both tasks and execution schedule</P> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">power saving via - entering IDLE sleep mode if no tasks are scheduled to run</P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Dynamic change of + task execution parameters (frequency, number of iterations, callback + function)</P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Power saving via + entering IDLE sleep mode between tasks are scheduled to run</P> </OL> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> -<P CLASS="western" STYLE="margin-bottom: 0in"><B>IDEA</B>:</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>TASK</B>:</P> <P CLASS="western" STYLE="margin-bottom: 0in">“Task” is a container concept that links together:</P> <OL> <LI><P CLASS="western" STYLE="margin-bottom: 0in">Execution interval</P> <LI><P CLASS="western" STYLE="margin-bottom: 0in">Number of execution iterations</P> - <LI><P CLASS="western" STYLE="margin-bottom: 0in">A piece of code - performing the task activities (callback function)</P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">Piece of code + performing task activities (callback functions)</P> </OL> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> -<P CLASS="western" STYLE="margin-bottom: 0in">Tasks are linked into -execution chains, which are processed by the “Scheduler” in the -order they are linked.</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>Tasks</B> are linked +into execution <B>chains</B>, which are processed by the “Scheduler” +in the order they are linked.</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in">Each task performs its +function via callback function. Scheduler calls Task’s callback +function periodically until task is disabled or task runs out of +iterations. In addition to “regular” callback, two methods could +be enabled for each task: a callback function invoked once when task +is enabled, and a callback function invoked once when the task is +disabled. Those two special methods allows task to properly initiate +themselves for execution and clean-up after execution is over. +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in">Tasks are responsible -for supporting cooperative multitasking by being “good neighbors”, -i.e., running their callback functions in a non-blocking way and -releasing control as soon as possible. +for supporting <B>cooperative</B> <B>multitasking</B> by being “good +neighbors”, i.e., running their callback functions quickly in a +non-blocking way and releasing control as soon as possible. </P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> @@ -73,8 +86,8 @@ releasing control as soon as possible. executing Tasks' callback functions in the order the tasks were added to the chain, from first to last. Scheduler stops and exists after processing the chain once in order to allow other statements in the -main code of <B>loop()</B> function to run. This a “scheduling -pass”.</P> +main code of <B>loop()</B> function to run. This <B>a “scheduling +pass”.</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in">If compiled with @@ -82,11 +95,16 @@ pass”.</P> enabled, the scheduler will place processor into IDLE sleep mode (for approximately 1 ms, as the timer interrupt will wake it up), after what is determined to be an “idle” pass. An Idle Pass is a pass -through the chain when no Tasks were scheduled to run their callback -functions. This is done to avoid repetitive empty passes through the -chain when no tasks need to be executed. If any of the tasks in the -chain always requires immediate execution (aInterval = 0), then there -will be no end-of-pass delay.</P> +through the task chain when no Tasks were scheduled to run their +callback functions. This is done to avoid repetitive empty passes +through the chain when no tasks need to be executed. If any of the +tasks in the chain always requires immediate execution (aInterval = +0), then there will be no IDLE sleep between task callback execution.</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid"> +<B>Below is the flowchart of a Task lifecycle:</B></P> +<P CLASS="western" STYLE="margin-bottom: 0in"><IMG SRC="TaskScheduler_html.png" NAME="graphics1" ALIGN=BOTTOM WIDTH=664 HEIGHT=769 BORDER=0></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Task @@ -178,7 +196,8 @@ tasks are created <B>disabled</B> by default.</P> </P> <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid"> <B>Task(unsigned long aInterval, long aIterations, void -(*aCallback)(), Scheduler* aScheduler, bool aEnable);</B></P> +(*aCallback)(), Scheduler* aScheduler, bool aEnable, bool +(*aOnEnable)(), void (*aOnDisable)(),);</B></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Constructor @@ -191,24 +210,33 @@ every pass. </P> <OL> <LI><P CLASS="western" STYLE="margin-bottom: 0in">aInterval is in - milliseconds</P> + milliseconds (<B>default = 0)</B></P> <LI><P CLASS="western" STYLE="margin-bottom: 0in">aIteration in - number of times, -1 for indefinite execution<BR><B>Note: </B>Tasks - do not remember the number of iteration set initially. After the - iterations are done, internal iteration counter is 0. If you need to - perform another set of iterations, you need to set the number of - iterations again. <BR><B>Note: </B>Tasks which performed all their - iterations remain active. + number of times, -1 for indefinite execution (<B>default = -1)</B><BR><B>Note: + </B>Tasks do not remember the number of iteration set initially. + After the iterations are done, internal iteration counter is 0. If + you need to perform another set of iterations, you need to set the + number of iterations again. <BR><B>Note: </B>Tasks which performed + all their iterations remain active. </P> <LI><P CLASS="western" STYLE="margin-bottom: 0in">aCallback is a - pointer to a void function without parameters</P> + pointer to a void callback function without parameters (<B>default = + NULL)</B></P> <LI><P CLASS="western" STYLE="margin-bottom: 0in">aScheduler – <B>optional</B> reference to existing scheduler. If supplied (not NULL) this task will be appended to the task chain of the current - scheduler). <B>Default=NULL</B></P> + scheduler). (<B>default = NULL)</B></P> <LI><P CLASS="western" STYLE="margin-bottom: 0in">aEnable – <B>optional</B>. Value of <B>true </B>will create task enabled. - <B>Default = false</B></P> + (<B>default = false)</B></P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">aOnEnable is a + pointer to a bool callback function without parameters, invoked when + task is enabled. If OnEnable function returns <B>true</B>, task is + enabled. If <B>OnEnable</B> function return <B>false</B>, task + remains disabled (<B>default = NULL)</B></P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in">aOnDisable is a + pointer to a void callback function without parameters, invoked when + task is disabled (<B>default = NULL)</B></P> </OL> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> @@ -267,13 +295,35 @@ execution purposes. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>unsigned long +getRunCounter()</B></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns +the number of the current run. “Current run” is the number of +times a callback function has been invoked since the last time a task +was enabled. <BR><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>NOTE: +</B>The <B>runCounter</B> value is incremented <I>before</I> callback +function is invoked. If a task is checking the <B>runCounter</B> +value within its callback function, then the first run value is 1. +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If +task T1 is checking the <B>runCounter</B> value of another task (T2) +, then value = 0 indicates that T2 has not been invoked yet, and +value = 1 indicates that T2 has run once. +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool isFirstIteration()</B></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Indicates +whether current pass is a first iteration of the task. +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool isLastIteration()</B></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">For -tasks with a defined number of iterations, indicates whether current -pass is a first or a last iteration of the task (respectively). +tasks with a limited number of iterations only, indicates whether +current pass is the last iteration. </P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> @@ -292,6 +342,25 @@ is a task which was enabled and requires execution. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note: +</B>enable() invokes task’s <B>OnEnable</B> method (if not NULL), +which can prepare task for execution. <B>OnEnable</B> must return a +value of <B>true</B> for task to be enabled. If <B>OnEnable</B> +returns <B>false</B>, task remains disabled. <B>OnEnable</B> is +invoked every time <B>enable</B> is called, regardless if task is +already enabled or not. +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>bool enableIfNot();</B></P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables +the task only if it was previously disabled. Returns previous enable +state: <B>true</B> if task was already enabled, and <B>false</B> if +task was disabled.</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>void delay();</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> @@ -301,6 +370,28 @@ the enabled/disabled status of the task. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note: +</B>a delay of 0 (zero) will delay task for current execution +interval. Use <B>forceNextIteration() </B>method to force execution +of the task’s callback during immediate next scheduling pass. +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>void +forceNextIteration();</B></P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Schedules +the task for execution during immediate next scheduling pass.</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note: +</B>Task’s schedule is adjusted to run from this moment in time. +For instance: if a task was running every 10 seconds: 10, 20, 30, .., +calling <B>forceNextIteration </B>at 44th second of task execution +will make subsequent schedule look like: 44, 54, 64, 74, ..</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>void enableDelayed();</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> @@ -340,26 +431,37 @@ Task is scheduled to run first iteration after a delay = <B>aDelay</B> milliseconds.</P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> -<P CLASS="western" STYLE="margin-bottom: 0in"><B>void disable();</B></P> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>bool disable();</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Disables the task. Scheduler will not execute this task any longer, even if it remains in the chain. Task can be later re-enabled for execution. </P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Return +previous enabled state: <B>true</B> if task was enabled prior to +calling disable, and <B>false</B> otherwise.</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If +not NULL, task’s <B>OnDisable</B> method is invoked. <B>OnDisable</B> +is invoked only if task was enabled. Calling <B>disable</B> 3 times +for instance will invoke <B>OnDisable</B> only once.</P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>void set(unsigned -long aInterval, long aIterations, void (*aCallback)());</B></P> +long aInterval, long aIterations, void (*aCallback)() , bool +(*aOnEnable)() , void (*aOnDisable)());</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Allows -dynamic control of all task execution parameters in one function -call. +dynamic control of task execution parameters in one function call. +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note</B><B>: +</B>OnEnable and OnDisable parameters can be omitted. In that case +they will be assigned to NULL and not called. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> -<P CLASS="western" STYLE="margin-bottom: 0in">Next three “setter” +<P CLASS="western" STYLE="margin-bottom: 0in">Next five “setter” functions allow changes of individual task execution control parameters. </P> @@ -372,6 +474,12 @@ setIterations (long aIterations) </B> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void setCallback (void (*aCallback)()) </B> </P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void +setOnEnable (bool (*aCallback)()) </B> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void +setOnDisable (void (*aCallback)()) </B> +</P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Next @@ -381,11 +489,12 @@ scheduler. For the situations when one task is changing the interval parameter for the other, <B>setInterval</B> function calls <B>delay </B>explicitly to guarantee schedule change, however it <B>does not </B>enable the task if task is disabled.</P> -<P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B><SPAN STYLE="font-weight: normal">Tasks -that ran through all their allocated iterations are disabled. -</SPAN><B>SetIterations()</B><SPAN STYLE="font-weight: normal"> -method </SPAN><B>DOES NOT</B><SPAN STYLE="font-weight: normal"> -enable the task. Either enable explicitly, or use restart methods. </SPAN> +<P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Tasks that +ran through all their allocated iterations are disabled. +<B>SetIterations()</B> method <B>DOES NOT</B> enable the task. Either +<B>enable</B> explicitly, or use <B>restart</B> methods. +</P> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> @@ -427,16 +536,17 @@ addTask(Task& aTask)</B></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Adds task aTask to the execution queue (or chain) of tasks by appending it to the end of the chain. If two tasks are scheduled for execution, -the sequence will match the order tasks are appended to the chain. -However, in reality, due to different timing of task execution, the -actual order will be different. +the sequence will match the order in which tasks were appended to the +chain. However, in reality, due to different timing of task +execution, the actual order may be different. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note: -</B>Currently, changing the execution dynamically is not supported. +</B>Currently, changing the execution sequence in a chain dynamically +is not supported. </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If -you need to reorder the queue – initialize the scheduler and re-add -the tasks in a different order. +you need to reorder the chain sequence – initialize the scheduler +and re-add the tasks in a different order. </P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void deleteTask(Task& aTask)</B></P> @@ -489,8 +599,8 @@ currentTask()<BR></B><BR> </P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns reference to the task, currently executing via <B>execute()</B> loop. -Could be used by callback functions to identify which of the -</P> +Could be used by callback functions to identify which of the Tasks +invoked callback function.</P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void execute()</B></P> <P CLASS="western" STYLE="margin-bottom: 0in"><BR> </P> @@ -774,16 +884,16 @@ determine the length of ultrasonic pulse.</FONT></P> <PinChangeInt.h><BR><BR><BR>#define TRIGGERPIN 5<BR>#define ECHOPIN 6<BR><BR>Output<TRIGGERPIN> pTrigger;<BR>Input<ECHOPIN> pEcho;<BR><BR>Scheduler -r;<BR><BR>Task tMeasure(1000, -1, &measureCallback);<BR>Task -tDisplay(1000, -1, &displayCallback);<BR>Task tPing(0, 1, -&pingCalcCallback);<BR><BR><BR>volatile bool pulseBusy = -false;<BR>volatile bool pulseTimeout = false;<BR>volatile unsigned -long pulseStart = 0;<BR>volatile unsigned long pulseStop = -0;<BR>volatile unsigned long pingDistance = 0;<BR><BR><BR>void -pingTrigger(unsigned long aTimeout) {<BR> if (pulseBusy) return; // -do not trigger if in the middle of a pulse<BR> if (pEcho == HIGH) -return; // do not trigger if ECHO pin is high<BR> <BR> pulseBusy = -true;<BR> pulseTimeout = false;</FONT></FONT></P> +r;<BR><BR>Task tMeasure(1000, -1, &measureCallback, &r, +true);<BR>Task tDisplay(1000, -1, &displayCallback, &r, +true);<BR>Task tPing(0, 1, &pingCalcCallback, &r, +false);<BR><BR><BR>volatile bool pulseBusy = false;<BR>volatile bool +pulseTimeout = false;<BR>volatile unsigned long pulseStart = +0;<BR>volatile unsigned long pulseStop = 0;<BR>volatile unsigned long +pingDistance = 0;<BR><BR><BR>void pingTrigger(unsigned long aTimeout) +{<BR> if (pulseBusy) return; // do not trigger if in the middle of +a pulse<BR> if (pEcho == HIGH) return; // do not trigger if ECHO pin +is high<BR> <BR> pulseBusy = true;<BR> pulseTimeout = false;</FONT></FONT></P> <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR> pTrigger = LOW;<BR> delayMicroseconds(4);<BR> pTrigger = HIGH;<BR><BR> tPing.setInterval (aTimeout);<BR><BR> delayMicroseconds(10);<BR> @@ -832,10 +942,134 @@ Wait for the measurement to <BR>void measureCallbackWait() {<BR> if cm);<BR> Serial.println(d);<BR> <BR>}<BR><BR>void setup() {<BR> // put your setup code here, to run once:<BR> <BR> Serial.begin(115200);<BR> <BR><BR> pTrigger = LOW;<BR> pEcho = -LOW;<BR> <BR> r.init();<BR> r.addTask(tDisplay);<BR> -r.addTask(tMeasure);<BR> r.addTask(tPing);<BR> <BR> -r.enableAll();<BR> tPing.disable();<BR>}<BR><BR>void loop() {<BR> -// put your main code here, to run repeatedly:<BR> r.execute();<BR>}<BR></FONT></FONT><BR> +LOW;<BR> <BR>}<BR><BR>void loop() {<BR> // put your main code here, +to run repeatedly:<BR> r.execute();<BR>}<BR></FONT></FONT><BR> +</P> +<OL START=3> + <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>USING + ONENABLE AND ONDISBALE METHODS </B></FONT> + </P> +</OL> +<P CLASS="western" STYLE="margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Consider +a task to flash onboard LED for 5 seconds with random frequency. Task +should be repeated every 30 seconds indefinitely. Since frequency is +random, there are two challenges:</FONT></P> +<OL START=3> + <OL> + <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">We + need to make sure LED is turned OFF at the last iteration</FONT></P> + <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">We + need to calculate random frequency every time</FONT></P> + </OL> +</OL> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Below +is the implementation using TaskScheduler </FONT> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR>#include +<TaskScheduler.h><BR><BR>#define LEDPIN 13<BR><BR><BR>Scheduler +ts;<BR></FONT></FONT><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task +tWrapper(30000L, -1, &WrapperCallback, &ts, true);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task +tBlink(5000, 1, NULL, &ts, false, &BlinkOnEnable, +&BlinkOnDisable);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task +tLED(0, -1, NULL, &ts, false, NULL, &LEDOff);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void +WrapperCallback() {</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tBlink.restartDelayed(); + // LED blinking is initiated </FONT></FONT> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> +<FONT FACE="Courier New, monospace"><FONT SIZE=2> //every 30 +seconds for 5 seconds</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +Upon being enabled, tBlink will define the parameters</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +and enable LED blinking task, which actually controls</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +the hardware (LED in this example)</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool +BlinkOnEnable() {</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.setInterval( +500 + random(501) );</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.setCallback( +&LEDOn);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.enable();</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> return +true; // Task should be enabled</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +tBlink does not really need a callback function</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +since it just waits for 5 seconds for the first </FONT></FONT> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +and only iteration to occur. Once the iteration</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +takes place, tBlink is disabled by the Scheduler, </FONT></FONT> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +thus executing its OnDisable method below.</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void +BlinkOnDisable() {</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.disable();</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void +LEDOn () {</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> digitalWrite(LEDPIN, +HIGH);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.setCallback( +&LEDOff);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void +LEDOff () {</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> digitalWrite(LEDPIN, +LOW);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tLED.setCallback( +&LEDOn);</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +Note that LEDOff method serves as OnDisable method</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +to make sure the LED is turned off when the tBlink</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>// +task finishes (or disabled ahead of time)</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void +setup() {<BR> // put your setup code here, to run once:<BR>}<BR><BR>void +loop() {<BR> // put your main code here, to run repeatedly:<BR> +ts.execute();<BR>}</FONT></FONT></P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> +</P> +<P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR> </P> </BODY> </HTML>
\ No newline at end of file diff --git a/extras/TaskScheduler_html.png b/extras/TaskScheduler_html.png Binary files differnew file mode 100644 index 0000000..febb8c7 --- /dev/null +++ b/extras/TaskScheduler_html.png |
