Pages: [1]   Go Down
Author Topic: Multithreading  (Read 9001 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

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

And

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

Using Threads library we breaking each thread into 2 functions:

Code:

// 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:

Code:
 
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:

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

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

Code:
   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.

Code:

// 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 - downloaded 92 times.)
Logged

Finland
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 <Documents>/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();
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Pages: [1]   Go Up
Jump to: