0

Simple question, of course if you do this

FunctionA();
Delay(1000);
FunctionB();
FunctionC();

it will call A, then wait a second, then call B, then call C.

How does one do this? ...

FunctionA();
.. Invoke FunctionX one second from now ..
FunctionB();
FunctionC();

So, I want it to do A, then without stopping continue to B and then C. Later (one second later) it will do X.

Of course, in c# you'd just use a coroutine, in Android you'd use a Handler or whatever.

Surely there's a command along the lines of .. invoke in .. 2000 .. method.

Really sorry for the basic question, experts, I am damned if I can find this anywhere. Thanks!

1

Surely there's a command along the lines of .. invoke in .. 2000 .. method.

Not "a command" but you can make up something like that easily enough. Example:

// Function scheduler demo
// Author: Nick Gammon
// Date: 11 July 2015

typedef void (*GeneralFunction) (); // function pointer type

GeneralFunction wantedFunction = NULL;  // function to call
unsigned long functionTimerStarted;     // when the timer started
unsigned long delayPeriod;              // how long to wait (ms)

void functionA ()
  {
  Serial.println ("Function A");
  }  // end of functionA

void functionB ()
  {
  Serial.println ("Function B");
  }  // end of functionB

void functionC ()
  {
  Serial.println ("Function C");
  }  // end of functionC

void functionX ()
  {
  Serial.println ("Function X");
  }  // end of functionX

void scheduleFunction (GeneralFunction f, unsigned long when);  // prototype
void scheduleFunction (GeneralFunction f, unsigned long when)
  {
  wantedFunction = f;
  functionTimerStarted = millis ();
  delayPeriod = when;
  }  // end of scheduleFunction

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  functionA ();  // call this now
  scheduleFunction (functionX, 2000);  // call this later
  functionB ();  // call this now
  functionC ();  // call this now

  }  // end of setup

void loop ()
  {
  // see if time to call the delayed function
  if (wantedFunction && millis () - functionTimerStarted >= delayPeriod)
    {
    wantedFunction ();
    wantedFunction = NULL;  // don't call it again
    }  // end of if time up

  // do other wanted stuff here

  }  // end of loop

This uses:

  • A function pointer to remember which function to call in the future.
  • A global variable to remember when you wanted this timing interval to start.
  • A global variable to remember how long to wait.

In setup() I called a function to save this information for future use:

  scheduleFunction (functionX, 2000);  // call this later

Then in loop() we see if the time is up, and then call the function.

This example just calls functions with no arguments, things will get more complex if you want to call a function with an argument. It would even be possible to remember the argument, but it may be unnecessarily complicated to explain how to do that, since your example did not ask for it.

You could also even schedule multiple functions, but again, showing all that adds to the complexity of the explanation.

For more information about function pointers, see Function pointers / function callbacks / function variables.

  • Hi Nick. Thanks for that detailed code sample! Thanks for letting me know there is indeed no "schedule" or "invoke" like function .. interesting. It's interesting you really have to "roll your own" just using the main run loop. Of course, this is a "one shot" solution, if you send another scheduleFunction it will walk over the previous one right! I'm wondering is there a trivial way to say start a new thread or some such? perhaps that would allow for a more flexible solution. Again it's priceless info there is NO schedule or invoke -like command, thanks!!!! – Fattie Jul 11 '15 at 8:03
  • 1
    There is no pre-emptive multi-tasking because the (AVR) hardware does not support it. The Unix-based boards probably do. The best you can manage is co-operative multi-tasking, where you give other functions a chance to run at some suitable point. If you wanted to have multiple functions scheduled you would have to expand what I wrote a bit, for example to have an array of outstanding functions. However you may want to design your project with a different paradigm, people have done quite complex projects without scheduling functions to run in the future. – Nick Gammon Jul 11 '15 at 8:12
  • 1
    @JoeBlow: No, there is no trivial way to start a new thread. You would need to install some sort of scheduler, which you don't have in the standard Arduino environment. You can take a look to the ArduinoThread library though. It is not threads, it's rather a generalization of Nick Gammon's approach. – Edgar Bonet Jul 11 '15 at 8:13
  • Hi Nick ... fascinating. Brilliant, thanks. Hi Edgar, that's awesome - again thanks for the definitive information. You guys are the best. Yes I will just write my own threadesque, blocker, etc. Thanks!!!!! – Fattie Jul 11 '15 at 8:20
  • @NickGammon: Preemptive multitasking is possible on the AVR. See Atomthreads for example. I never tried, and it's likely to be expensive in RAM, as you need a per-thread call stack. – Edgar Bonet Jul 11 '15 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.