Multithreading Option?

Hello, my team and I are currently doing a project with 9 servos controlled by 9 photoresistors.
We have the following code in order to control ONE of the servos:

#include <Servo.h>
#include <pt.h>

Servo myservo;
//Servo myservo2;
int val1;
int pos = 180;
//int val2;

void setup()
{
  Serial.begin(9600);
  myservo.attach(12);
  pinMode(0, INPUT);
//myservo2.attach(11);
}
void loop() 
{ 
  
  int v;
  
  while ((v = analogRead(0))>300) 
  {
  Serial.println(v);  
  ; 
  }                                                   
  while (((v = analogRead(0)) < 300)&&( pos != 0)) 
  {
    Serial.println(v); 
    myservo.write(pos);
    delay(15);
    pos--;
  }
   delay(10000); 
    
  for( ; pos <= 180; pos += 1)  
  {                                  
    myservo.write(pos);              
    delay(45);                       
  }

We want to “attach” the code to all nine servos/photoresistors to control all of them simultaneously (we are going to use a PWM extension) but we have not managed to do this using the Arduino Uno.We tried to use the “Demonstration code for several things at the same time” we have found in the forum, but it doesn’t seem to work. Do you know another way of managing to control all nine at the same time? Is Arduino Uno able to support multithreading or not? If not, is Arduino Due a better option?

Thanks!!

You probably don’t understand what the demo shows. For a more teaching explanation, have a look at

How to do multiple things at once.

The quote below is the thrust of it, he does cover details down to code too. The main lesson is about blocking and how to not block code. The rest and whatever you write using this approach turns on that. All of your tasks should run in short pieces that never wait and always allow the other tasks a turn. If a task will take more than a little while (200 usecs) then run it as pieces to let the other tasks have a chance and it may take a little longer but still in short time it will be done as long as no other task holds things up.

In your case, as long as the sensors aren’t getting over 1 KHz signals, this kind of system will mostly be spending slack time just waiting for sensors to change state.

But what if you want to blink the two LEDs at different rates? Like, once a second for LED 1 and twice a second for LED 2?

This is where the delay function doesn’t really help.

Let’s look at an analogy. Say you want to cook breakfast. You need to cook:

Coffee - takes 1 minute
Bacon - takes 2 minutes
Eggs - takes 3 minutes

Now a seasoned cook would NOT do this:

Put coffee on. Stare at watch until 1 minute has elapsed. Pour coffee.
Cook bacon. Stare at watch until 2 minutes have elapsed. Serve bacon.
Fry eggs. Stare at watch until 3 minutes have elapsed. Serve eggs.

The flaw in this is that whichever way you do it, something is going to be cooked too early (and get cold).

In computer terminology this is blocking. That is, you don’t do anything else until the one task at hand is over.

What you are likely to do is this:

Start frying eggs. Look at watch and note the time.
Glance at watch from time to time. When one minute is up then …
Start cooking bacon. Look at watch and note the time.
Glance at watch from time to time. When another minute is up then …
Put coffee on. Look at watch and note the time.
When 3 minutes are up, everything is cooked. Serve it all up.

In computer terminology this is non-blocking. That is, keep doing other things while you wait for time to be up.

Hi Renos,

Unfortunately multithreading is really an OS thing, threads dont exist in the low level world of arduino’s and micros. Even if you implemented them, I’m not sure it would be useful as you only have one “core” to play with (I think you are thinking of having things running side by side, which doenst work here)

Assuming all 9 servos have to be controlled individually (i.e. not all the same settings), you will need to write code which looks like this

#include <Servo.h>
#include <pt.h>

#define NUMSERVOS 9

Servo myservo[NUMSERVOS];
int vals[NUMSERVOS];
int pos[NUMSERVOS];
for(int i=0;i<NUMSERVOS;i++){
 pos[i] = 180; //initialise
}


void setup()
{
  Serial.begin(9600);  
  myservo[0].attach(12);
  myservo[1].attach(11);
  //and so on
  pinMode(0, INPUT);

}
void loop()
{
 
  int v;
  int loop_counter = 0;
  while ((v = analogRead(0))>300)
  {
 Serial.println(v);   
  }                    
 
  while (((v = analogRead(0)) < 300)&& (loop_counter < 180))
  {
 Serial.println(v);
 for(int i=0;i<NUMSERVOS;i++){  
 myservo[i].write(pos[i]);
 pos[i]--;
 }
 delay(15);
  }
  
   delay(10000);
   
  loop_counter = 0;
  for( ; loop_counter <= 180; loop_counter += 1) 
  {                                 
    for(int i=0;i<NUMSERVOS;i++){  
 myservo[i].write(pos[i]);
 pos[i]++;
 }         
    delay(45);                       
  }

Basically you need to restructure your program, so that at every loop you update all of the servos and keep track of all the positions (i have created arrays for this purpose)

in other words, the program structure has to be

mainloop
setup
loop(repeat x times)
move the position by one for all servos

and not

mainloop
setup
loop(repeat x times)
move the position of one servo
loop(repeat x times)
move the position of the next servo
loop(repeat x times)
move the position of the next servo
… and so on

Hope this is useful / I’ve understood what you are trying to achieve

Renos:
Do you know another way of managing to control all nine at the same time? Is Arduino Uno able to support multithreading or not? If not, is Arduino Due a better option?

What you can do is "cooperative multitasking" in a way, that no task blocks other tasks from running. So never use "delay()" or other ways of "busy waiting" in your sketch.

For doing that, I'm always using the IPO principle, which consists of three easy tasks, which are executed in a round-robin scheduling:

  • Input
  • Processing
  • Output

In an Arduino program I just write three functions for it, so that the loop maybe looks like:

void loop()
{
  input();      // read the input from 9 photoresistors and save values to an array in RAM
  processing(); // calculate the 9 current servo positions, dependent from time and input
  output(); // write the calculated servo positions to the servos
}

Three functions for handling 9 input values and 9 output values.
The "processing()" function will make use of the millis() function to slow down actions when servo positions are based on time passing by.

Each run through the loop() function will need less than one millisecond, so the loop() function runs more than a thousand times per second, and when watching it how it works, it looks like "everything happens at the same time".

You'd just need to write those three functions. The input() and output() are easy ones, and the processing() function is a bit more complicated as that represents the programming logic.

cguesty:
Hi Renos,

Unfortunately multithreading is really an OS thing, threads dont exist in the low level world of arduino’s and micros. Even if you implemented them, I’m not sure it would be useful as you only have one “core” to play with (I think you are thinking of having things running side by side, which doenst work here)

Assuming all 9 servos have to be controlled individually (i.e. not all the same settings), you will need to write code which looks like this

#include <Servo.h>

#include <pt.h>

#define NUMSERVOS 9

Servo myservo[NUMSERVOS];
int vals[NUMSERVOS];
int pos[NUMSERVOS];
for(int i=0;i<NUMSERVOS;i++){
pos[i] = 180; //initialise
}

void setup()
{
 Serial.begin(9600);  
 myservo[0].attach(12);
 myservo[1].attach(11);
 //and so on
 pinMode(0, INPUT);

}
void loop()
{

int v;
 int loop_counter = 0;
 while ((v = analogRead(0))>300)
 {
Serial.println(v);  
 }

while (((v = analogRead(0)) < 300)&& (loop_counter < 180))
 {
Serial.println(v);
for(int i=0;i<NUMSERVOS;i++){  
myservo[i].write(pos[i]);
pos[i]–;
}
delay(15);
 }
 
  delay(10000);
 
 loop_counter = 0;
 for( ; loop_counter <= 180; loop_counter += 1)
 {                                
   for(int i=0;i<NUMSERVOS;i++){  
myservo[i].write(pos[i]);
pos[i]++;
}        
   delay(45);                      
 }

You could do MUCH MUCH better! Those delays waste more cycles than the rest of the code uses.

Multithreading does require an OS but multi-tasking does not. For things like home control or most normal automation, an UNO can run literally 100’s of things “at once” smoothly. So far, most people don’t tap 1% of what that chip can do.

jurs:
For doing that, I'm always using the IPO principle, which consists of three easy tasks, which are executed in a round-robin scheduling:

Yeah, each in turn every time through loop but... scheduling?? The only schedules needed are timed events.

Processing should trigger on input, and output should be triggered by processing, through flags or state variable values. But every time through loop() all the routines should check for time elapsed or flag or serial available, etc, the events (input, processing done, some state reached) drive the code hence "event driven/real time code".

For most uses the Arduino is so much faster than the events that the events govern the sketch.
But there's always the frequency counters and heavy bandwidth sketches to break that.

Have look at the demo several things at a time

If you want the appearance that several things are happening in parallel do not use the delay() function.

...R