Can Arduino Multitask?

Ok, so bear with me on this one cause, it seems like a stupid question to me, but I cannot figure it out. Can arduino run two loop functions independently from each other? so loop1{blink LED 2 times/second} loop2{blink LED2 5 times/second} Sorry if this is extremely basic. Thanks in advance!

Paranemertes: Ok, so bear with me on this one cause, it seems like a stupid question to me, but I cannot figure it out. Can arduino run two loop functions independently from each other? so loop1{blink LED 2 times/second} loop2{blink LED2 5 times/second} Sorry if this is extremely basic. Thanks in advance!

Nope. It's not a stupid question, so take a look at http://arduino.cc/en/Tutorial/BlinkWithoutDelay.

I hope this helps,

Brad.

hey Brad, thanks fore the quick reply, yeah that helps a little, but what about just splitting up the thing into two individual loops, is that possible? Im kinda trying o keep it simple.

Arduino can. My Mega2560 is doing so right now using cooperative multi-tasking. It's set up to handle 16 asynchronous tasks, but that's a compile-time choice - I can change that to 2 or 200 by modifying a #define. Events (function calls) can be scheduled to run at a particular date/time or after some specified delay. Scheduling is done with usec resolution and, as you would expect with cooperative multitasking, the timing accuracy is largely determined by how frequently the dispatcher receives control. I typically see jitter between -0 and 28 usecs.

That's pretty straight forward, along these lines:

void setup(){
unsigned long old100mStime  millis(); // capture the time
unsigned lonng old250mStime = old100mStime;  // set so both are the same
// along with other variables, pinModes, etc
}

void loop() {

if (millis()> (old100mStime+100)){  // has 100mS passed?
if yes: change state of 5x/sec LED  // leave that for you do
old100mStime = old100mStime + 100;  // set up for next time thru
}

if (millis()> (old250mStime+100)){  // has 250mS passed?
if yes: change state of 2x/sec LED
old250mStime = old250mStime + 250;  // set up for next time thru
}

http://gammon.com.au/blink

[quote author=Morris Dovey link=topic=91874.msg690075#msg690075 date=1329201931] Arduino can.[/quote]

No, it can't. The OP asked if the Arduino could run two loops at the same time.

I know what co-operative multitasking is... and multi-tasking in general. Hell, even what an RTOS is.

None of them can actually run two loops at the same time.

It might appear to be at the same time, but it's not.

FWIW,

Brad.

PS for something kinda simple, take a look at http://bleaklow.com/2010/07/20/a_very_simple_arduino_task_manager.html

Hmm. Then I assume that you know the difference between a function named loop() and and a code construct called a "loop" which result in repeated execution of a sequence of instructions. Here are two such sequences (and yes, they do execute concurrently):

#include "fusion.h"

// Global variables

time_t cycle1 = 0;
time_t cycle2 = 0;

// Loop 1

void led1(void)
{  static int state1 = 0;
   digitalWrite(LED1,state1 ^= 1);
   schd(cycle1 += 250000,led1);
}

// Loop 2

void led2(void)
{  static int state2 = 0;
   digitalWrite(LED2,state2 ^= 1);
   schd(cycle2 += 100000,led2);
}

// Arduino setup()

void setup(void)
{  pinMode(LED1,OUTPUT);
   pinMode(LED2,OUTPUT);
   cycle1 = cycle2 = now();
   led1();
   led2();
}

// Arduino loop()

void loop(void)
{  idle();
}

Edit: code simplification

Say you are cooking dinner and vacuuming the floor. You are doing both “at the same time”.

Sorry to piggyback on this thread, but I have a similar question: My project I'd like to do has two speakers, that will each play a line of music. (One bass, and another treble) Is it possible for the arduino to have both playing at the same time? I tried to think it through but the only thing I thought of was the base playing a while loop of the bass, but then the treble would never run.

My project I’d like to do has two speakers, that will each play a line of music.

Have you tried playing music through just one speaker to see how that sounds? Pretty awful, isn’t it?

Thinking of it as each speaker representing an instrument, or a singer playing a single part, not one speaker playing the entire song itself.

You can certainly play two sets of notes but, as PaulS pointed out, you're probably not going to like the result very well. If you're using digitalWrite(), frequency modulation is possible but there may be an upper bound on the range - and amplitude modulation won't be available (all notes will be played with the same loudness). If you're using analogWrite(), then you're likely to encounter some compute speed limitations.

It might be interesting (for you) to experiment to see where the limitations fall. :grin:

[quote author=Morris Dovey link=topic=91874.msg690120#msg690120 date=1329205862] Hmm. Then I assume that you know the difference between a function named loop() and and a code construct called a "loop" which result in repeated execution of a sequence of instructions. Here are two such sequences (and yes, they do execute concurrently): [/quote]

I stand corrected. I guess I missed the OP's intent and the exact same time was my interpretation .

Brad.

@Brad - you were spot on with respect to simultaneity, since that would require either another processor or additional (outboard) circuitry. With my cobbled-together approach I can come within 30 usec of exact task synchronization, which is probably adequate for human consumption but perhaps marginal for lab instrumentation.

Thanks for the link, by the way. It's always fun to see how other people solve problems. :-)

cbredlow: My project I'd like to do has two speakers, that will each play a line of music. (One bass, and another treble) Is it possible for the arduino to have both playing at the same time?

I suppose it depends how this music is going to be generated. But certainly the Arduino can do multiple things at the same time, in this sense ...

Say you want to have two lights on "at the same time". You can do this:

  • Turn on light 1
  • Turn on light 2 (a millisecond later)

To people watching both lights seemed to come on at once, and they are now both on together. It took an action to turn them on, it doesn't take an action to keep them on. In the same way that, in your house, you have lots of lights on at once, once you initially go around turning them on, one by one.

Now for the music, the Arduino with only 2 Kb of RAM doesn't have a lot to hold sampled music, so you aren't going to get too far with that, unless you have external peripherals. It has 3 timers capable of generating tones, so you could get Timer 1 to start a tone on one speaker, and Timer 2 to do a tone on the other speaker. Then when it was time to change notes you change the appropriate tones.

WOAH. did not expect to see 15 replies today. thank you to everyone for the quick replies! A little more detail on the use of this, I want to put a RGB led in an arcade style button, I have some code to make it fade between colors. I want to run this (looping) while also reading the button and doing other stuff from the resulting state of the button. How do any of you suggest going about this?

Button(im going to replace the white led with a RGB one):http://www.paradisearcadeshop.com/en/234-led-convex-arcade-pushbuttonwhite-led-convex-arcade-pushbutton.html

Fading Code:

#define GREEN 3
#define BLUE 5
#define RED 6
#define delayTime 20

void setup() {

  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(RED, OUTPUT);
  digitalWrite(GREEN, HIGH);
  digitalWrite(BLUE, HIGH);
  digitalWrite(RED, HIGH);
}

int redVal;
int blueVal;
int greenVal;
 
void loop() {
 
  int redVal = 255;
  int blueVal = 0;
  int greenVal = 0;
  for( int i = 0 ; i < 255 ; i += 1 ){
    greenVal += 1;
    redVal -= 1;
    analogWrite( GREEN, 255 - greenVal );
    analogWrite( RED, 255 - redVal );

    delay( delayTime );
  }
 
  redVal = 0;
  blueVal = 0;
  greenVal = 255;
  for( int i = 0 ; i < 255 ; i += 1 ){
    blueVal += 1;
    greenVal -= 1;
    analogWrite( BLUE, 255 - blueVal );
    analogWrite( GREEN, 255 - greenVal );

    delay( delayTime );
  }
 
  redVal = 0;
  blueVal = 255;
  greenVal = 0;
  for( int i = 0 ; i < 255 ; i += 1 ){
    redVal += 1;
    blueVal -= 1;
    analogWrite( RED, 255 - redVal );
    analogWrite( BLUE, 255 - blueVal );

    delay( delayTime );
  }
}

Get rid of the delays.

http://gammon.com.au/blink

(I’m curious - where is UKF?)

I couldn’t resist the urge to play with your code and ended up withis this (untested):

#define GREEN 3
#define BLUE 5
#define RED 6

void (*execute)();
unsigned long runTime,delayTime = 20;
int index,redVal,blueVal,greenVal;

void cycle1_head(void)
{  redVal = 255;
   index = blueVal = greenVal = 0;
   execute = cycle1_body;
}
void cycle1_body(void)
{  if (index++ < 255)
   {  analogWrite(GREEN,255 - ++greenVal);
      analogWrite(RED,255 - --redVal);
      runTime += delayTime;
   }
   else execute = cycle2_head;
}
void cycle2_head(void)
{  greenVal = 255;
   index = redVal = blueVal = 0;
   execute = cycle2_body;
}
void cycle2_body(void)
{  if (index++ < 255)
   {  analogWrite(BLUE,255 - ++blueVal);
      analogWrite(GREEN,255 - --greenVal);
      runTime += delayTime;
   }
   else execute = cycle3_head;
}
void cycle3_head(void)
{  blueVal = 255;
   index = redVal = greenVal = 0;
   execute = cycle3_body;
}
void cycle3_body(void)
{  if (index++ < 255)
   {  analogWrite(RED,255 - ++redVal);
      analogWrite(BLUE,255 - --blueVal);
      runTime += delayTime;
   }
   else execute = cycle1_head;
}
void setup(void)
{  pinMode(GREEN,OUTPUT);
   pinMode(BLUE,OUTPUT);
   pinMode(RED,OUTPUT);
   digitalWrite(GREEN,HIGH);
   digitalWrite(BLUE,HIGH);
   digitalWrite(RED,HIGH);
   runTime = millis();
   execute = cycle1_head;
}
void loop(void)
{  while (millis() >= runTime) execute();

   /* Whatever else you want to do in loop() */
}

If you do try it with a multi-color LED, I’d like to know how well it works. :grin:

Edited for compactness and clarity

Awesome. It did exactly the same thing as when it was running on the old code, nice job. Frome. But as to the original question, there isnt a way to do a simple loop1 and loop2? you HAVE to mess around so there is no delay?