Multithreading

Hi, All!
I'm new in Arduino field. After trying few examples, I realized that each time I solving same problem: handling few parallel processes.
So I wrote a smal library which helps to mimic multithreading.

Example:

Let say we have 2 processes which blinking in different frequencies.

//Thread 1
void loop() {
  digitalWrite(6, HIGH);
  delay(500);
  digitalWrite(6, LOW);
  delay(500);
}

And

//Thread 2
void loop() {
  digitalWrite(4, HIGH);
  delay(300);
  digitalWrite(4, LOW);
  delay(300);
}

Using Threads library we breaking each thread into 2 functions:

// 1-st thread s1_1 & s1_2 blink 500/500 
unsigned long s1_1(void *param) {
  digitalWrite(6, HIGH);
  return 500l;
}

unsigned long s1_2(void *param) {
  digitalWrite(6, LOW);
  return 500l;
}

// 2-nd thread blink 300/300
unsigned long s2_1(void *param) {
  digitalWrite(4, HIGH);
  return 300l;
}

unsigned long s2_2(void *param) {
  digitalWrite(4, LOW);
  return 300l;
}

As you can see delay values returned by the functions.
Than we creating the threads:

void setup() {
  t1 = new Thread(NULL);
  t1->addFunc(s1_1);
  t1->addFunc(s1_2);  

  t2 = new Thread(NULL);
  t2->addFunc(s2_1);
  t2->addFunc(s2_2);  

  // ...
}

Finally we can run it from loop function:

void loop()
{
  t1->run();
  t2->run(); 
}

Ok we have multithreading. Now let's add some local variables. Let's implement following thread:

   unsigned long sos[] = {200,200,200,200,200,200,700,200,700,200,700,200,200,200,200,200,200,1500};

   void loop() {
    for(int i=0;i<18;i += 2) {
      digitalWrite(5, HIGH);
      delay(sos[i]);
      digitalWrite(5, LOW);
      delay(sos[i+1]);
    } // end of for
  }

We will implement it in one function and pass the parameter which points to the current interval.
The parameter class not only holds the variables, but have some functionality.

// Morse time intervals SOS: ...---... 
unsigned long sos[] = {
  200,200,200,200,200,200,700,200,700,200,700,200,200,200,200,200,200,1500};

/* Parameter class which passed between functions of 3rd thread */
class ParamMorse {
private:
  int curr;
public:
  ParamMorse(){
    curr = 0;
  }

  int signal(){
    return ((curr%2)==0)?HIGH:LOW;
  }

  long nextVal(){
    long res = sos[curr];
    curr++;
    if(curr >= 18) {
      curr=0;
    }
    return res;
  }      
};

// 3-rd thread blink with intervals from ParamMorse parameter
unsigned long s3_1(void *param) {
  ParamMorse *p = (ParamMorse *)param;
  digitalWrite(5, p->signal());
  unsigned long t = p->nextVal();
  return t;
}

Than we can add 3-rd thread to the example. (See full example in attached file)
To run it connect 3 leds to pins 4,5 and 6 and see what happends.

Any suggestions / fixes etc - very welcome!

Threads.zip (3.27 KB)

Hi
Yet another multithreading/multitasking implementation.
Look at the test program below [2]. It has empty loop, but
the LED still blinks. I use watchdog timer to interrupt
and change the CPU's environment. mexFork() creates
a copy of itself, but with own stack. When the child
wakes it returns out of fork() with zero. Parent returns
with child's process id. The library implements few
routines below [1].

Find the library at http://lumme.org/arduino/Mex.zip,
copy it to your /Arduino/libraries as such
and restart arduino SDK.

[1]
int mexInit(char ntsk);
int mexSleep(int pid);
int mexWake(int pid);
void mexYield();
int mexFork();
void mexDie(char v);
int mexSettime(long delay);
char mexTimeout(long dsttime);
void mexDelay(long dly);
#define mexLock() mex_block++
#define mexUnlock() mex_block--

[2]
#include <Arduino.h>
#include <Task.h>

void blinker(int n)
{
char tick=0;
pinMode(n,OUTPUT);
for(;; ){
delay(300); // better is mexDelay()
digitalWrite(n,tick++ & 1);
}
}

void setup()
{
int r;
Serial.begin(19200); // start serial for output
pinMode(13,OUTPUT);
mexInit(10);
r = mexFork();
if(!r) blinker(13);
mexWake(r);
}

void loop()
{
// Initial task
// if nothing else to do here put at least yield()
mexYield();
}

Hi!

I have also created a time-sharing solution for Arduino called SoftTimer.
http://code.google.com/p/arduino-softtimer/

It is easy to use and very flexible. Has a lot of build in tools like software PWM, Blinker, Debouncer, melody player.

Regards,
Balazs

handling few parallel processes.

Generally speaking, that makes no sense for small mcus.

If you insist on doing it, think about a simple state machine and use a timer to switch among them.