Does Arduino support threading?

2019-03-10 06:28发布

问题:

I have a couple of tasks to do with arduino but one of them takes very long time, so I was thinking to use threads to run them simultaneously. I have an Arduino Mega

[Update] Finally after four years I can install FreeRTOS in my arduino mega. Here is a link

回答1:

In short: NO. But you may give it a shot at: http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/



回答2:

Not yet, but I always use this Library with big projects: https://github.com/ivanseidel/ArduinoThread

I place the callback within a Timer interrupt, and voilá! You have pseudo-threads running on the Arduino...



回答3:

Just to make this thread more complete: there are also protothreads which have very small memory footprint (couple bytes if I remember right) and preserve variables local to thread; very handy and time saving (far less finite state machines -> more readable code).

Examples and code: arduino-class / ProtoThreads wiki

Just to let you know what results you may expect: serial communication @ 153K6 baudrate with threads for: status diodes blinking, time keeping, requested functions evaluation, IO handling and logic and all on atmega328.



回答4:

Not real threading but TimedActions are a good alternative for many uses

http://playground.arduino.cc/Code/TimedAction#Example

Of course, if one task blocks, the others will too, while threading can let one task freeze and the others will continue...



回答5:

The previous answer is correct, however, the arduino generally runs pretty quick, so if you properly time your code, it can accomplish tasks more or less simultaneously.

The best practice is to make your own functions and avoid putting too much real code in the default void loop



回答6:

You can use arduinos

It is designed for Arduino environment. Features:

  • Only static allocation (no malloc/new)
  • Support context switching when delaying execution
  • Implements semaphores
  • Lightweight, both cpu and memory

I use it when I need to receive new commands from bluetooth/network/serial while executing the old ones and the old ones have delay in them. One thread is the sever thread that does the following loop:

while (1) {
    while ((n = Serial.read()) != -1) {
        // do something with n, like filling a buffer
        if (command_was_received) {
            arduinos_create(command_func, arg);
        }
    }
    arduinos_yield(); // context switch to other threads
}

The other is the command thread that executes the command:

int command_func(void* arg) {
    // move some servos
    arduinos_delay(1000); // wait for them to move
    // move some more servos
}


回答7:

No you can't but you can use Timer interrupt.



回答8:

Arduino does not support multithread programming.

However there have been some workarounds, for example the one in this project (you can install it also from the Arduino IDE).

It seems you have to define the schedule time yourself while in a real multithread environment it is the OS that decides when to execute tasks.

Alternatively you can use protothreads



回答9:

Arduino does not supports threading. However, you can do the next best thing and structure your code around state machines running in interleaving.

While there are lots of ways to implement your tasks as state machines, I recommend this library (https://github.com/Elidio/StateMachine). This library abstracts most of the process.

You can create a state machine as a class like this:

#include "StateMachine.h"
class STATEMACHINE(Blink) {
  private:
    int port;
    int waitTime;
    CREATE_STATE(low);
    CREATE_STATE(high);

    void low() {
      digitalWrite(port, LOW);
      *this << &STATE(high)<< waitTime;
    }
    void high() {
      digitalWrite(port, HIGH);
      *this << &STATE(low)<< waitTime;
    }
  public:
    Blink(int port = 0, int waitTime = 0) :
      port(port),
      waitTime(waitTime),
      INIT_STATE(low),
      INIT_STATE(high)
      {
        pinMode(port, OUTPUT);
        *this << &STATE(low);
      }
};

The macro STATEMACHINE() abstracts the class inheritances, the macro CREATE_STATE() abstracts the state wrapper creation, the macro INIT_STATE() abstracts method wrapping and the macro STATE() abstracts state wrapper reference within the state machine class.

State transition is abstracted by << operator between the state machine class and the state, and if you want a delayed state transition, all you have to do is to use that operator with an integer, where the integer is the delay in millisseconds.

To use the state machine, first you have to instantiate it. Declaring an reference to the class in global space while instantiating it with new on setup function might do the trick

Blink *led1, *led2, *led3;


void setup() {
  led1 = new Blink(12, 300);
  led2 = new Blink(11, 500);
  led3 = new Blink(10, 700);
}

Then you run the states on loop.

void loop() {
    (*led2)();
    (*led1)();
    (*led3)();
}