Scheduler_example00_Blink.ino 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. Every example set must have a LED blink example
  3. For this one the idea is to have as many ways to blink the LED
  4. as I can think of. So, here we go.
  5. Tested on:
  6. - Arduino Nano
  7. - ESP8266
  8. - ESP32
  9. - STM32 Maple Mini
  10. */
  11. // ----------------------------------------
  12. // The following "defines" control library functionality at compile time,
  13. // and should be used in the main sketch depending on the functionality required
  14. //
  15. // #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns
  16. #define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between runs if no callback methods were invoked during the pass
  17. #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
  18. // #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids
  19. // #define _TASK_LTS_POINTER // Compile with support for local task storage pointer
  20. // #define _TASK_PRIORITY // Support for layered scheduling priority
  21. // #define _TASK_MICRO_RES // Support for microsecond resolution
  22. // #define _TASK_STD_FUNCTION // Support for std::function (ESP8266 ONLY)
  23. // #define _TASK_DEBUG // Make all methods and variables public for debug purposes
  24. // #define _TASK_INLINE // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
  25. // #define _TASK_TIMEOUT // Support for overall task timeout
  26. // #define _TASK_OO_CALLBACKS // Support for callbacks via inheritance
  27. // #define _TASK_EXPOSE_CHAIN // Methods to access tasks in the task chain
  28. // #define _TASK_SCHEDULING_OPTIONS // Support for multiple scheduling options
  29. // #define _TASK_THREAD_SAFE // Enable additional checking for thread safety
  30. // #define _TASK_SELF_DESTRUCT // Enable tasks to "self-destruct" after disable
  31. #include <TaskScheduler.h>
  32. // Debug and Test options
  33. #define _DEBUG_
  34. //#define _TEST_
  35. #ifdef _DEBUG_
  36. #define _PP(a) Serial.print(a);
  37. #define _PL(a) Serial.println(a);
  38. #else
  39. #define _PP(a)
  40. #define _PL(a)
  41. #endif
  42. // LED_BUILTIN 13
  43. #if defined( ARDUINO_ARCH_ESP32 )
  44. #define LED_BUILTIN 23 // esp32 dev2 kit does not have LED
  45. #endif
  46. // Scheduler
  47. Scheduler ts;
  48. /*
  49. Approach 1: LED is driven by the boolean variable; false = OFF, true = ON
  50. */
  51. #define PERIOD1 500
  52. #define DURATION 10000
  53. void blink1CB();
  54. Task tBlink1 ( PERIOD1 * TASK_MILLISECOND, DURATION / PERIOD1, &blink1CB, &ts, true );
  55. /*
  56. Approac 2: two callback methods: one turns ON, another turns OFF
  57. */
  58. #define PERIOD2 400
  59. void blink2CB_ON();
  60. void blink2CB_OFF();
  61. Task tBlink2 ( PERIOD2 * TASK_MILLISECOND, DURATION / PERIOD2, &blink2CB_ON, &ts, false );
  62. /*
  63. Approach 3: Use RunCounter
  64. */
  65. #define PERIOD3 300
  66. void blink3CB();
  67. Task tBlink3 (PERIOD3 * TASK_MILLISECOND, DURATION / PERIOD3, &blink3CB, &ts, false);
  68. /*
  69. Approach 4: Use status request objects to pass control from one task to the other
  70. */
  71. #define PERIOD4 200
  72. bool blink41OE();
  73. void blink41();
  74. void blink42();
  75. void blink42OD();
  76. Task tBlink4On ( PERIOD4 * TASK_MILLISECOND, TASK_ONCE, blink41, &ts, false, &blink41OE );
  77. Task tBlink4Off ( PERIOD4 * TASK_MILLISECOND, TASK_ONCE, blink42, &ts, false, NULL, &blink42OD );
  78. /*
  79. Approach 5: Two interleaving tasks
  80. */
  81. #define PERIOD5 600
  82. bool blink51OE();
  83. void blink51();
  84. void blink52();
  85. void blink52OD();
  86. Task tBlink5On ( 600 * TASK_MILLISECOND, DURATION / PERIOD5, &blink51, &ts, false, &blink51OE );
  87. Task tBlink5Off ( 600 * TASK_MILLISECOND, DURATION / PERIOD5, &blink52, &ts, false, NULL, &blink52OD );
  88. /*
  89. Approach 6: RunCounter-based with random intervals
  90. */
  91. #define PERIOD6 300
  92. void blink6CB();
  93. bool blink6OE();
  94. void blink6OD();
  95. Task tBlink6 ( PERIOD6 * TASK_MILLISECOND, DURATION / PERIOD6, &blink6CB, &ts, false, &blink6OE, &blink6OD );
  96. void setup() {
  97. // put your setup code here, to run once:
  98. #if defined(_DEBUG_) || defined(_TEST_)
  99. Serial.begin(115200);
  100. delay(TASK_SECOND);
  101. _PL("TaskScheduler Blink example");
  102. _PL("Blinking for 10 seconds using various techniques\n");
  103. delay(2 * TASK_SECOND);
  104. #endif
  105. pinMode(LED_BUILTIN, OUTPUT);
  106. }
  107. void loop() {
  108. ts.execute();
  109. }
  110. inline void LEDOn() {
  111. digitalWrite( LED_BUILTIN, HIGH );
  112. }
  113. inline void LEDOff() {
  114. digitalWrite( LED_BUILTIN, LOW );
  115. }
  116. // === 1 =======================================
  117. bool LED_state = false;
  118. void blink1CB() {
  119. if ( tBlink1.isFirstIteration() ) {
  120. _PP(millis());
  121. _PL(": Blink1 - simple flag driven");
  122. LED_state = false;
  123. }
  124. if ( LED_state ) {
  125. LEDOff();
  126. LED_state = false;
  127. }
  128. else {
  129. LEDOn();
  130. LED_state = true;
  131. }
  132. if ( tBlink1.isLastIteration() ) {
  133. tBlink2.restartDelayed( 2 * TASK_SECOND );
  134. LEDOff();
  135. }
  136. }
  137. // === 2 ======================================
  138. void blink2CB_ON() {
  139. if ( tBlink2.isFirstIteration() ) {
  140. _PP(millis());
  141. _PL(": Blink2 - 2 callback methods");
  142. }
  143. LEDOn();
  144. tBlink2.setCallback( &blink2CB_OFF );
  145. if ( tBlink2.isLastIteration() ) {
  146. tBlink3.restartDelayed( 2 * TASK_SECOND );
  147. LEDOff();
  148. }
  149. }
  150. void blink2CB_OFF() {
  151. LEDOff();
  152. tBlink2.setCallback( &blink2CB_ON );
  153. if ( tBlink2.isLastIteration() ) {
  154. tBlink3.restartDelayed( 2 * TASK_SECOND );
  155. LEDOff();
  156. }
  157. }
  158. // === 3 =====================================
  159. void blink3CB() {
  160. if ( tBlink3.isFirstIteration() ) {
  161. _PP(millis());
  162. _PL(": Blink3 - Run Counter driven");
  163. }
  164. if ( tBlink3.getRunCounter() & 1 ) {
  165. LEDOn();
  166. }
  167. else {
  168. LEDOff();
  169. }
  170. if ( tBlink3.isLastIteration() ) {
  171. tBlink4On.setOnEnable( &blink41OE );
  172. tBlink4On.restartDelayed( 2 * TASK_SECOND );
  173. LEDOff();
  174. }
  175. }
  176. // === 4 =============================================
  177. int counter = 0;
  178. bool blink41OE() {
  179. _PP(millis());
  180. _PL(": Blink4 - Internal status request based");
  181. counter = 0;
  182. tBlink4On.setOnEnable( NULL );
  183. return true;
  184. }
  185. void blink41() {
  186. // _PP(millis());
  187. // _PL(": blink41");
  188. LEDOn();
  189. StatusRequest* r = tBlink4On.getInternalStatusRequest();
  190. tBlink4Off.waitForDelayed( r );
  191. counter++;
  192. }
  193. void blink42() {
  194. // _PP(millis());
  195. // _PL(": blink42");
  196. LEDOff();
  197. StatusRequest* r = tBlink4Off.getInternalStatusRequest();
  198. tBlink4On.waitForDelayed( r );
  199. counter++;
  200. }
  201. void blink42OD() {
  202. if ( counter >= DURATION / PERIOD4 ) {
  203. tBlink4On.disable();
  204. tBlink4Off.disable();
  205. tBlink5On.setOnEnable( &blink51OE );
  206. tBlink5On.restartDelayed( 2 * TASK_SECOND );
  207. tBlink5Off.restartDelayed( 2 * TASK_SECOND + PERIOD5 / 2 );
  208. LEDOff();
  209. }
  210. }
  211. // === 5 ==========================================
  212. bool blink51OE() {
  213. _PP(millis());
  214. _PL(": Blink5 - Two interleaving tasks");
  215. tBlink5On.setOnEnable( NULL );
  216. return true;
  217. }
  218. void blink51() {
  219. // _PP(millis());
  220. // _PL(": blink51");
  221. LEDOn();
  222. }
  223. void blink52() {
  224. // _PP(millis());
  225. // _PL(": blink52");
  226. LEDOff();
  227. }
  228. void blink52OD() {
  229. tBlink6.restartDelayed( 2 * TASK_SECOND );
  230. LEDOff();
  231. }
  232. // === 6 ============================================
  233. long interval6 = 0;
  234. bool blink6OE() {
  235. _PP(millis());
  236. _PP(": Blink6 - RunCounter + Random ON interval = ");
  237. interval6 = random( 100, 901 );
  238. tBlink6.setInterval( interval6 );
  239. _PL( interval6 );
  240. tBlink6.delay( 2 * TASK_SECOND );
  241. return true;
  242. }
  243. void blink6CB() {
  244. if ( tBlink6.getRunCounter() & 1 ) {
  245. LEDOn();
  246. tBlink6.setInterval( interval6 );
  247. }
  248. else {
  249. LEDOff();
  250. tBlink6.setInterval( TASK_SECOND - interval6 );
  251. }
  252. }
  253. void blink6OD() {
  254. tBlink1.restartDelayed( 2 * TASK_SECOND );
  255. LEDOff();
  256. }