Scheduler_example7_WDT.ino 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /**
  2. * TaskScheduler Test sketch - use of task IDs and watchdog timer to identify hung tasks
  3. * Test case:
  4. * Watchdog timer is set to 2 seconds (interrupt + reset)
  5. * A hearbeat task (resetting the watchdog timer) is scheduled with 500 ms interval
  6. * A number of tasks are running every 1 second and "rolling the dice" 0..9. If 5, task is made to enter infinite loop
  7. * Device should reset in 2 seconds after a task enters infinite loop
  8. * A task id and a control point number are saved to EEPROM prior to device reset, and are displayed after reboot.
  9. * In real life, device might chose to NOT activate certain tasks which failed previously (failed sensors for instance)
  10. */
  11. #define _TASK_SLEEP_ON_IDLE_RUN
  12. #define _TASK_WDT_IDS
  13. #include <TaskScheduler.h>
  14. #include <EEPROM.h>
  15. #include <avr/wdt.h>
  16. Scheduler ts;
  17. // Three tasks emulating accidental infinite loop
  18. Task tTask1(1000, -1, &TaskCB, &ts, true);
  19. Task tTask2(1000, -1, &TaskCB, &ts, true);
  20. Task tTask3(1000, -1, &TaskCB, &ts, true);
  21. // Heartbeat task - resetting the watchdog timer periodically
  22. // Initiates WDT on enable, and deactivates it on disable
  23. Task tHB(500, -1, &HB, &ts, false, &HBOn, &HBOff);
  24. /**
  25. * Emulating task callback function
  26. * Prints task id and randomly "hangs" in two places.
  27. * Control points are stored on the task prior to section which might hang,
  28. * making this information available to the WDT interrupt handler
  29. */
  30. void TaskCB() {
  31. Task& T = ts.currentTask();
  32. Serial.print("Task #:");
  33. Serial.print(T.getId());
  34. Serial.print(" current iteration = ");
  35. Serial.println(T.getRunCounter());
  36. // Hang if random number between 0 and 9 is 5 (10% probability)
  37. T.setControlPoint(10);
  38. if (random(10) == 5) for(;;);
  39. // Hang if random number between 0 and 99 is more that 85 (15% probability)
  40. T.setControlPoint(85);
  41. if (random(100) > 84) for(;;);
  42. }
  43. /**
  44. * This On Enable method sets up the WDT
  45. * for interrupt and reset after 2 seconds
  46. */
  47. bool HBOn() {
  48. //disable interrupts
  49. cli();
  50. //reset watchdog
  51. wdt_reset();
  52. //set up WDT interrupt
  53. WDTCSR = (1<<WDCE)|(1<<WDE);
  54. //Start watchdog timer with aDelay prescaller
  55. WDTCSR = (1<<WDIE)|(1<<WDE)|(WDTO_2S & 0x2F);
  56. // WDTCSR = (1<<WDIE)|(WDTO_2S & 0x2F); // interrupt only without reset
  57. //Enable global interrupts
  58. sei();
  59. }
  60. /**
  61. * This On Disable method disables WDT
  62. */
  63. void HBOff() {
  64. wdt_disable();
  65. }
  66. /**
  67. * This is a periodic reset of WDT
  68. */
  69. void HB() {
  70. wdt_reset();
  71. }
  72. /**
  73. * Watchdog timeout ISR
  74. *
  75. */
  76. ISR(WDT_vect)
  77. {
  78. Task& T = ts.currentTask();
  79. digitalWrite(13, HIGH);
  80. EEPROM.write(0, (byte)T.getId());
  81. EEPROM.write(1, (byte)T.getControlPoint());
  82. digitalWrite(13, LOW);
  83. }
  84. /**
  85. * Standard arduino setup routine
  86. */
  87. void setup() {
  88. Serial.begin(115200);
  89. randomSeed(analogRead(0)+analogRead(5));
  90. pinMode(13, OUTPUT);
  91. digitalWrite(13, LOW);
  92. Serial.println("WDT heartbeat test");
  93. Serial.print("Last task before reset="); Serial.println(EEPROM.read(0));
  94. Serial.print("Last control point before reset="); Serial.println(EEPROM.read(1));
  95. delay(2000);
  96. tHB.enableDelayed();
  97. }
  98. /**
  99. * Not much is left for the loop()
  100. */
  101. void loop() {
  102. ts.execute();
  103. }