Task Loop using Function Pointers

Dette eksempel illustrerer, hvordan man kan bruge function pointers til at køre forskellige opgaver med hvert sit interval, uden at de blokerer for hinanden i længere tid end det tager at eksekvere en enkelt opgave.

typedef struct MyTask {
   void (*handler)();
   int intervalMs;
   int taskId;
   unsigned long lastRunMs;
} MyTask;


// Forward declaration of the task runner functions
void task_main();
void task_A();
void task_B();
void task_C();

MyTask tasks[] = {
  {.handler=task_main},
  {task_A,300},
  {task_B,500},
  {task_C,3000}
};

const int arrSize = sizeof(tasks)/sizeof(MyTask);

void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  
  Serial.print("Task count: ");
  Serial.println(arrSize);

  for(int i=0 ; i<arrSize; i++){
    if(tasks[i].intervalMs <= 0){
      tasks[i].intervalMs = (i+1)*100;
    }
    String msg = "";
    msg = "task id: ";
    msg += i;
    msg += ", interval ";
    msg += tasks[i].intervalMs;
    Serial.println(msg);
  }
  
  Serial.println("Setup DONE");
}

// example of non-blocking asyncronous wait loop using function pointers
void loop() {
  for(int i=0 ; i<arrSize; i++){
    runInterval(&tasks[i]);
  }
}

void runInterval(struct MyTask *t){
  unsigned long tickMs = millis();
  unsigned long diffMs = tickMs - t->lastRunMs;

  // Handle first run
  if(0 == t->lastRunMs){
    t->lastRunMs = tickMs;
  }
  bool shouldRun = (t->intervalMs < diffMs);
  if(!shouldRun){
    return;
  }
  // Store last run
  t->lastRunMs = tickMs;

  // Perform the process by calling the handler function
  (t->handler)();
}

// Create some tasks to run in the example
void task_main(){
  static int runCount = 0;
  Serial.print(".");
  if(0 == runCount % 30){
    Serial.println();
    Serial.print(runCount);
    Serial.print(" : ");
  }
  runCount++;
}

void task_A(){
  Serial.print("A");
}

void task_B(){
  Serial.print("B");
}

void task_C(){
  Serial.print("C");
}

Når eksemplet køres på en arduino generes dette output på seriel porten.

Bemærk at baudrate er sat til 115200.

Task count: 4
task id: 0, interval 100
task id: 1, interval 300
task id: 2, interval 500
task id: 3, interval 3000
Setup DONE
.
0 : .A..B.A...A.B..A...BA...A..B.A...A.B..A...CBA..
30 : .A..B.A...A.B..A...BA...A..B.A...A.B..A...CBA..
60 : .A..B.A...A.B..A...BA...A..B.A...A.B..A...CBA..
90 : .A..B.A...A.B..A...BA...A..B.A...A.B..A..C.BA..
120 : .A.B..A...AB...A..B.A...A.B..A..A.B..A...CBA...

Materiale