| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
- <HTML>
- <HEAD>
- <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
- <TITLE></TITLE>
- <META NAME="GENERATOR" CONTENT="LibreOffice 3.5 (Linux)">
- <META NAME="CREATED" CONTENT="20150206;16300000">
- <META NAME="CHANGEDBY" CONTENT="Anatoli Arkhipenko">
- <META NAME="CHANGED" CONTENT="20151015;23250000">
- <META NAME="Info 1" CONTENT="">
- <META NAME="Info 2" CONTENT="">
- <META NAME="Info 3" CONTENT="">
- <META NAME="Info 4" CONTENT="">
- <STYLE TYPE="text/css">
- <!--
- @page { margin: 0.79in }
- P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 }
- 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" 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.8.0:
- 2015-10-15</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">A lightweight
- implementation of cooperative multitasking (task scheduling)
- supporting:</P>
- <OL>
- <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
- in predefined sequence</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>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in">Support for task
- invocation via Status Request object</P>
- </OL>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </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">Execution event
- (Status Request)</P>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in">Number of
- execution iterations</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"><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 <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>
- <P CLASS="western" STYLE="margin-bottom: 0in">“Scheduler” is
- 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 <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
- <FONT FACE="Courier New, monospace">_TASK_SLEEP_ON_IDLE_RUN</FONT>
- 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 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=747 BORDER=0></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Task
- Scheduler uses <B>millis()</B> to determine if tasks are ready to be
- invoked. Therefore, if you put your device to any “deep” sleep
- mode disabling timer interrupts, the <B>millis()</B> count will be
- suspended, leading to effective suspension of scheduling. Upon wake
- up, active tasks need to be re-enabled, which will effectively reset
- their internal time scheduling variables to the new value of
- <B>millis(). </B>Time spent in deep sleep mode should be considered
- “frozen”, i.e., if a task was scheduled to run in 1 second from
- now, and device was put to sleep for 5 minutes, upon wake up, the
- task will still be scheduled 1 second from the time of wake up.
- Executing <B>enable() </B>function on this tasks will make it run as
- soon as possible. This is a concern only for tasks which are required
- to run in a truly periodical manner (in absolute time terms).
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">In addition to
- time-only invocation, tasks can be scheduled to wait on an event
- employing StatusRequest objects (more about Status Requests later).</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Consider a scenario
- when one task (t1) is performing a function which affects execution
- of many tasks (t2, t3). In this case the task t1 will “signal”
- completion of its function via Status Request object. Tasks t2 and t3
- are “waiting” on the same Status Request object. As soon as
- status request completes, t2 and t3 are activated.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Alternative scenario is
- the ne task (t1) and waiting for the completion of a number of tasks
- (t2, t3). When done, t2 and t3 signal completion of their functions,
- t1 is invoked.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Please see the examples
- at the end of this document.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>COMPILE PARAMETERS:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in">This library could be
- compiled with several options.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">These parameters must
- be defined before inclusion of the library header file into the
- sketch.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">#define
- <B>_TASK_TIMECRITICAL</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in">...will compile the
- library with time critical tracking option enabled.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Time critical option
- keeps track where next execution time of the task falls, and makes it
- available via API through Task::<B> getOverrun() </B>function. If
- <B>getOverrun </B>returns a negative value, this Task’s next
- execution time is in the past, and task is behind schedule. This most
- probably means that either task’s callback function runtime is too
- long, or the execution interval is too short (then schedule is too
- aggressive).</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">A positive value
- indicates that task is on schedule, and callback functions have
- enough time to finish before the next scheduled pass.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">#define
- <B>_TASK_SLEEP_ON_IDLE_RUN</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in">...will compile the
- library with the <B>sleep</B> option enabled (AVR boards only).</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">When enabled, scheduler
- will put the microcontroller into <B>SLEEP_MODE_IDLE</B> state if
- none of the tasks’ callback functions were activated during pass.
- <B>IDLE</B> state is interrupted by timers once every 1 ms. Helps
- conserve power. Device in SLEEP_MODE_IDLE wakes up to all hardware
- and timer interrupts, so scheduling is kept current.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">#define
- <B>_TASK_STATUS_REQUEST</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in">…will compile
- TaskScheduler with support for StatusRequest object. Status Requests
- are objects allowing tasks to wait on an event, and signal event
- completion to each other.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>NOTE: above
- parameters are DISABLED by default, and need to be explicitly
- enabled.</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>API DOCUMENTATION:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>TASKS:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">CREATION:</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>Task();</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
- constructor.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
- no parameters and creates a task that could be scheduled to run at
- every scheduling pass indefinitely, but does not have a callback
- function defined, so no execution will actually take place.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">All
- tasks are created <B>disabled</B> by default.</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </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, 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
- with parameters.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Creates
- a task that is scheduled to run every <aInterval> milliseconds,
- <aIterations> times, executing <aCallback> function on
- every pass.
- </P>
- <OL>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in">aInterval is in
- milliseconds (<B>default = 0)</B></P>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in">aIteration in
- 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 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>
- <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>
- <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>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">All
- tasks are created <B>disabled</B> by default (unless aEnable = true).
- You have to explicitly enable the task for execution.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enabled
- task is scheduled for execution immediately. Enable tasks with delay
- (standard execution interval or specific execution interval) in order
- to defer first run of the task.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>Task(void (*aCallback)(), Scheduler* aScheduler, 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">If
- compiled with support for Status Request objects, this constructor
- creates a Task for activation on event (since such tasks must run
- <B>waitFor() </B>method, their <I>interval</I>, <I>iteration</I> and
- <I>enabled</I> status will be set by that method.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>INFORMATION</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">The
- following 3 “getter” functions return task status
- (enabled/disabled), execution interval in milliseconds, number of
- <I><B>remaining</B></I> iterations.
- </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>bool
- isEnabled() </B>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>unsigned
- long getInterval()</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>long
- getIterations() </B>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>long getOverrun()</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
- library is compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
- enabled, tasks are monitored for “long running” scenario. A “long
- running” task is a task that does not finish processing its
- callback functions quickly, and thus creates a situation for itself
- and other tasks where they don't run on a scheduled interval, but
- rather “catch up” and are behind. When task scheduler sets the
- next execution target time, it adds Task's execution interval to the
- previously scheduled execution time:</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <B>next
- execution time = previous execution time + task execution interval</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">If
- <B>next execution time</B> happens to be already in the past (<B>next
- execution time</B> < <B>millis()</B>), then task is considered
- <I><B>overrun</B></I>. <B>GetOverrun</B> function returns number of
- milliseconds between next execution time and current time. If the
- <B>value is negative</B>, the task is overrun by that many
- milliseconds.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Positive
- value indicate number of milliseconds of slack this task has for
- 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 limited number of iterations only, indicates whether
- current pass is the last iteration.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>CONTROL:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void enable();</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, and schedules it for immediate execution (without delay) at
- this or next scheduling pass depending on when the task was enabled.
- Scheduler will execute the next pass without any delay because there
- 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>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Schedules
- the task for execution after a delay (aInterval), but does not change
- 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>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables
- the task, and schedules it for execution after a delay (aInterval).
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void enableDelayed
- (unsigned long aDelay);</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, and schedules it for execution after a specific delay
- (aDelay, which maybe different from aInterval).
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void restart();</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">For
- tasks with limited number of iterations only, <B>restart</B> function
- will re-enable the task, set the number of iterations back to when
- the task was created and and schedule the task for execution as soon
- as possible.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void restartDelayed
- (unsigned long aDelay);</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Same
- as <B>restart() </B>function, with the only difference being that
- 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>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)() , 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 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 five “setter”
- functions allow changes of individual task execution control
- parameters.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
- setInterval (unsigned long aInterval) </B>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
- setIterations (long aIterations) </B>
- </P>
- <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
- execution time calculation takes place <B>after</B> the callback
- function is called, so new interval will be used immediately by the
- 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>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; page-break-after: avoid">
- <B>void waitFor(StatusRequest* aStatusRequest);</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
- compiled with support for Status Requests, this method makes task
- wait for the completion of <B>aStatusRequest</B> event.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>waitFor()
- </B>sets tasks interval to <B>0 (zero)</B> for immediate execution
- when event happens, and also sets the number of <B>iterations to 1</B>.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
- aStatusRequest</B> should be “activated” by calling <B>setWaiting()
- </B>method before making a task wait on it. Otherwise, the task will
- execute immediately.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>StatusRequest*
- getStatusRequest()</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
- a StatusReqeust object this Task was waiting on.
- </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"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>TASK SCHEDULER:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>CREATION:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>Scheduler()</B><BR><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
- constructor.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
- no parameters. Creates task scheduler with default parameters and an
- empty task queue.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void init()</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">Initializes
- the task queue and scheduler parameters, Executed as part of
- constructor, so don't need to be explicitly called after creation.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
- </B>be default (if compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
- enabled) scheduler is allowed to put processor to IDLE sleep mode. If
- this behavior was changed via <B>allowSleep() </B>function, <B>inti()
- </B>will <B>NOT</B> reset allow sleep particular parameter.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void
- addTask(Task& aTask)</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">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 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 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 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>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Deletes
- task aTask from the execution chain. The chain of remaining tasks is
- linked together (i.e</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">if
- original task chain is 1 → 2 → 3 → 4, deleting 3 will result in
- 1 → 2 → 4).</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
- </B>it is not required to delete a task from the chain. A disabled
- task will not be executed anyway, but you save a few microseconds per
- scheduling pass by deleting it, since it is not even considered for
- execution.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">An
- example of proper use of this function would be running some sort of
- <B>initialize</B> task in the chain, and then deleting it from the
- chain since it only needs to run once.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void allowSleep(bool
- aState) </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">Available
- in API only if compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
- enabled. Controls whether scheduler is allowed (<B>aState =true</B>),
- or not (<B>aState =false</B>) to put processor into IDLE sleep mode
- in case not tasks are scheduled to run.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">The
- <B>default</B> behavior of scheduler upon creation is to allow sleep
- mode.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void enableAll()</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void disableAll()</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">enables
- and disables (respectively) all tasks in the chain. Convenient if
- your need to enable/disable majority of the tasks (i.e. disable all
- and then enable one).
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>Task&
- 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 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>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Executes
- one scheduling pass, including end-of-pass sleep. This function
- typically placed inside the <B>loop()</B> function of the sketch.
- Since <B>execute</B> exits after every pass, you can put additional
- statements after <B>execute</B> inside the <B>loop()</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"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>STATUS REQUEST:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>CREATION:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>StatusRequest()</B><BR><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
- constructor.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
- no parameters. Creates Status Request object, which is assigned a
- status of “completed” on creation.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
- setWaiting(unsigned int aCount)</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Activates
- Status Request object. By default each object is set to wait on one
- event only, however, if <B>aCount</B> is supplied, Status Request can
- wait on multiple events. For instance, <B>setWaiting(3)</B> will wait
- on three signals. An example could be waiting for completion of
- measurements from 3 sensors.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool signal(int
- aStatus)</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Signals
- completion of the event to the Status Request object, and passes a
- completion code, which could be interrogated later.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
- </B> passing a <B>negative</B> status code to the status request
- object is considered reporting an error condition, and will complete
- the status request regardless of how many outstanding signals it is
- still waiting for.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note</B>:
- only the latest status code is kept.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool signalComplete
- (int aStatus)</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Signals
- completion of <B>ALL</B> events to the Status Request object, and
- passes a completion code, which could be interrogated later. The
- status request completes regardless of how many events it is still
- waiting on.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool pending() </B>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
- <B>true</B> if status request is still waiting for event or events to
- happen.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool completed () </B>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
- <B>true</B> if status has completed.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><B>int getStatus()</B></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
- the status code passed to the status request object by the <B>signal()
- </B>and <B>signalComplete() </B>methods.
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Any
- <B>positive</B> number is considered a successful completion status.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">A
- 0 (zero) is considered a default successful completion status.</P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Any
- <B>negative</B> number is considered an error code and unsuccessful
- completion of a request.</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"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
- <B>IMPLEMENTATION SCENARIOS AND IDEAS:</B></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <OL>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in"><B>EVENT DRIVEN
- PROGRAMMING</B></P>
- </OL>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Each of the processes
- of your application becomes a separate and distinct programming area,
- which may or may not interact and control each other.
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Example:
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">In a plant watering
- system you need to measure soil humidity, control pump and display
- the results</P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Each of the areas
- becomes a task:</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- <B>tMeasure</B> (TMEASURE_INTERVAL*SECOND, -1,
- &measureCallback);<BR>Task <B>tWater</B>
- (TWATER_INTERVAL*SECOND, RETRIES, &waterCallback);<BR>Task
- <B>tDisplay</B> (TDISPLAY_INTERVAL*SECOND, -1, &displayCallback);
- <BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
- </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>taskManager</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>;</FONT></FONT><BR><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Further, once you turn
- on the pump, you keep it running for TWATER_INTERVAL interval and
- then turn it off. Turning off a pump is also a task which only needs
- to run once for every time the pump is turned on:</P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>tWaterOff</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>
- (WATERTIME*SECOND, 1,</FONT></FONT><FONT FACE="Courier New, monospace">
- &waterOffCallback);</FONT><BR><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in">Example of the callback
- function:</P>
- <P CLASS="western" STYLE="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
- waterOffCallback() {<BR> motorOff();<BR>
- tWater.enableDelayed();<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"><FONT FACE="Courier New, monospace"><FONT SIZE=2>or</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
- waterCallback() {<BR> if (tWater.getIterations()) {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- If this is not the last iteration = turn the pump on<BR>
- motorOn();<BR> tWaterOff.set(parameters.watertime * SECOND, 1,
- &waterOffCallback);<BR> tWaterOff.enableDelayed();<BR>
- return;<BR> }</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- We could not reach target humidity – something is wrong<BR>
- motorOff;<BR> taskManager.disableAll();<BR> tError.enable();<BR>}</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Your
- sample <B>setup</B>() and <B>loop</B>() (partially) are as follows. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Note:
- </B>please note that tWater is <B>not</B> activated during setup().
- It is activated by tMeasure callback once the watering conditions are
- met. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"> </FONT><FONT FACE="Courier New, monospace">setup()</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Courier New, monospace">
- ...</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace">tWater.setIterations(parameters.retries);<BR>
- tWaterOff.setInterval(parameters.watertime * SECOND);<BR><BR><BR>
- taskManager.init();<BR> taskManager.addTask(tMeasure);<BR>
- taskManager.addTask(tDisplay);<BR> taskManager.addTask(tWater);<BR>
- taskManager.addTask(tWaterOff);<BR> <BR> tMeasure.enable();<BR>
- tDisplay.enable();<BR><BR> currentHumidity =
- measureHumidity();<BR>}<BR><BR><BR>void loop ()<BR>{<BR>
- taskManager.execute();<BR>}</FONT><FONT FACE="Times New Roman, serif"><BR></FONT><BR>
- </P>
- <OL START=2>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in">“<FONT FACE="Times New Roman, serif"><B>NATIVE”
- SUPPORT FOR FINITE STATE MACHINE</B></FONT></P>
- </OL>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Define
- “states” as callback function or functions. Each callback
- function executes activities specific to a “state” and then
- “transitions” to the next state by assigning next callback
- function to the task. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Transition
- from one state to the next is achieved by setting next callback
- function at the end of preceding one. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Note:
- </B>do not call the next callback function. Let the schedule take
- care of that during the next pass. (Thus letting other tasks run). </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Example:
- Blinking LED 2 times a second could be achieved this way</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">Task
- tLedBlinker (500, -1, &ledOnCallback);</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">Scheduler
- taskManager;</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">void
- ledOnCallback() {</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> turnLedOn();</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.setCallback(&ledOffCallback);</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</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">void
- ledOffCallback() {</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> turnLedOff();</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.setCallback(&ledOnCallback);</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</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">setup()
- {</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> taskManager.init();<BR>
- taskManager.addTask(tLedBlinker);</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> </FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.enable();</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</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">loop
- () {</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> taskManager.execute();</FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</FONT><FONT FACE="Times New Roman, serif"><BR></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Obviously
- the example is simple, but gives the idea of how the tasks could be
- used to go through states.</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <OL START=3>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>MULTIPLE
- POSSIBLE CALLBACKS FOR TASK</B></FONT></P>
- </OL>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">There
- may be a need to select an option for callback function based on
- certain criteria, or randomly. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">You
- can achieve that by defining an array of callback function pointers
- and selecting one based on the criteria you need. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Example:
- when a robot detects an obstacle, it may go left, right backwards,
- etc. Each of the “directions” or “behaviors” are represented
- by a different callback function. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Another
- example of using multiple callbacks:</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">You
- may need to “initialize” variables for a particular task.</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">In
- this case, define a tasks with two callbacks:</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- <B>tWork</B> (T_INTERVAL, -1, &workCallbackInit);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">…</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
- workCallbackInit() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
- do your initializationstuff here</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"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
- finally assigne the main callback function </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.setCallback(&workCallback);</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
- workCallback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
- main callback function</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"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">The
- task will initialize during first execution pass and switch to
- “regular” callback execution starting with second pass. There is
- a delay between first and second passes of the task (scheduling
- period, if defined). In order to execute the second pass immediately
- after initialization first pass, change the above code like this:</FONT></P>
- <P CLASS="western" STYLE="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
- workCallbackInit() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
- do your initializationstuff here</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"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
- finally assigne the main callback function </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.setCallback(&workCallback);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.enable();</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-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">The
- task will run initialization first, then immediately second pass, and
- then switch to processing at regular intervals starting with a third
- pass. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <OL START=3>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>INTERRUP-DRIVEN
- EXECUTION SUPPORT </B></FONT>
- </P>
- </OL>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">In
- case of interrupt-driven program flow, tasks could be scheduled to
- run once to request asynchronous execution (request), and then
- re-enabled (restarted) again with a different callback function to
- process the results. </FONT>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Example</B>:
- event driven distance calculation for ultrasonic pulses. EchoPin #6
- triggers pin change interrupts on rising and falling edges to
- determine the length of ultrasonic pulse.</FONT></P>
- <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#include
- <DirectIO.h><BR>#include <TaskScheduler.h><BR>#include
- <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, &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>
- pTrigger = LOW; <BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tPing.restartDelayed();
- // timeout countdown starts now<BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- will start the pulse clock on the rising edge of ECHO pin</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>PCintPort::attachInterrupt(ECHOPIN,
- &pingStartClock, RISING); <BR>}<BR><BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- Start clock on the <B>rising</B> edge of the ultrasonic pulse<BR>void
- pingStartClock() {<BR> pulseStart = micros();<BR>
- PCintPort::detachInterrupt(ECHOPIN); // not sure this is necessary<BR>
- PCintPort::attachInterrupt(ECHOPIN, &pingStopClock, FALLING); <BR>
- tPing.restartDelayed();<BR>}<BR><BR>// Stop clock on the <B>falling</B>
- edge of the ultrasonic pulse<BR>void pingStopClock() {<BR> pulseStop
- = micros();<BR> PcintPort::detachInterrupt(ECHOPIN);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>pingDistance =
- pulseStop - pulseStart;<BR> pulseBusy = false;<BR> tPing.disable();
- // disable timeout<BR>}<BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- Stop clock because of the timeout – the wave did not return<BR>void
- pingCalcCallback() {<BR> if (pulseBusy) {<BR> pingStopClock();<BR>
- }<BR> pulseTimeout = true;<BR>}<BR><BR><BR><BR>// Initial measure
- callback sets the trigger<BR>void measureCallback() {<BR> if
- (pulseBusy) { // already measuring, try again<BR>
- tMeasure.enable();<BR> return;<BR> }<BR> pingTrigger(30); // 30
- milliseconds or max range of ~5.1 meters<BR>
- tMeasure.setCallback(&measureCallbackWait);<BR>}<BR></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
- Wait for the measurement to <BR>void measureCallbackWait() {<BR> if
- (pulseBusy) return;<BR> tMeasure.setCallback(&measureCallback);
- <BR>}<BR><BR><BR>bool state = true;<BR><BR>void displayCallback() {<BR>
- char d[256];<BR> <BR> unsigned long cm = pingDistance * 17 / 100;
- // cm<BR> <BR> snprintf(d, 256, "pulseStart =
- %8lu\tpulseStop=%8lu\tdistance, cm=%8lu", pulseStart, pulseStop,
- 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>}<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></FONT></FONT><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
- _TASK_SLEEP_ON_IDLE_RUN</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#include
- <TaskScheduler.h></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>#define
- LEDPIN 13</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>Scheduler
- ts;</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>Task
- tWrapper(30000, -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>Serial.println("In
- 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>Serial.println("In
- 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>Serial.println("In
- 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>Serial.println("In
- 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>Serial.println("In
- 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() {</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>Serial.begin(115200);
- </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>pinMode(LEDPIN,
- OUTPUT); </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
- loop() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>// put your main
- code here, to run repeatedly:</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>ts.execute();</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"><BR>
- </P>
- <OL START=3>
- <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>USING
- STATUS REQUEST OBJECTS </B></FONT>
- </P>
- </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"><FONT SIZE=2 STYLE="font-size: 11pt">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.</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="Times New Roman, serif"><FONT SIZE=2 STYLE="font-size: 11pt">The
- overall timeout of 1 second is setup as well.</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><FONT SIZE=2 STYLE="font-size: 11pt">An
- error message needs to be printed if a timeout occurred instead of a
- value.</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </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>#define
- _TASK_SLEEP_ON_IDLE_RUN</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
- _TASK_STATUS_REQUEST</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>#include
- <TaskScheduler.h></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>StatusRequest
- measure;</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>Scheduler
- ts; </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>Task
- tCycle(10000, -1, &CycleCallback, &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
- tMeasure(1000, 1, &MeasureCallback, &ts, false,
- &MeasureEnable, &MeasureDisable);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- tCalculate(&CalcCallback, &ts);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- tSensor1(0, 1, &S1Callback, &ts, false, &S1Enable);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- tSensor2(0, 1, &S2Callback, &ts, false, &S2Enable);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
- tSensor3(0, 1, &S3Callback, &ts, false, &S3Enable);</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>long
- distance, d1, d2, d3;</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
- CycleCallback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("CycleCallback:
- Initiating measurement cycle every 10 seconds");</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>tMeasure.restartDelayed();</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"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
- MeasureEnable() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("MeasureEnable:
- Activating sensors"); </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>distance = 0;</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.setWaiting(3);
- // Set the StatusRequest to wait for 3 signals. </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tCalculate.waitFor(&measure);</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>tSensor1.restart();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor2.restart();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor3.restart();</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;</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
- MeasureCallback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("MeasureCallback:
- Invoked by calculate task or one second later"); </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>if
- (measure.pending()) {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tCalculate.disable();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signalComplete(-1);
- // signal error</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("MeasureCallback:
- Timeout!");</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">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>else {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("MeasureCallback:
- Min distance=");Serial.println(distance);</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"><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
- MeasureDisable() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("MeasureDisable:
- Cleaning up"); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor1.disable();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor2.disable();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor3.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"><BR>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
- CalcCallback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("CalcCallback:
- calculating"); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = -1;</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>if (
- measure.getStatus() >= 0) { // only calculate if statusrequest
- ended successfully</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = d1 <
- d2 ? d1 : d2;</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = d3 <
- distance ? d3 : distance;</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>tMeasure.forceNextIteration();</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"><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>/**
- Simulation code for sensor 1</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">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
- S1Enable() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S1Enable:
- Triggering sensor1. Delay="); </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>tSensor1.setInterval(
- random(1200) ); // Simulating sensor delay, which could go over 1
- second and cause timeout</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d1 = 0;</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(
- tSensor1.getInterval() );</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</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
- S1Callback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S1Callback:
- Emulating measurement. d1="); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d1 = random(501); //
- pick a value from 0 to 500 "centimeters" simulating a
- measurement </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(d1); </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>/**
- Simulation code for sensor 2</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">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
- S2Enable() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S2Enable:
- Triggering sensor2. Delay="); </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>tSensor2.setInterval(
- random(1200) ); // Simulating sensor delay, which could go over 1
- second and cause timeout</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d2 = 0;</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>Serial.println(
- tSensor2.getInterval() );</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</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
- S2Callback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S2Callback:
- Emulating measurement. d2="); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d2 = random(501); //
- pick a value from 0 to 500 "centimeters" simulating a
- measurement</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</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>Serial.println(d2);
- </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>/**
- Simulation code for sensor 3</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">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
- S3Enable() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S3Enable:
- Triggering sensor3. Delay="); </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>tSensor3.setInterval(
- random(1200) ); // Simulating sensor delay, which could go over 1
- second and cause timeout</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d3 = 0;</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>Serial.println(
- tSensor3.getInterval() );</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</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
- S3Callback() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print("S3Callback:
- Emulating measurement. d3="); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>d3 = random(501); //
- pick a value from 0 to 500 "centimeters" simulating a
- measurement</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(d3); </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>/**
- Main Arduino code</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <FONT FACE="Courier New, monospace"><FONT SIZE=2>*
- Not much is left here - everything is taken care of by the framework</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"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
- setup() {</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>Serial.begin(115200);</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println("TaskScheduler
- StatusRequest Sensor Emulation Test. Complex Test."); </FONT></FONT>
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>randomSeed(analogRead(A1)+millis());</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
- loop() {</FONT></FONT></P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- </P>
- <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
- <FONT FACE="Courier New, monospace"><FONT SIZE=2>ts.execute();</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>}</FONT></FONT></P>
- </BODY>
- </HTML>
|