TaskScheduler.html 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <HTML>
  3. <HEAD>
  4. <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
  5. <TITLE></TITLE>
  6. <META NAME="GENERATOR" CONTENT="LibreOffice 3.5 (Linux)">
  7. <META NAME="CREATED" CONTENT="20150206;16300000">
  8. <META NAME="CHANGEDBY" CONTENT="Anatoli Arkhipenko">
  9. <META NAME="CHANGED" CONTENT="20151015;23250000">
  10. <META NAME="Info 1" CONTENT="">
  11. <META NAME="Info 2" CONTENT="">
  12. <META NAME="Info 3" CONTENT="">
  13. <META NAME="Info 4" CONTENT="">
  14. <STYLE TYPE="text/css">
  15. <!--
  16. @page { margin: 0.79in }
  17. P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 0; orphans: 0 }
  18. P.western { font-family: "Liberation Serif", "MS PMincho", serif; font-size: 12pt; so-language: en-US }
  19. P.cjk { font-family: "WenQuanYi Micro Hei", "MS Mincho"; font-size: 12pt; so-language: zh-CN }
  20. P.ctl { font-family: "Lohit Hindi", "MS Mincho"; font-size: 12pt; so-language: hi-IN }
  21. -->
  22. </STYLE>
  23. </HEAD>
  24. <BODY LANG="en-US" TEXT="#000000" BGCOLOR="#ffffff" DIR="LTR">
  25. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Task Scheduler –
  26. cooperative multitasking for Arduino microcontrollers</B></P>
  27. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Version 1.8.0:
  28. 2015-10-15</B></P>
  29. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  30. </P>
  31. <P CLASS="western" STYLE="margin-bottom: 0in"><B>OVERVIEW</B>:</P>
  32. <P CLASS="western" STYLE="margin-bottom: 0in">A lightweight
  33. implementation of cooperative multitasking (task scheduling)
  34. supporting:</P>
  35. <OL>
  36. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Periodic task
  37. execution (with dynamic execution period in milliseconds)</P>
  38. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Number of
  39. iterations (n times)</P>
  40. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Execution of tasks
  41. in predefined sequence</P>
  42. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Dynamic change of
  43. task execution parameters (frequency, number of iterations, callback
  44. function)</P>
  45. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Power saving via
  46. entering IDLE sleep mode between tasks are scheduled to run</P>
  47. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Support for task
  48. invocation via Status Request object</P>
  49. </OL>
  50. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  51. </P>
  52. <P CLASS="western" STYLE="margin-bottom: 0in"><B>TASK</B>:</P>
  53. <P CLASS="western" STYLE="margin-bottom: 0in">“Task” is a
  54. container concept that links together:</P>
  55. <OL>
  56. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Execution interval</P>
  57. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Execution event
  58. (Status Request)</P>
  59. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Number of
  60. execution iterations</P>
  61. <LI><P CLASS="western" STYLE="margin-bottom: 0in">Piece of code
  62. performing task activities (callback functions)</P>
  63. </OL>
  64. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  65. </P>
  66. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Tasks</B> are linked
  67. into execution <B>chains</B>, which are processed by the “Scheduler”
  68. in the order they are linked.</P>
  69. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  70. </P>
  71. <P CLASS="western" STYLE="margin-bottom: 0in">Each task performs its
  72. function via callback function. Scheduler calls Task’s callback
  73. function periodically until task is disabled or task runs out of
  74. iterations. In addition to “regular” callback, two methods could
  75. be enabled for each task: a callback function invoked once when task
  76. is enabled, and a callback function invoked once when the task is
  77. disabled. Those two special methods allows task to properly initiate
  78. themselves for execution and clean-up after execution is over.
  79. </P>
  80. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  81. </P>
  82. <P CLASS="western" STYLE="margin-bottom: 0in">Tasks are responsible
  83. for supporting <B>cooperative</B> <B>multitasking</B> by being “good
  84. neighbors”, i.e., running their callback functions quickly in a
  85. non-blocking way and releasing control as soon as possible.
  86. </P>
  87. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  88. </P>
  89. <P CLASS="western" STYLE="margin-bottom: 0in">“Scheduler” is
  90. executing Tasks' callback functions in the order the tasks were added
  91. to the chain, from first to last. Scheduler stops and exists after
  92. processing the chain once in order to allow other statements in the
  93. main code of <B>loop()</B> function to run. This <B>a “scheduling
  94. pass”.</B></P>
  95. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  96. </P>
  97. <P CLASS="western" STYLE="margin-bottom: 0in">If compiled with
  98. <FONT FACE="Courier New, monospace">_TASK_SLEEP_ON_IDLE_RUN</FONT>
  99. enabled, the scheduler will place processor into IDLE sleep mode (for
  100. approximately 1 ms, as the timer interrupt will wake it up), after
  101. what is determined to be an “idle” pass. An Idle Pass is a pass
  102. through the task chain when no Tasks were scheduled to run their
  103. callback functions. This is done to avoid repetitive empty passes
  104. through the chain when no tasks need to be executed. If any of the
  105. tasks in the chain always requires immediate execution (aInterval =
  106. 0), then there will be no IDLE sleep between task callback execution.</P>
  107. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  108. </P>
  109. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  110. <B>Below is the flowchart of a Task lifecycle:</B></P>
  111. <P CLASS="western" STYLE="margin-bottom: 0in"><IMG SRC="TaskScheduler_html.png" NAME="graphics1" ALIGN=BOTTOM WIDTH=664 HEIGHT=747 BORDER=0></P>
  112. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  113. </P>
  114. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Task
  115. Scheduler uses <B>millis()</B> to determine if tasks are ready to be
  116. invoked. Therefore, if you put your device to any “deep” sleep
  117. mode disabling timer interrupts, the <B>millis()</B> count will be
  118. suspended, leading to effective suspension of scheduling. Upon wake
  119. up, active tasks need to be re-enabled, which will effectively reset
  120. their internal time scheduling variables to the new value of
  121. <B>millis(). </B>Time spent in deep sleep mode should be considered
  122. “frozen”, i.e., if a task was scheduled to run in 1 second from
  123. now, and device was put to sleep for 5 minutes, upon wake up, the
  124. task will still be scheduled 1 second from the time of wake up.
  125. Executing <B>enable() </B>function on this tasks will make it run as
  126. soon as possible. This is a concern only for tasks which are required
  127. to run in a truly periodical manner (in absolute time terms).
  128. </P>
  129. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  130. </P>
  131. <P CLASS="western" STYLE="margin-bottom: 0in">In addition to
  132. time-only invocation, tasks can be scheduled to wait on an event
  133. employing StatusRequest objects (more about Status Requests later).</P>
  134. <P CLASS="western" STYLE="margin-bottom: 0in">Consider a scenario
  135. when one task (t1) is performing a function which affects execution
  136. of many tasks (t2, t3). In this case the task t1 will “signal”
  137. completion of its function via Status Request object. Tasks t2 and t3
  138. are “waiting” on the same Status Request object. As soon as
  139. status request completes, t2 and t3 are activated.</P>
  140. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  141. </P>
  142. <P CLASS="western" STYLE="margin-bottom: 0in">Alternative scenario is
  143. the ne task (t1) and waiting for the completion of a number of tasks
  144. (t2, t3). When done, t2 and t3 signal completion of their functions,
  145. t1 is invoked.
  146. </P>
  147. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  148. </P>
  149. <P CLASS="western" STYLE="margin-bottom: 0in">Please see the examples
  150. at the end of this document.</P>
  151. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  152. </P>
  153. <P CLASS="western" STYLE="margin-bottom: 0in"><B>COMPILE PARAMETERS:</B></P>
  154. <P CLASS="western" STYLE="margin-bottom: 0in">This library could be
  155. compiled with several options.
  156. </P>
  157. <P CLASS="western" STYLE="margin-bottom: 0in">These parameters must
  158. be defined before inclusion of the library header file into the
  159. sketch.</P>
  160. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  161. </P>
  162. <P CLASS="western" STYLE="margin-bottom: 0in">#define
  163. <B>_TASK_TIMECRITICAL</B></P>
  164. <P CLASS="western" STYLE="margin-bottom: 0in">...will compile the
  165. library with time critical tracking option enabled.</P>
  166. <P CLASS="western" STYLE="margin-bottom: 0in">Time critical option
  167. keeps track where next execution time of the task falls, and makes it
  168. available via API through Task::<B> getOverrun() </B>function. If
  169. <B>getOverrun </B>returns a negative value, this Task’s next
  170. execution time is in the past, and task is behind schedule. This most
  171. probably means that either task’s callback function runtime is too
  172. long, or the execution interval is too short (then schedule is too
  173. aggressive).</P>
  174. <P CLASS="western" STYLE="margin-bottom: 0in">A positive value
  175. indicates that task is on schedule, and callback functions have
  176. enough time to finish before the next scheduled pass.
  177. </P>
  178. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  179. </P>
  180. <P CLASS="western" STYLE="margin-bottom: 0in">#define
  181. <B>_TASK_SLEEP_ON_IDLE_RUN</B></P>
  182. <P CLASS="western" STYLE="margin-bottom: 0in">...will compile the
  183. library with the <B>sleep</B> option enabled (AVR boards only).</P>
  184. <P CLASS="western" STYLE="margin-bottom: 0in">When enabled, scheduler
  185. will put the microcontroller into <B>SLEEP_MODE_IDLE</B> state if
  186. none of the tasks’ callback functions were activated during pass.
  187. <B>IDLE</B> state is interrupted by timers once every 1 ms. Helps
  188. conserve power. Device in SLEEP_MODE_IDLE wakes up to all hardware
  189. and timer interrupts, so scheduling is kept current.</P>
  190. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  191. </P>
  192. <P CLASS="western" STYLE="margin-bottom: 0in">#define
  193. <B>_TASK_STATUS_REQUEST</B></P>
  194. <P CLASS="western" STYLE="margin-bottom: 0in">…will compile
  195. TaskScheduler with support for StatusRequest object. Status Requests
  196. are objects allowing tasks to wait on an event, and signal event
  197. completion to each other.
  198. </P>
  199. <P CLASS="western" STYLE="margin-bottom: 0in">
  200. </P>
  201. <P CLASS="western" STYLE="margin-bottom: 0in"><B>NOTE: above
  202. parameters are DISABLED by default, and need to be explicitly
  203. enabled.</B></P>
  204. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  205. </P>
  206. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  207. </P>
  208. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  209. </P>
  210. <P CLASS="western" STYLE="margin-bottom: 0in"><B>API DOCUMENTATION:</B></P>
  211. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  212. </P>
  213. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  214. <B>TASKS:</B></P>
  215. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  216. </P>
  217. <P CLASS="western" STYLE="margin-bottom: 0in">CREATION:</P>
  218. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Task();</B></P>
  219. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  220. </P>
  221. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
  222. constructor.
  223. </P>
  224. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
  225. no parameters and creates a task that could be scheduled to run at
  226. every scheduling pass indefinitely, but does not have a callback
  227. function defined, so no execution will actually take place.
  228. </P>
  229. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">All
  230. tasks are created <B>disabled</B> by default.</P>
  231. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  232. </P>
  233. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  234. <B>Task(unsigned long aInterval, long aIterations, void
  235. (*aCallback)(), Scheduler* aScheduler, bool aEnable, bool
  236. (*aOnEnable)(), void (*aOnDisable)())</B></P>
  237. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  238. </P>
  239. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Constructor
  240. with parameters.
  241. </P>
  242. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Creates
  243. a task that is scheduled to run every &lt;aInterval&gt; milliseconds,
  244. &lt;aIterations&gt; times, executing &lt;aCallback&gt; function on
  245. every pass.
  246. </P>
  247. <OL>
  248. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aInterval is in
  249. milliseconds (<B>default = 0)</B></P>
  250. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aIteration in
  251. number of times, -1 for indefinite execution (<B>default = -1)</B><BR><B>Note:
  252. </B>Tasks do not remember the number of iteration set initially.
  253. After the iterations are done, internal iteration counter is 0. If
  254. you need to perform another set of iterations, you need to set the
  255. number of iterations again. <BR><B>Note: </B>Tasks which performed
  256. all their iterations remain active.
  257. </P>
  258. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aCallback is a
  259. pointer to a void callback function without parameters (<B>default =
  260. NULL)</B></P>
  261. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aScheduler –
  262. <B>optional</B> reference to existing scheduler. If supplied (not
  263. NULL) this task will be appended to the task chain of the current
  264. scheduler). (<B>default = NULL)</B></P>
  265. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aEnable –
  266. <B>optional</B>. Value of <B>true </B>will create task enabled.
  267. (<B>default = false)</B></P>
  268. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aOnEnable is a
  269. pointer to a bool callback function without parameters, invoked when
  270. task is enabled. If OnEnable function returns <B>true</B>, task is
  271. enabled. If <B>OnEnable</B> function return <B>false</B>, task
  272. remains disabled (<B>default = NULL)</B></P>
  273. <LI><P CLASS="western" STYLE="margin-bottom: 0in">aOnDisable is a
  274. pointer to a void callback function without parameters, invoked when
  275. task is disabled (<B>default = NULL)</B></P>
  276. </OL>
  277. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  278. </P>
  279. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">All
  280. tasks are created <B>disabled</B> by default (unless aEnable = true).
  281. You have to explicitly enable the task for execution.</P>
  282. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enabled
  283. task is scheduled for execution immediately. Enable tasks with delay
  284. (standard execution interval or specific execution interval) in order
  285. to defer first run of the task.</P>
  286. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  287. </P>
  288. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  289. <B>Task(void (*aCallback)(), Scheduler* aScheduler, bool
  290. (*aOnEnable)(), void (*aOnDisable)())</B></P>
  291. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  292. </P>
  293. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  294. compiled with support for Status Request objects, this constructor
  295. creates a Task for activation on event (since such tasks must run
  296. <B>waitFor() </B>method, their <I>interval</I>, <I>iteration</I> and
  297. <I>enabled</I> status will be set by that method.</P>
  298. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  299. </P>
  300. <P CLASS="western" STYLE="margin-bottom: 0in"><B>INFORMATION</B></P>
  301. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">The
  302. following 3 “getter” functions return task status
  303. (enabled/disabled), execution interval in milliseconds, number of
  304. <I><B>remaining</B></I> iterations.
  305. </P>
  306. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  307. </P>
  308. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>bool
  309. isEnabled() </B>
  310. </P>
  311. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>unsigned
  312. long getInterval()</B></P>
  313. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>long
  314. getIterations() </B>
  315. </P>
  316. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  317. </P>
  318. <P CLASS="western" STYLE="margin-bottom: 0in"><B>long getOverrun()</B></P>
  319. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  320. library is compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
  321. enabled, tasks are monitored for “long running” scenario. A “long
  322. running” task is a task that does not finish processing its
  323. callback functions quickly, and thus creates a situation for itself
  324. and other tasks where they don't run on a scheduled interval, but
  325. rather “catch up” and are behind. When task scheduler sets the
  326. next execution target time, it adds Task's execution interval to the
  327. previously scheduled execution time:</P>
  328. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <B>next
  329. execution time = previous execution time + task execution interval</B></P>
  330. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  331. </P>
  332. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  333. <B>next execution time</B> happens to be already in the past (<B>next
  334. execution time</B> &lt; <B>millis()</B>), then task is considered
  335. <I><B>overrun</B></I>. <B>GetOverrun</B> function returns number of
  336. milliseconds between next execution time and current time. If the
  337. <B>value is negative</B>, the task is overrun by that many
  338. milliseconds.
  339. </P>
  340. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Positive
  341. value indicate number of milliseconds of slack this task has for
  342. execution purposes.
  343. </P>
  344. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  345. </P>
  346. <P CLASS="western" STYLE="margin-bottom: 0in"><B>unsigned long
  347. getRunCounter()</B></P>
  348. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  349. the number of the current run. “Current run” is the number of
  350. times a callback function has been invoked since the last time a task
  351. was enabled. <BR><BR>
  352. </P>
  353. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>NOTE:
  354. </B>The <B>runCounter</B> value is incremented <I>before</I> callback
  355. function is invoked. If a task is checking the <B>runCounter</B>
  356. value within its callback function, then the first run value is 1.
  357. </P>
  358. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  359. task T1 is checking the <B>runCounter</B> value of another task (T2)
  360. , then value = 0 indicates that T2 has not been invoked yet, and
  361. value = 1 indicates that T2 has run once.
  362. </P>
  363. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  364. </P>
  365. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool
  366. isFirstIteration()</B></P>
  367. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Indicates
  368. whether current pass is a first iteration of the task.
  369. </P>
  370. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool
  371. isLastIteration()</B></P>
  372. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">For
  373. tasks with a limited number of iterations only, indicates whether
  374. current pass is the last iteration.
  375. </P>
  376. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  377. </P>
  378. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  379. <B>CONTROL:</B></P>
  380. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  381. <BR>
  382. </P>
  383. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void enable();</B></P>
  384. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  385. </P>
  386. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables
  387. the task, and schedules it for immediate execution (without delay) at
  388. this or next scheduling pass depending on when the task was enabled.
  389. Scheduler will execute the next pass without any delay because there
  390. is a task which was enabled and requires execution.
  391. </P>
  392. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  393. </P>
  394. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  395. </B>enable() invokes task’s <B>OnEnable</B> method (if not NULL),
  396. which can prepare task for execution. <B>OnEnable</B> must return a
  397. value of <B>true</B> for task to be enabled. If <B>OnEnable</B>
  398. returns <B>false</B>, task remains disabled. <B>OnEnable</B> is
  399. invoked every time <B>enable</B> is called, regardless if task is
  400. already enabled or not.
  401. </P>
  402. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  403. </P>
  404. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool enableIfNot();</B></P>
  405. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  406. </P>
  407. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables
  408. the task only if it was previously disabled. Returns previous enable
  409. state: <B>true</B> if task was already enabled, and <B>false</B> if
  410. task was disabled.</P>
  411. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  412. </P>
  413. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void delay();</B></P>
  414. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  415. </P>
  416. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Schedules
  417. the task for execution after a delay (aInterval), but does not change
  418. the enabled/disabled status of the task.
  419. </P>
  420. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  421. </P>
  422. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  423. </B>a delay of 0 (zero) will delay task for current execution
  424. interval. Use <B>forceNextIteration() </B>method to force execution
  425. of the task’s callback during immediate next scheduling pass.
  426. </P>
  427. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  428. </P>
  429. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
  430. forceNextIteration();</B></P>
  431. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  432. </P>
  433. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Schedules
  434. the task for execution during immediate next scheduling pass.</P>
  435. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  436. </P>
  437. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  438. </B>Task’s schedule is adjusted to run from this moment in time.
  439. For instance: if a task was running every 10 seconds: 10, 20, 30, ..,
  440. calling <B>forceNextIteration </B>at 44th second of task execution
  441. will make subsequent schedule look like: 44, 54, 64, 74, ..</P>
  442. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  443. </P>
  444. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
  445. enableDelayed();</B></P>
  446. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  447. </P>
  448. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables
  449. the task, and schedules it for execution after a delay (aInterval).
  450. </P>
  451. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  452. </P>
  453. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void enableDelayed
  454. (unsigned long aDelay);</B></P>
  455. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  456. </P>
  457. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Enables
  458. the task, and schedules it for execution after a specific delay
  459. (aDelay, which maybe different from aInterval).
  460. </P>
  461. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  462. </P>
  463. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void restart();</B></P>
  464. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  465. </P>
  466. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">For
  467. tasks with limited number of iterations only, <B>restart</B> function
  468. will re-enable the task, set the number of iterations back to when
  469. the task was created and and schedule the task for execution as soon
  470. as possible.</P>
  471. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  472. </P>
  473. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void restartDelayed
  474. (unsigned long aDelay);</B></P>
  475. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  476. </P>
  477. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Same
  478. as <B>restart() </B>function, with the only difference being that
  479. Task is scheduled to run first iteration after a delay = <B>aDelay</B>
  480. milliseconds.</P>
  481. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  482. </P>
  483. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool disable();</B></P>
  484. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  485. </P>
  486. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Disables
  487. the task. Scheduler will not execute this task any longer, even if it
  488. remains in the chain. Task can be later re-enabled for execution.
  489. </P>
  490. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Return
  491. previous enabled state: <B>true</B> if task was enabled prior to
  492. calling disable, and <B>false</B> otherwise.</P>
  493. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  494. not NULL, task’s <B>OnDisable</B> method is invoked. <B>OnDisable</B>
  495. is invoked only if task was enabled. Calling <B>disable</B> 3 times
  496. for instance will invoke <B>OnDisable</B> only once.</P>
  497. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  498. </P>
  499. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void set(unsigned
  500. long aInterval, long aIterations, void (*aCallback)() , bool
  501. (*aOnEnable)() , void (*aOnDisable)());</B></P>
  502. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  503. </P>
  504. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Allows
  505. dynamic control of task execution parameters in one function call.
  506. </P>
  507. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note</B><B>:
  508. </B>OnEnable and OnDisable parameters can be omitted. In that case
  509. they will be assigned to NULL and not called.
  510. </P>
  511. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  512. </P>
  513. <P CLASS="western" STYLE="margin-bottom: 0in">Next five “setter”
  514. functions allow changes of individual task execution control
  515. parameters.
  516. </P>
  517. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
  518. setInterval (unsigned long aInterval) </B>
  519. </P>
  520. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
  521. setIterations (long aIterations) </B>
  522. </P>
  523. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
  524. setCallback (void (*aCallback)()) </B>
  525. </P>
  526. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
  527. setOnEnable (bool (*aCallback)()) </B>
  528. </P>
  529. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>void
  530. setOnDisable (void (*aCallback)()) </B>
  531. </P>
  532. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  533. </P>
  534. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Next
  535. execution time calculation takes place <B>after</B> the callback
  536. function is called, so new interval will be used immediately by the
  537. scheduler. For the situations when one task is changing the interval
  538. parameter for the other, <B>setInterval</B> function calls <B>delay
  539. </B>explicitly to guarantee schedule change, however it <B>does not
  540. </B>enable the task if task is disabled.</P>
  541. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Note: </B>Tasks that
  542. ran through all their allocated iterations are disabled.
  543. <B>SetIterations()</B> method <B>DOES NOT</B> enable the task. Either
  544. <B>enable</B> explicitly, or use <B>restart</B> methods.
  545. </P>
  546. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  547. </P>
  548. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  549. <B>void waitFor(StatusRequest* aStatusRequest);</B></P>
  550. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  551. <BR>
  552. </P>
  553. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  554. compiled with support for Status Requests, this method makes task
  555. wait for the completion of <B>aStatusRequest</B> event.
  556. </P>
  557. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>waitFor()
  558. </B>sets tasks interval to <B>0 (zero)</B> for immediate execution
  559. when event happens, and also sets the number of <B>iterations to 1</B>.</P>
  560. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  561. aStatusRequest</B> should be “activated” by calling <B>setWaiting()
  562. </B>method before making a task wait on it. Otherwise, the task will
  563. execute immediately.
  564. </P>
  565. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  566. </P>
  567. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  568. </P>
  569. <P CLASS="western" STYLE="margin-bottom: 0in"><B>StatusRequest*
  570. getStatusRequest()</B></P>
  571. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  572. a StatusReqeust object this Task was waiting on.
  573. </P>
  574. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  575. </P>
  576. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  577. </P>
  578. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  579. </P>
  580. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  581. </P>
  582. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  583. <B>TASK SCHEDULER:</B></P>
  584. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  585. </P>
  586. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  587. <B>CREATION:</B></P>
  588. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  589. <BR>
  590. </P>
  591. <P CLASS="western" STYLE="margin-bottom: 0in"><B>Scheduler()</B><BR><BR>
  592. </P>
  593. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
  594. constructor.
  595. </P>
  596. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
  597. no parameters. Creates task scheduler with default parameters and an
  598. empty task queue.
  599. </P>
  600. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  601. </P>
  602. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void init()</B></P>
  603. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  604. </P>
  605. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Initializes
  606. the task queue and scheduler parameters, Executed as part of
  607. constructor, so don't need to be explicitly called after creation.</P>
  608. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  609. </B>be default (if compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
  610. enabled) scheduler is allowed to put processor to IDLE sleep mode. If
  611. this behavior was changed via <B>allowSleep() </B>function, <B>inti()
  612. </B>will <B>NOT</B> reset allow sleep particular parameter.
  613. </P>
  614. <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void
  615. addTask(Task&amp; aTask)</B></P>
  616. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  617. </P>
  618. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Adds
  619. task aTask to the execution queue (or chain) of tasks by appending it
  620. to the end of the chain. If two tasks are scheduled for execution,
  621. the sequence will match the order in which tasks were appended to the
  622. chain. However, in reality, due to different timing of task
  623. execution, the actual order may be different.
  624. </P>
  625. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  626. </B>Currently, changing the execution sequence in a chain dynamically
  627. is not supported.
  628. </P>
  629. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">If
  630. you need to reorder the chain sequence – initialize the scheduler
  631. and re-add the tasks in a different order.
  632. </P>
  633. <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void
  634. deleteTask(Task&amp; aTask)</B></P>
  635. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  636. </P>
  637. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Deletes
  638. task aTask from the execution chain. The chain of remaining tasks is
  639. linked together (i.e</P>
  640. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">if
  641. original task chain is 1 → 2 → 3 → 4, deleting 3 will result in
  642. 1 → 2 → 4).</P>
  643. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  644. </B>it is not required to delete a task from the chain. A disabled
  645. task will not be executed anyway, but you save a few microseconds per
  646. scheduling pass by deleting it, since it is not even considered for
  647. execution.
  648. </P>
  649. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">An
  650. example of proper use of this function would be running some sort of
  651. <B>initialize</B> task in the chain, and then deleting it from the
  652. chain since it only needs to run once.
  653. </P>
  654. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  655. </P>
  656. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void allowSleep(bool
  657. aState) </B>
  658. </P>
  659. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  660. </P>
  661. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Available
  662. in API only if compiled with <FONT FACE="Courier New, monospace">_TASK_TIMECRITICAL</FONT>
  663. enabled. Controls whether scheduler is allowed (<B>aState =true</B>),
  664. or not (<B>aState =false</B>) to put processor into IDLE sleep mode
  665. in case not tasks are scheduled to run.</P>
  666. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">The
  667. <B>default</B> behavior of scheduler upon creation is to allow sleep
  668. mode.
  669. </P>
  670. <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void enableAll()</B></P>
  671. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void disableAll()</B></P>
  672. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  673. </P>
  674. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">enables
  675. and disables (respectively) all tasks in the chain. Convenient if
  676. your need to enable/disable majority of the tasks (i.e. disable all
  677. and then enable one).
  678. </P>
  679. <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>Task&amp;
  680. currentTask()<BR></B><BR>
  681. </P>
  682. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  683. reference to the task, currently executing via <B>execute()</B> loop.
  684. Could be used by callback functions to identify which of the Tasks
  685. invoked callback function.</P>
  686. <P CLASS="western" STYLE="margin-bottom: 0in"><BR><B>void execute()</B></P>
  687. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  688. </P>
  689. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Executes
  690. one scheduling pass, including end-of-pass sleep. This function
  691. typically placed inside the <B>loop()</B> function of the sketch.
  692. Since <B>execute</B> exits after every pass, you can put additional
  693. statements after <B>execute</B> inside the <B>loop()</B>
  694. </P>
  695. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  696. </P>
  697. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  698. </P>
  699. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  700. </P>
  701. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  702. <B>STATUS REQUEST:</B></P>
  703. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  704. <BR>
  705. </P>
  706. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  707. <B>CREATION:</B></P>
  708. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  709. <BR>
  710. </P>
  711. <P CLASS="western" STYLE="margin-bottom: 0in"><B>StatusRequest()</B><BR><BR>
  712. </P>
  713. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Default
  714. constructor.
  715. </P>
  716. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Takes
  717. no parameters. Creates Status Request object, which is assigned a
  718. status of “completed” on creation.
  719. </P>
  720. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  721. </P>
  722. <P CLASS="western" STYLE="margin-bottom: 0in"><B>void
  723. setWaiting(unsigned int aCount)</B></P>
  724. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Activates
  725. Status Request object. By default each object is set to wait on one
  726. event only, however, if <B>aCount</B> is supplied, Status Request can
  727. wait on multiple events. For instance, <B>setWaiting(3)</B> will wait
  728. on three signals. An example could be waiting for completion of
  729. measurements from 3 sensors.
  730. </P>
  731. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  732. </P>
  733. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool signal(int
  734. aStatus)</B></P>
  735. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Signals
  736. completion of the event to the Status Request object, and passes a
  737. completion code, which could be interrogated later.
  738. </P>
  739. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note:
  740. </B> passing a <B>negative</B> status code to the status request
  741. object is considered reporting an error condition, and will complete
  742. the status request regardless of how many outstanding signals it is
  743. still waiting for.
  744. </P>
  745. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><B>Note</B>:
  746. only the latest status code is kept.</P>
  747. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  748. </P>
  749. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool signalComplete
  750. (int aStatus)</B></P>
  751. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Signals
  752. completion of <B>ALL</B> events to the Status Request object, and
  753. passes a completion code, which could be interrogated later. The
  754. status request completes regardless of how many events it is still
  755. waiting on.
  756. </P>
  757. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  758. </P>
  759. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool pending() </B>
  760. </P>
  761. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  762. <B>true</B> if status request is still waiting for event or events to
  763. happen.</P>
  764. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  765. </P>
  766. <P CLASS="western" STYLE="margin-bottom: 0in"><B>bool completed () </B>
  767. </P>
  768. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  769. <B>true</B> if status has completed.</P>
  770. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  771. </P>
  772. <P CLASS="western" STYLE="margin-bottom: 0in"><B>int getStatus()</B></P>
  773. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Returns
  774. the status code passed to the status request object by the <B>signal()
  775. </B>and <B>signalComplete() </B>methods.
  776. </P>
  777. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Any
  778. <B>positive</B> number is considered a successful completion status.</P>
  779. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">A
  780. 0 (zero) is considered a default successful completion status.</P>
  781. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">Any
  782. <B>negative</B> number is considered an error code and unsuccessful
  783. completion of a request.</P>
  784. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  785. </P>
  786. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  787. </P>
  788. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  789. </P>
  790. <P CLASS="western" STYLE="margin-bottom: 0in; page-break-after: avoid">
  791. <B>IMPLEMENTATION SCENARIOS AND IDEAS:</B></P>
  792. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  793. </P>
  794. <OL>
  795. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><B>EVENT DRIVEN
  796. PROGRAMMING</B></P>
  797. </OL>
  798. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  799. </P>
  800. <P CLASS="western" STYLE="margin-bottom: 0in">Each of the processes
  801. of your application becomes a separate and distinct programming area,
  802. which may or may not interact and control each other.
  803. </P>
  804. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  805. </P>
  806. <P CLASS="western" STYLE="margin-bottom: 0in">Example:
  807. </P>
  808. <P CLASS="western" STYLE="margin-bottom: 0in">In a plant watering
  809. system you need to measure soil humidity, control pump and display
  810. the results</P>
  811. <P CLASS="western" STYLE="margin-bottom: 0in">Each of the areas
  812. becomes a task:</P>
  813. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  814. </P>
  815. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  816. <B>tMeasure</B> (TMEASURE_INTERVAL*SECOND, -1,
  817. &amp;measureCallback);<BR>Task <B>tWater</B>
  818. (TWATER_INTERVAL*SECOND, RETRIES, &amp;waterCallback);<BR>Task
  819. <B>tDisplay</B> (TDISPLAY_INTERVAL*SECOND, -1, &amp;displayCallback);
  820. <BR></FONT></FONT><BR>
  821. </P>
  822. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
  823. </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>
  824. </P>
  825. <P CLASS="western" STYLE="margin-bottom: 0in">Further, once you turn
  826. on the pump, you keep it running for TWATER_INTERVAL interval and
  827. then turn it off. Turning off a pump is also a task which only needs
  828. to run once for every time the pump is turned on:</P>
  829. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  830. </P>
  831. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  832. </FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2><B>tWaterOff</B></FONT></FONT><FONT FACE="Courier New, monospace"><FONT SIZE=2>
  833. (WATERTIME*SECOND, 1,</FONT></FONT><FONT FACE="Courier New, monospace">
  834. &amp;waterOffCallback);</FONT><BR><BR>
  835. </P>
  836. <P CLASS="western" STYLE="margin-bottom: 0in">Example of the callback
  837. function:</P>
  838. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  839. </P>
  840. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  841. waterOffCallback() {<BR> motorOff();<BR>
  842. tWater.enableDelayed();<BR>}</FONT></FONT></P>
  843. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  844. </P>
  845. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>or</FONT></FONT></P>
  846. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  847. </P>
  848. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  849. waterCallback() {<BR> if (tWater.getIterations()) {</FONT></FONT></P>
  850. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  851. If this is not the last iteration = turn the pump on<BR>
  852. motorOn();<BR> tWaterOff.set(parameters.watertime * SECOND, 1,
  853. &amp;waterOffCallback);<BR> tWaterOff.enableDelayed();<BR>
  854. return;<BR> }</FONT></FONT></P>
  855. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  856. We could not reach target humidity – something is wrong<BR>
  857. motorOff;<BR> taskManager.disableAll();<BR> tError.enable();<BR>}</FONT></FONT></P>
  858. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  859. </P>
  860. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Your
  861. sample <B>setup</B>() and <B>loop</B>() (partially) are as follows. </FONT>
  862. </P>
  863. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Note:
  864. </B>please note that tWater is <B>not</B> activated during setup().
  865. It is activated by tMeasure callback once the watering conditions are
  866. met. </FONT>
  867. </P>
  868. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  869. </P>
  870. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"> </FONT><FONT FACE="Courier New, monospace">setup()</FONT></P>
  871. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Courier New, monospace">
  872. ...</FONT></P>
  873. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  874. <FONT FACE="Courier New, monospace">tWater.setIterations(parameters.retries);<BR>
  875. tWaterOff.setInterval(parameters.watertime * SECOND);<BR><BR><BR>
  876. taskManager.init();<BR> taskManager.addTask(tMeasure);<BR>
  877. taskManager.addTask(tDisplay);<BR> taskManager.addTask(tWater);<BR>
  878. taskManager.addTask(tWaterOff);<BR> <BR> tMeasure.enable();<BR>
  879. tDisplay.enable();<BR><BR> currentHumidity =
  880. measureHumidity();<BR>}<BR><BR><BR>void loop ()<BR>{<BR>
  881. taskManager.execute();<BR>}</FONT><FONT FACE="Times New Roman, serif"><BR></FONT><BR>
  882. </P>
  883. <OL START=2>
  884. <LI><P CLASS="western" STYLE="margin-bottom: 0in">“<FONT FACE="Times New Roman, serif"><B>NATIVE”
  885. SUPPORT FOR FINITE STATE MACHINE</B></FONT></P>
  886. </OL>
  887. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  888. </P>
  889. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Define
  890. “states” as callback function or functions. Each callback
  891. function executes activities specific to a “state” and then
  892. “transitions” to the next state by assigning next callback
  893. function to the task. </FONT>
  894. </P>
  895. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Transition
  896. from one state to the next is achieved by setting next callback
  897. function at the end of preceding one. </FONT>
  898. </P>
  899. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Note:
  900. </B>do not call the next callback function. Let the schedule take
  901. care of that during the next pass. (Thus letting other tasks run). </FONT>
  902. </P>
  903. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  904. </P>
  905. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Example:
  906. Blinking LED 2 times a second could be achieved this way</FONT></P>
  907. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  908. </P>
  909. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">Task
  910. tLedBlinker (500, -1, &amp;ledOnCallback);</FONT></P>
  911. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">Scheduler
  912. taskManager;</FONT></P>
  913. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  914. </P>
  915. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">void
  916. ledOnCallback() {</FONT></P>
  917. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> turnLedOn();</FONT></P>
  918. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.setCallback(&amp;ledOffCallback);</FONT></P>
  919. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</FONT></P>
  920. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  921. </P>
  922. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">void
  923. ledOffCallback() {</FONT></P>
  924. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> turnLedOff();</FONT></P>
  925. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.setCallback(&amp;ledOnCallback);</FONT></P>
  926. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</FONT></P>
  927. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  928. </P>
  929. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">setup()
  930. {</FONT></P>
  931. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> taskManager.init();<BR>
  932. taskManager.addTask(tLedBlinker);</FONT></P>
  933. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> </FONT></P>
  934. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> tLedBlinker.enable();</FONT></P>
  935. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">}</FONT></P>
  936. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  937. </P>
  938. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace">loop
  939. () {</FONT></P>
  940. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"> taskManager.execute();</FONT></P>
  941. <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>
  942. </P>
  943. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Obviously
  944. the example is simple, but gives the idea of how the tasks could be
  945. used to go through states.</FONT></P>
  946. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  947. </P>
  948. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  949. </P>
  950. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  951. </P>
  952. <OL START=3>
  953. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>MULTIPLE
  954. POSSIBLE CALLBACKS FOR TASK</B></FONT></P>
  955. </OL>
  956. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  957. </P>
  958. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">There
  959. may be a need to select an option for callback function based on
  960. certain criteria, or randomly. </FONT>
  961. </P>
  962. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">You
  963. can achieve that by defining an array of callback function pointers
  964. and selecting one based on the criteria you need. </FONT>
  965. </P>
  966. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Example:
  967. when a robot detects an obstacle, it may go left, right backwards,
  968. etc. Each of the “directions” or “behaviors” are represented
  969. by a different callback function. </FONT>
  970. </P>
  971. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  972. </P>
  973. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Another
  974. example of using multiple callbacks:</FONT></P>
  975. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">You
  976. may need to “initialize” variables for a particular task.</FONT></P>
  977. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">In
  978. this case, define a tasks with two callbacks:</FONT></P>
  979. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  980. </P>
  981. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  982. <B>tWork</B> (T_INTERVAL, -1, &amp;workCallbackInit);</FONT></FONT></P>
  983. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">…</P>
  984. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  985. </P>
  986. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  987. workCallbackInit() {</FONT></FONT></P>
  988. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
  989. do your initializationstuff here</FONT></FONT></P>
  990. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> </FONT></FONT></P>
  991. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
  992. finally assigne the main callback function </FONT></FONT>
  993. </P>
  994. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.setCallback(&amp;workCallback);</FONT></FONT></P>
  995. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  996. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  997. </P>
  998. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  999. workCallback() {</FONT></FONT></P>
  1000. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
  1001. main callback function</FONT></FONT></P>
  1002. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> …</FONT></FONT></P>
  1003. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1004. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1005. </P>
  1006. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">The
  1007. task will initialize during first execution pass and switch to
  1008. “regular” callback execution starting with second pass. There is
  1009. a delay between first and second passes of the task (scheduling
  1010. period, if defined). In order to execute the second pass immediately
  1011. after initialization first pass, change the above code like this:</FONT></P>
  1012. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1013. </P>
  1014. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1015. workCallbackInit() {</FONT></FONT></P>
  1016. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
  1017. do your initializationstuff here</FONT></FONT></P>
  1018. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> </FONT></FONT></P>
  1019. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> //
  1020. finally assigne the main callback function </FONT></FONT>
  1021. </P>
  1022. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.setCallback(&amp;workCallback);</FONT></FONT></P>
  1023. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2> tWork.enable();</FONT></FONT></P>
  1024. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1025. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1026. </P>
  1027. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">The
  1028. task will run initialization first, then immediately second pass, and
  1029. then switch to processing at regular intervals starting with a third
  1030. pass. </FONT>
  1031. </P>
  1032. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1033. </P>
  1034. <OL START=3>
  1035. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>INTERRUP-DRIVEN
  1036. EXECUTION SUPPORT </B></FONT>
  1037. </P>
  1038. </OL>
  1039. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1040. </P>
  1041. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">In
  1042. case of interrupt-driven program flow, tasks could be scheduled to
  1043. run once to request asynchronous execution (request), and then
  1044. re-enabled (restarted) again with a different callback function to
  1045. process the results. </FONT>
  1046. </P>
  1047. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1048. </P>
  1049. <P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>Example</B>:
  1050. event driven distance calculation for ultrasonic pulses. EchoPin #6
  1051. triggers pin change interrupts on rising and falling edges to
  1052. determine the length of ultrasonic pulse.</FONT></P>
  1053. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1054. </P>
  1055. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#include
  1056. &lt;DirectIO.h&gt;<BR>#include &lt;TaskScheduler.h&gt;<BR>#include
  1057. &lt;PinChangeInt.h&gt;<BR><BR><BR>#define TRIGGERPIN 5<BR>#define
  1058. ECHOPIN 6<BR><BR>Output&lt;TRIGGERPIN&gt;
  1059. pTrigger;<BR>Input&lt;ECHOPIN&gt; pEcho;<BR><BR>Scheduler
  1060. r;<BR><BR>Task tMeasure(1000, -1, &amp;measureCallback, &amp;r,
  1061. true);<BR>Task tDisplay(1000, -1, &amp;displayCallback, &amp;r,
  1062. true);<BR>Task tPing(0, 1, &amp;pingCalcCallback, &amp;r,
  1063. false);<BR><BR><BR>volatile bool pulseBusy = false;<BR>volatile bool
  1064. pulseTimeout = false;<BR>volatile unsigned long pulseStart =
  1065. 0;<BR>volatile unsigned long pulseStop = 0;<BR>volatile unsigned long
  1066. pingDistance = 0;<BR><BR><BR>void pingTrigger(unsigned long aTimeout)
  1067. {<BR> if (pulseBusy) return; // do not trigger if in the middle of
  1068. a pulse<BR> if (pEcho == HIGH) return; // do not trigger if ECHO pin
  1069. is high<BR> <BR> pulseBusy = true;<BR> pulseTimeout = false;</FONT></FONT></P>
  1070. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR>
  1071. pTrigger = LOW;<BR> delayMicroseconds(4);<BR> pTrigger = HIGH;<BR><BR>
  1072. tPing.setInterval (aTimeout);<BR><BR> delayMicroseconds(10);<BR>
  1073. pTrigger = LOW; <BR></FONT></FONT><BR>
  1074. </P>
  1075. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1076. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tPing.restartDelayed();
  1077. // timeout countdown starts now<BR></FONT></FONT><BR>
  1078. </P>
  1079. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1080. will start the pulse clock on the rising edge of ECHO pin</FONT></FONT></P>
  1081. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1082. <FONT FACE="Courier New, monospace"><FONT SIZE=2>PCintPort::attachInterrupt(ECHOPIN,
  1083. &amp;pingStartClock, RISING); <BR>}<BR><BR></FONT></FONT><BR>
  1084. </P>
  1085. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1086. Start clock on the <B>rising</B> edge of the ultrasonic pulse<BR>void
  1087. pingStartClock() {<BR> pulseStart = micros();<BR>
  1088. PCintPort::detachInterrupt(ECHOPIN); // not sure this is necessary<BR>
  1089. PCintPort::attachInterrupt(ECHOPIN, &amp;pingStopClock, FALLING); <BR>
  1090. tPing.restartDelayed();<BR>}<BR><BR>// Stop clock on the <B>falling</B>
  1091. edge of the ultrasonic pulse<BR>void pingStopClock() {<BR> pulseStop
  1092. = micros();<BR> PcintPort::detachInterrupt(ECHOPIN);</FONT></FONT></P>
  1093. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1094. <FONT FACE="Courier New, monospace"><FONT SIZE=2>pingDistance =
  1095. pulseStop - pulseStart;<BR> pulseBusy = false;<BR> tPing.disable();
  1096. // disable timeout<BR>}<BR></FONT></FONT><BR>
  1097. </P>
  1098. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1099. Stop clock because of the timeout – the wave did not return<BR>void
  1100. pingCalcCallback() {<BR> if (pulseBusy) {<BR> pingStopClock();<BR>
  1101. }<BR> pulseTimeout = true;<BR>}<BR><BR><BR><BR>// Initial measure
  1102. callback sets the trigger<BR>void measureCallback() {<BR> if
  1103. (pulseBusy) { // already measuring, try again<BR>
  1104. tMeasure.enable();<BR> return;<BR> }<BR> pingTrigger(30); // 30
  1105. milliseconds or max range of ~5.1 meters<BR>
  1106. tMeasure.setCallback(&amp;measureCallbackWait);<BR>}<BR></FONT></FONT><BR>
  1107. </P>
  1108. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1109. Wait for the measurement to <BR>void measureCallbackWait() {<BR> if
  1110. (pulseBusy) return;<BR> tMeasure.setCallback(&amp;measureCallback);
  1111. <BR>}<BR><BR><BR>bool state = true;<BR><BR>void displayCallback() {<BR>
  1112. char d[256];<BR> <BR> unsigned long cm = pingDistance * 17 / 100;
  1113. // cm<BR> <BR> snprintf(d, 256, &quot;pulseStart =
  1114. %8lu\tpulseStop=%8lu\tdistance, cm=%8lu&quot;, pulseStart, pulseStop,
  1115. cm);<BR> Serial.println(d);<BR> <BR>}<BR><BR>void setup() {<BR> //
  1116. put your setup code here, to run once:<BR> <BR>
  1117. Serial.begin(115200);<BR> <BR><BR> pTrigger = LOW;<BR> pEcho =
  1118. LOW;<BR> <BR>}<BR><BR>void loop() {<BR> // put your main code here,
  1119. to run repeatedly:<BR> r.execute();<BR>}<BR></FONT></FONT><BR>
  1120. </P>
  1121. <OL START=3>
  1122. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>USING
  1123. ONENABLE AND ONDISBALE METHODS </B></FONT>
  1124. </P>
  1125. </OL>
  1126. <P CLASS="western" STYLE="margin-bottom: 0in"><BR>
  1127. </P>
  1128. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Consider
  1129. a task to flash onboard LED for 5 seconds with random frequency. Task
  1130. should be repeated every 30 seconds indefinitely. Since frequency is
  1131. random, there are two challenges:</FONT></P>
  1132. <OL START=3>
  1133. <OL>
  1134. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">We
  1135. need to make sure LED is turned OFF at the last iteration</FONT></P>
  1136. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif">We
  1137. need to calculate random frequency every time</FONT></P>
  1138. </OL>
  1139. </OL>
  1140. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1141. </P>
  1142. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Times New Roman, serif">Below
  1143. is the implementation using TaskScheduler </FONT>
  1144. </P>
  1145. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1146. </P>
  1147. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2><BR></FONT></FONT><BR>
  1148. </P>
  1149. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
  1150. _TASK_SLEEP_ON_IDLE_RUN</FONT></FONT></P>
  1151. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#include
  1152. &lt;TaskScheduler.h&gt;</FONT></FONT></P>
  1153. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1154. </P>
  1155. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
  1156. LEDPIN 13</FONT></FONT></P>
  1157. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1158. </P>
  1159. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1160. </P>
  1161. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
  1162. ts;</FONT></FONT></P>
  1163. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1164. </P>
  1165. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1166. tWrapper(30000, -1, &amp;WrapperCallback, &amp;ts, true);</FONT></FONT></P>
  1167. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1168. tBlink(5000, 1, NULL, &amp;ts, false, &amp;BlinkOnEnable,
  1169. &amp;BlinkOnDisable);</FONT></FONT></P>
  1170. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1171. tLED(0, -1, NULL, &amp;ts, false, NULL, &amp;LEDOff);</FONT></FONT></P>
  1172. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1173. </P>
  1174. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1175. WrapperCallback() {</FONT></FONT></P>
  1176. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1177. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;In
  1178. WrapperCallback&quot;);</FONT></FONT></P>
  1179. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1180. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tBlink.restartDelayed();
  1181. // LED blinking is initiated </FONT></FONT>
  1182. </P>
  1183. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1184. <FONT FACE="Courier New, monospace"><FONT SIZE=2>//every
  1185. 30 seconds for 5 seconds</FONT></FONT></P>
  1186. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1187. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1188. </P>
  1189. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1190. </P>
  1191. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1192. Upon being enabled, tBlink will define the parameters</FONT></FONT></P>
  1193. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1194. and enable LED blinking task, which actually controls</FONT></FONT></P>
  1195. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1196. the hardware (LED in this example)</FONT></FONT></P>
  1197. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
  1198. BlinkOnEnable() {</FONT></FONT></P>
  1199. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1200. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;In
  1201. BlinkOnEnable&quot;);</FONT></FONT></P>
  1202. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1203. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.setInterval(
  1204. 500 + random(501) );</FONT></FONT></P>
  1205. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1206. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.setCallback(
  1207. &amp;LEDOn);</FONT></FONT></P>
  1208. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1209. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.enable();</FONT></FONT></P>
  1210. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1211. </P>
  1212. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1213. <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true; //
  1214. Task should be enabled</FONT></FONT></P>
  1215. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1216. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1217. </P>
  1218. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1219. tBlink does not really need a callback function</FONT></FONT></P>
  1220. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1221. since it just waits for 5 seconds for the first </FONT></FONT>
  1222. </P>
  1223. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1224. and only iteration to occur. Once the iteration</FONT></FONT></P>
  1225. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1226. takes place, tBlink is disabled by the Scheduler, </FONT></FONT>
  1227. </P>
  1228. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1229. thus executing its OnDisable method below.</FONT></FONT></P>
  1230. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1231. </P>
  1232. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1233. BlinkOnDisable() {</FONT></FONT></P>
  1234. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1235. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;In
  1236. BlinkOnDisable&quot;);</FONT></FONT></P>
  1237. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1238. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.disable();</FONT></FONT></P>
  1239. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1240. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1241. </P>
  1242. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1243. LEDOn () {</FONT></FONT></P>
  1244. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1245. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;In
  1246. LEDOn&quot;);</FONT></FONT></P>
  1247. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1248. <FONT FACE="Courier New, monospace"><FONT SIZE=2>digitalWrite(LEDPIN,
  1249. HIGH);</FONT></FONT></P>
  1250. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1251. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.setCallback(
  1252. &amp;LEDOff);</FONT></FONT></P>
  1253. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1254. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1255. </P>
  1256. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1257. LEDOff () {</FONT></FONT></P>
  1258. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1259. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;In
  1260. LEDOff&quot;);</FONT></FONT></P>
  1261. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1262. <FONT FACE="Courier New, monospace"><FONT SIZE=2>digitalWrite(LEDPIN,
  1263. LOW);</FONT></FONT></P>
  1264. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1265. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tLED.setCallback(
  1266. &amp;LEDOn);</FONT></FONT></P>
  1267. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1268. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1269. </P>
  1270. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1271. Note that LEDOff method serves as OnDisable method</FONT></FONT></P>
  1272. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1273. to make sure the LED is turned off when the tBlink</FONT></FONT></P>
  1274. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>//
  1275. task finishes (or disabled ahead of time)</FONT></FONT></P>
  1276. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1277. </P>
  1278. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1279. setup() {</FONT></FONT></P>
  1280. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1281. </P>
  1282. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1283. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.begin(115200);
  1284. </FONT></FONT>
  1285. </P>
  1286. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1287. <FONT FACE="Courier New, monospace"><FONT SIZE=2>pinMode(LEDPIN,
  1288. OUTPUT); </FONT></FONT>
  1289. </P>
  1290. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1291. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1292. </P>
  1293. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1294. loop() {</FONT></FONT></P>
  1295. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1296. <FONT FACE="Courier New, monospace"><FONT SIZE=2>// put your main
  1297. code here, to run repeatedly:</FONT></FONT></P>
  1298. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1299. </P>
  1300. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1301. <FONT FACE="Courier New, monospace"><FONT SIZE=2>ts.execute();</FONT></FONT></P>
  1302. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1303. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1304. </P>
  1305. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1306. </P>
  1307. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1308. </P>
  1309. <OL START=3>
  1310. <LI><P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Times New Roman, serif"><B>USING
  1311. STATUS REQUEST OBJECTS </B></FONT>
  1312. </P>
  1313. </OL>
  1314. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1315. </P>
  1316. <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
  1317. test emulates querying 3 sensors once every 10 seconds, each could
  1318. respond with a different delay (ultrasonic sensors for instance) and
  1319. printing a min value of the three when all three have reported their
  1320. values.</FONT></FONT></P>
  1321. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1322. </P>
  1323. <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
  1324. overall timeout of 1 second is setup as well.</FONT></FONT></P>
  1325. <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
  1326. error message needs to be printed if a timeout occurred instead of a
  1327. value.</FONT></FONT></P>
  1328. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1329. </P>
  1330. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1331. </P>
  1332. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1333. </P>
  1334. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
  1335. _TASK_SLEEP_ON_IDLE_RUN</FONT></FONT></P>
  1336. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#define
  1337. _TASK_STATUS_REQUEST</FONT></FONT></P>
  1338. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1339. </P>
  1340. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>#include
  1341. &lt;TaskScheduler.h&gt;</FONT></FONT></P>
  1342. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1343. </P>
  1344. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>StatusRequest
  1345. measure;</FONT></FONT></P>
  1346. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1347. </P>
  1348. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Scheduler
  1349. ts; </FONT></FONT>
  1350. </P>
  1351. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1352. </P>
  1353. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1354. tCycle(10000, -1, &amp;CycleCallback, &amp;ts, true);</FONT></FONT></P>
  1355. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1356. tMeasure(1000, 1, &amp;MeasureCallback, &amp;ts, false,
  1357. &amp;MeasureEnable, &amp;MeasureDisable);</FONT></FONT></P>
  1358. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1359. tCalculate(&amp;CalcCallback, &amp;ts);</FONT></FONT></P>
  1360. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1361. tSensor1(0, 1, &amp;S1Callback, &amp;ts, false, &amp;S1Enable);</FONT></FONT></P>
  1362. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1363. tSensor2(0, 1, &amp;S2Callback, &amp;ts, false, &amp;S2Enable);</FONT></FONT></P>
  1364. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>Task
  1365. tSensor3(0, 1, &amp;S3Callback, &amp;ts, false, &amp;S3Enable);</FONT></FONT></P>
  1366. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1367. </P>
  1368. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1369. </P>
  1370. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>long
  1371. distance, d1, d2, d3;</FONT></FONT></P>
  1372. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1373. </P>
  1374. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1375. CycleCallback() {</FONT></FONT></P>
  1376. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1377. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;CycleCallback:
  1378. Initiating measurement cycle every 10 seconds&quot;);</FONT></FONT></P>
  1379. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1380. </P>
  1381. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1382. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tMeasure.restartDelayed();</FONT></FONT></P>
  1383. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1384. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1385. </P>
  1386. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1387. </P>
  1388. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1389. </P>
  1390. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
  1391. MeasureEnable() {</FONT></FONT></P>
  1392. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1393. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;MeasureEnable:
  1394. Activating sensors&quot;); </FONT></FONT>
  1395. </P>
  1396. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1397. </P>
  1398. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1399. <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = 0;</FONT></FONT></P>
  1400. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1401. <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.setWaiting(3);
  1402. // Set the StatusRequest to wait for 3 signals. </FONT></FONT>
  1403. </P>
  1404. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1405. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tCalculate.waitFor(&amp;measure);</FONT></FONT></P>
  1406. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1407. </P>
  1408. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1409. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor1.restart();</FONT></FONT></P>
  1410. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1411. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor2.restart();</FONT></FONT></P>
  1412. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1413. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor3.restart();</FONT></FONT></P>
  1414. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1415. </P>
  1416. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1417. <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</FONT></FONT></P>
  1418. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1419. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1420. </P>
  1421. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1422. MeasureCallback() {</FONT></FONT></P>
  1423. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1424. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;MeasureCallback:
  1425. Invoked by calculate task or one second later&quot;); </FONT></FONT>
  1426. </P>
  1427. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1428. </P>
  1429. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1430. <FONT FACE="Courier New, monospace"><FONT SIZE=2>if
  1431. (measure.pending()) {</FONT></FONT></P>
  1432. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1433. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tCalculate.disable();</FONT></FONT></P>
  1434. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1435. <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signalComplete(-1);
  1436. // signal error</FONT></FONT></P>
  1437. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1438. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;MeasureCallback:
  1439. Timeout!&quot;);</FONT></FONT></P>
  1440. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1441. <FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1442. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1443. <FONT FACE="Courier New, monospace"><FONT SIZE=2>else {</FONT></FONT></P>
  1444. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1445. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;MeasureCallback:
  1446. Min distance=&quot;);Serial.println(distance);</FONT></FONT></P>
  1447. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1448. <FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1449. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1450. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1451. </P>
  1452. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1453. MeasureDisable() {</FONT></FONT></P>
  1454. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1455. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;MeasureDisable:
  1456. Cleaning up&quot;); </FONT></FONT>
  1457. </P>
  1458. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1459. </P>
  1460. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1461. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor1.disable();</FONT></FONT></P>
  1462. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1463. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor2.disable();</FONT></FONT></P>
  1464. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1465. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor3.disable();</FONT></FONT></P>
  1466. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1467. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1468. </P>
  1469. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1470. </P>
  1471. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1472. CalcCallback() {</FONT></FONT></P>
  1473. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1474. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;CalcCallback:
  1475. calculating&quot;); </FONT></FONT>
  1476. </P>
  1477. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1478. <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = -1;</FONT></FONT></P>
  1479. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1480. <FONT FACE="Courier New, monospace"><FONT SIZE=2>if (
  1481. measure.getStatus() &gt;= 0) { // only calculate if statusrequest
  1482. ended successfully</FONT></FONT></P>
  1483. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1484. <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = d1 &lt;
  1485. d2 ? d1 : d2;</FONT></FONT></P>
  1486. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1487. <FONT FACE="Courier New, monospace"><FONT SIZE=2>distance = d3 &lt;
  1488. distance ? d3 : distance;</FONT></FONT></P>
  1489. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1490. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tMeasure.forceNextIteration();</FONT></FONT></P>
  1491. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1492. <FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1493. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1494. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1495. </P>
  1496. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1497. </P>
  1498. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>/**
  1499. Simulation code for sensor 1</FONT></FONT></P>
  1500. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <FONT FACE="Courier New, monospace"><FONT SIZE=2>*
  1501. ----------------------------</FONT></FONT></P>
  1502. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1503. <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
  1504. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
  1505. S1Enable() {</FONT></FONT></P>
  1506. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1507. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S1Enable:
  1508. Triggering sensor1. Delay=&quot;); </FONT></FONT>
  1509. </P>
  1510. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1511. </P>
  1512. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1513. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor1.setInterval(
  1514. random(1200) ); // Simulating sensor delay, which could go over 1
  1515. second and cause timeout</FONT></FONT></P>
  1516. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1517. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d1 = 0;</FONT></FONT></P>
  1518. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1519. </P>
  1520. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1521. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(
  1522. tSensor1.getInterval() );</FONT></FONT></P>
  1523. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1524. <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</FONT></FONT></P>
  1525. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1526. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1527. </P>
  1528. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1529. S1Callback() {</FONT></FONT></P>
  1530. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1531. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S1Callback:
  1532. Emulating measurement. d1=&quot;); </FONT></FONT>
  1533. </P>
  1534. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1535. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d1 = random(501); //
  1536. pick a value from 0 to 500 &quot;centimeters&quot; simulating a
  1537. measurement </FONT></FONT>
  1538. </P>
  1539. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1540. <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</FONT></FONT></P>
  1541. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1542. </P>
  1543. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1544. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(d1); </FONT></FONT>
  1545. </P>
  1546. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1547. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1548. </P>
  1549. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1550. </P>
  1551. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>/**
  1552. Simulation code for sensor 2</FONT></FONT></P>
  1553. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <FONT FACE="Courier New, monospace"><FONT SIZE=2>*
  1554. ----------------------------</FONT></FONT></P>
  1555. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1556. <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
  1557. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
  1558. S2Enable() {</FONT></FONT></P>
  1559. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1560. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S2Enable:
  1561. Triggering sensor2. Delay=&quot;); </FONT></FONT>
  1562. </P>
  1563. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1564. </P>
  1565. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1566. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor2.setInterval(
  1567. random(1200) ); // Simulating sensor delay, which could go over 1
  1568. second and cause timeout</FONT></FONT></P>
  1569. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1570. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d2 = 0;</FONT></FONT></P>
  1571. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1572. </P>
  1573. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1574. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(
  1575. tSensor2.getInterval() );</FONT></FONT></P>
  1576. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1577. <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</FONT></FONT></P>
  1578. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1579. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1580. </P>
  1581. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1582. S2Callback() {</FONT></FONT></P>
  1583. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1584. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S2Callback:
  1585. Emulating measurement. d2=&quot;); </FONT></FONT>
  1586. </P>
  1587. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1588. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d2 = random(501); //
  1589. pick a value from 0 to 500 &quot;centimeters&quot; simulating a
  1590. measurement</FONT></FONT></P>
  1591. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1592. <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</FONT></FONT></P>
  1593. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1594. </P>
  1595. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1596. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(d2);
  1597. </FONT></FONT>
  1598. </P>
  1599. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1600. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1601. </P>
  1602. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1603. </P>
  1604. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>/**
  1605. Simulation code for sensor 3</FONT></FONT></P>
  1606. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <FONT FACE="Courier New, monospace"><FONT SIZE=2>*
  1607. ----------------------------</FONT></FONT></P>
  1608. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1609. <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
  1610. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>bool
  1611. S3Enable() {</FONT></FONT></P>
  1612. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1613. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S3Enable:
  1614. Triggering sensor3. Delay=&quot;); </FONT></FONT>
  1615. </P>
  1616. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1617. </P>
  1618. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1619. <FONT FACE="Courier New, monospace"><FONT SIZE=2>tSensor3.setInterval(
  1620. random(1200) ); // Simulating sensor delay, which could go over 1
  1621. second and cause timeout</FONT></FONT></P>
  1622. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1623. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d3 = 0;</FONT></FONT></P>
  1624. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1625. </P>
  1626. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1627. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(
  1628. tSensor3.getInterval() );</FONT></FONT></P>
  1629. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1630. <FONT FACE="Courier New, monospace"><FONT SIZE=2>return true;</FONT></FONT></P>
  1631. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1632. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1633. </P>
  1634. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1635. S3Callback() {</FONT></FONT></P>
  1636. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1637. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.print(&quot;S3Callback:
  1638. Emulating measurement. d3=&quot;); </FONT></FONT>
  1639. </P>
  1640. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1641. <FONT FACE="Courier New, monospace"><FONT SIZE=2>d3 = random(501); //
  1642. pick a value from 0 to 500 &quot;centimeters&quot; simulating a
  1643. measurement</FONT></FONT></P>
  1644. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1645. <FONT FACE="Courier New, monospace"><FONT SIZE=2>measure.signal();</FONT></FONT></P>
  1646. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1647. </P>
  1648. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1649. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(d3); </FONT></FONT>
  1650. </P>
  1651. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1652. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1653. </P>
  1654. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1655. </P>
  1656. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>/**
  1657. Main Arduino code</FONT></FONT></P>
  1658. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"> <FONT FACE="Courier New, monospace"><FONT SIZE=2>*
  1659. Not much is left here - everything is taken care of by the framework</FONT></FONT></P>
  1660. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1661. <FONT FACE="Courier New, monospace"><FONT SIZE=2>*/</FONT></FONT></P>
  1662. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1663. setup() {</FONT></FONT></P>
  1664. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1665. </P>
  1666. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1667. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.begin(115200);</FONT></FONT></P>
  1668. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1669. <FONT FACE="Courier New, monospace"><FONT SIZE=2>Serial.println(&quot;TaskScheduler
  1670. StatusRequest Sensor Emulation Test. Complex Test.&quot;); </FONT></FONT>
  1671. </P>
  1672. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1673. <FONT FACE="Courier New, monospace"><FONT SIZE=2>randomSeed(analogRead(A1)+millis());</FONT></FONT></P>
  1674. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1675. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1676. </P>
  1677. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>void
  1678. loop() {</FONT></FONT></P>
  1679. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1680. </P>
  1681. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in">
  1682. <FONT FACE="Courier New, monospace"><FONT SIZE=2>ts.execute();</FONT></FONT></P>
  1683. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><BR>
  1684. </P>
  1685. <P CLASS="western" STYLE="margin-left: 0.49in; margin-bottom: 0in"><FONT FACE="Courier New, monospace"><FONT SIZE=2>}</FONT></FONT></P>
  1686. </BODY>
  1687. </HTML>