Index

Cooperating Sequential Tasks

  1. Introduction
    1. Arduino
    2. Interrupts
  2. Simple Tasks
  3. Multiple Tasks
  4. Communicating Tasks
  5. Communicating Values
  6. Synchronising Tasks
  7. Buffered Communication
  8. Multiple Senders
  9. Conditional Tasks
  10. Transput
  11. Implementation
    1. Common Data
    2. Tasks
    3. task_builder
    4. task
    5. channel
    6. virtual_machine
    7. set
    8. queue
    9. clock
    10. standard
    11. Adjusting Limits
images/15-1.png

Describing Multiple Tasks



In the previous blinker example, we only described and ran one task. Before going on to describe a series of different tasks, it is worth stopping to make the blinker task more flexible so that we can easily use it to flash more than one LED. A new version that supports this is shown below.

#include "Tasks.h"

void blinker_setup(int led_pin)
{
  pinMode(led_pin, OUTPUT);
}

void led_off(int led_pin)
{
  digitalWrite(led_pin, LOW);
}

void led_on(int led_pin)
{
  digitalWrite(led_pin, HIGH);
}

void blinker(int interval, int led_pin)
{
  new_task(blinker_setup, led_pin);
    action(led_off, led_pin);
    pause(interval);
    action(led_on, led_pin);
    pause(interval);
  end_task();
}


At first sight, this might not look a lot different to the original until you realise that this version does not directly specify which pin the LED is to be connected to. Instead, the blinker_setup, led_off and led_on functions have been extended to take a parameter indicating which pin is to be used. In addition the blinker function itself now has an extra led_pin parameter. In the definition of the actions the task is to perform, led_pin is passed to the new_task and action functions. When these functions are called with a second parameter, they expect the first parameter to be a function which accepts an integer value - as is now the case. The effect is that we can define which pin is to be used when we call blinker and the appropriate value will be passed to the Arduino specific functions blinker_setup, led_off and led_on when the task is executing.

We can now modify the main tab as follows.

#include "Tasks.h"

void setup()
{
  init_tasks();
  blinker(17011);
  blinker(13012);
  blinker(10013);
}

void loop()
{
  run_system();
}


If we upload this to an Arduino with LEDs connected to pins 11, 12 and 13, they will all flash at different rates. If you observe the behaviour of the LEDs, it should be clear that the three blinker tasks are not interfering with each other. The important thing here is that when we specify that a task should pause for some interval, something very different is happening compared to calling the Arduino delay function. When a task pauses it simply provides a chance for other tasks to execute rather than blocking them. To say this another way, unless you are using interrupts, delays are bad because they block other activities. In this scheme of things pauses are good because they release the processor so that other tasks can use it.

Think about trying to make a reusable function in the standard Arduino style that does the same thing. It is difficult to make it as simple and as modular style as this.

Next: Communicating Tasks