2

I understand that Arduino programming is procedural and not so much Object Orientated and also that the Arduino or AVR are only single core processors and any kind of "Multitasking" or "Threading" is emulated at best but I was wondering if there is a way to pause program execution in one area temporarily and give another area control? For example say we have the following class:

Class A{
   void Test();
   void ProgramLoop();
}

void A::Test(){
   for (int i = 0; i < 10; i++){
      //Lots of cool stuff going on here but need to give
      //Control to someone else say ProgramLoop()
      Sleep(10);
   }
}

void A::ProgramLoop(){
   Serial.println("In Program Loop");
}

Then in the main file:

A testClass;

void Setup(){
   Serial.begin(57600);
}

void Loop(){
   testClass.Test();
   testClass.ProgramLoop();
}

I know I could do something like:

void Loop(){
   if (!testClass.isBusy){
      testClass.ProgramLoop();
   }
}

But I am trying to find out if there is a way to control how the program execution gives control? I understand that this is more of a threading topic, thats not what I am trying to get at, I just want to know if this is possible maybe using some sort of built in function or something? Or do my programs have to "Fall Through" being ONLY Procedural?

  • You could use a timer interrupt and build your own scheduler, like any preemptive multitasking OS on a single core machine (though resources will be tight). But it is probably better to do your long tasks in pieces, perhaps as state machines that advance one state each time they are called. If the thing that needs to happen in the meantime is simple, perhaps you could just do that in an interrupt on the timer or some relevant occurence (pin change, serial rx, etc) – Chris Stratton May 14 '16 at 15:34
1

This article gives a great example of multitasking by using FreeRTOS.

I am pasting the sample code snippet which is pretty much self explanatory.

#include <Arduino_FreeRTOS.h>

// define two tasks for Blink & AnalogRead
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );

// the setup function runs once when you press reset or power the board
void setup() {

  // Now set up two tasks to run independently.
  xTaskCreate(
    TaskBlink
    ,  (const portCHAR *)"Blink"   // A name just for humans
    ,  128  // Stack size
    ,  NULL
    ,  2  // priority
    ,  NULL );

  xTaskCreate(
    TaskAnalogRead
    ,  (const portCHAR *) "AnalogRead"
    ,  128 // This stack size can be checked & adjusted by reading Highwater
    ,  NULL
    ,  1  // priority
    ,  NULL );

  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskBlink(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);

  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
    digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
  }
}

void TaskAnalogRead(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  for (;;)
  {
    // read the input on analog pin 0:
    int sensorValue = analogRead(A0);
    // print out the value you read:
    Serial.println(sensorValue);
    vTaskDelay(1);  // one tick delay (15ms) in between reads for stability
  }
}
1

If you have used threading before, this library-

https://github.com/ivanseidel/ArduinoThread

makes it very easy to schedule tasks in a controlled manner.

I would put this in a comment, but I don't have enough reputation yet.

  • I am a little confused in the readme it states "On the one hand, this means that the only way a task can “yield” the CPU is by returning to the caller, and it is thus inadvisable to delay() or do long waits inside a task." does this library have a function to give control to another process? Or would you have to put a return and let the program flow back to that point again? – Andy Braham May 15 '16 at 14:06
  • I am by no means an expert on threads, but I think the writer might have confused threads and processes. As for your second question, I think you'd switch between threads by using SetInterval. – Tri May 17 '16 at 17:19

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.