How to have multiple infinite loops to be running at the same time?

Hi guys,

I am trying to have multiple loops to be running on different output pins.

I have been searching up and some people have suggested to use multi threading in a similar situation.

But at the same time some of the people said Arduino does not support multi threading.

what I have done to make up the easiest way for the loop is:

digitalWrite(13, HIGH);
delay(3.5);
digitalWrite(13, LOW);
delay(1.5);

digitalWrite(13, HIGH);
delay(3.5);
digitalWrite(13, LOW);
delay(1.5);

digitalWrite(13, HIGH);
delay(2.0);
digitalWrite(13, LOW);
delay(1.0);

digitalWrite(13, HIGH);
delay(1.0);
digitalWrite(13, LOW);
delay(1.0);

Similar loop for the other one but different time period.

I cannot get the loops to run at the exact time because the program reads the line sequentially.

which means if I put the loops one after the other, then one output will be off when the other pin is producing the output.

I have also looked into the learning sections which says that "delay" is very easy to use but the only down side is that once it reads "delay", it will stop everything until the delay time has pass.

maybe this will be another problem in my program?
I have tried using the suggestion "millis" timer but I couldn't get it going like that way I want. (Maybe I did it incorrectly).

Also tired adding pthread.h and use the way it was shown from the video from youtube, gave me some errors.

now I have looked into the "os_wrap" library which I have no idea how to use it because I do not understand the document.......

Please advice what I should do at this moment.

Thanks,
Anthony

Take a look at this code here
http://forum.arduino.cc//index.php?topic=179761.0

(I would attach it, but its stored in another computer).

Use blink without delay style programming to let up to 13 notes play simultaneously on a chip with more IO; limit will be 10 with a standard 20 IO Arduino.

Also, delay's argument is of the type unsigned long, meaning it can only take integer values, not fractional ones.

Use code-tags when posting your code.

I have been wondering the same thing, and would like an answer as well. Is it possible to run multiple loops at the same time?

It is possible using millis(), but I can imagine there is an easier way. Someone more experienced have to help you with that.

It is also possible using delay, you would have to sort of "merge" all the pins and cut the delays into shorter delays, for example:

digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
digitalWrite(13, HIGH);
digitalWrite(12, LOW);
delay(1000);
digitalWrite(13, LOW);
// And so on...

Pin 13 will change every second, while pin 12 will change every 2 seconds(simple solution, loaded with limits. Not ideal).

Still hoping for an answer on this question, as it would come very handy to be able to run different loops simultaneously.

delayMicroseconds(1500); can be used in place of delay(1.5);

Neither one lets multiple things appear to happen at the same time (or within a few clock cycles anyway).

Strongly suggest you look at the thread I posted. The code is there, as well as a video of it in action.

okay now seems working.......

i was thinking if i can add another trick to it so i can use the pot trimmer to adjust the "delay" for overall frequency

Sure,
delayTime = analogRead(A0); // gives a result from 0 to 1023.

so pretty much it will be 0-5v = 0 - 1023? and that is 1023 milli seconds?

if my delay1 = 8 ms
and delay2 = 4ms,
can i change to delay1 = analogRead(A0)
and delay2 = delay1 / 2 ?

You can manipulate the reading however you'd like.
Use the map ( ) command to scale it up, or down, make one delay some manipulation of another delay, etc.
Use it with delayMicroseconds( ) instead for delays as small as 4uS even (0.004mS).
Check the reference page, I think there is some upper limit recommended for delayMicroseconds( ) after which delay( ) is recommended.

after what i have tried, i am avoiding to use delay as it ruins my loop completely.......

so all i have to do is to change from milli to micro and convert the unit to 8000 instead to have much higher resolution right?

Yes.

You might also want to look up Finite State Machines. Programming using these techniques allow you to run multiple independent actions or logic threads simultaneously. An example that you could look at is the MultiBlink sketch in my code repository (link below).

anthony_hk2001:
so pretty much it will be 0-5v = 0 - 1023? and that is 1023 milli seconds?

if my delay1 = 8 ms
and delay2 = 4ms,
can i change to delay1 = analogRead(A0)
and delay2 = delay1 / 2 ?

Yes, you can do that.

Keep in mind though that analogRead value is a scalar, it has no units (microsecond, or otherwise), it's just a number you can do anything with.
You can't increase the resolution of the analogRead. You get 1024 values (0-1023). How you scale them is irrelevant. You can map it to 0-2046, or 0-645164, or 654-5641 or any other range you can think of, but the resolution is the same -you only get 1024 different values.

I have recently made an entry in the playground with a state machine class that can handle concurrent machines.
The entry is here: http://playground.arduino.cc//Code/SMlib.

Here is a example of blinking 3 leds at diffrent rates (500, 600, and 700 ms). I suppose it is something like this that you want to do.

#include <SM.h>

SM Led1(Led1Change, Led1Wait);
SM Led2(Led2Change, Led2Wait);
SM Led3(Led3Change, Led3Wait);

const int Led1Pin = 10;
const int Led2Pin = 11;
const int Led3Pin = 12;

void setup(){
  Serial.begin(115200);
  pinMode(Led1Pin, OUTPUT);
  pinMode(Led2Pin, OUTPUT);
  pinMode(Led3Pin, OUTPUT);
  Serial.println("Setupt finished");  
}//setup()

void loop(){
  EXEC(Led1);
  EXEC(Led2);
  EXEC(Led3);  
}//loop()

State Led1Change(){
  digitalWrite(Led1Pin, !digitalRead(Led1Pin));
  Serial.println("Changed Led1");
}//Led1Change()

State Led1Wait(){
  if(Led1.Timeout(500)) Led1.Set(Led1Change, Led1Wait);
}//Led1Wait()

State Led2Change(){
  digitalWrite(Led2Pin, !digitalRead(Led2Pin));
  Serial.println("Changed Led2");
}//Led2Change()

State Led2Wait(){
  if(Led2.Timeout(600)) Led2.Set(Led2Change, Led2Wait);
}//Led2Wait()

State Led3Change(){
  digitalWrite(Led3Pin, !digitalRead(Led3Pin));
  Serial.println("Changed Led3");
}//Led3Change()

State Led3Wait(){
  if(Led3.Timeout(700)) Led3.Set(Led3Change, Led3Wait);
}//Led3Wait()