web-dev-qa-db-ja.com

Arduinoはスレッドをサポートしていますか?

Arduinoにはいくつかのタスクがありますが、そのうちの1つは非常に時間がかかるため、スレッドを使用してそれらを同時に実行することを考えていました。 Arduino Megaを持っています

[更新]最後に4年後、私のArduino megaにFreeRTOSをインストールできます。これが link です

20
Snake Sanders

つまり、いいえ。しかし、次の場所で試してみることができます: http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/

13

まだですが、このライブラリは常に大きなプロジェクトで使用しています https://github.com/ivanseidel/ArduinoThread

タイマーコールバック内にコールバックを配置します。 Arduinoで疑似スレッドが実行されています...

5
Ivan Seidel

このスレッドをより完全にするために:メモリフットプリントが非常に小さい(=覚えていればバイトを結合する)protothreadsもあり、スレッドにローカルな変数を保持します。非常に便利で時間を節約できます(有限状態マシンがはるかに少ない->より読みやすいコード)。

例とコード: arduino-class/ProtoThreads wiki

期待できる結果を知らせるためだけに:シリアル通信@ 153K6のボーレートとスレッド:ステータスダイオードの点滅、計時、要求された機能の評価、IO処理とロジック、およびすべてatmega328で。

5
Mr. Girgitt

実際のスレッドではありませんが、TimedActionsは多くの用途に適した代替手段です

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

もちろん、1つのタスクがブロックすると、他のタスクもブロックされますが、スレッド化により1つのタスクがフリーズし、他のタスクは続行します...

4
FrancescoMM

Arduinoはマルチスレッドプログラミングをサポートしていません。

ただし、たとえば このプロジェクト の回避策など、いくつかの回避策があります(Arduino IDEからもインストールできます)。

実際のマルチスレッド環境では、いつタスクを実行するかを決定するのはOSですが、自分でスケジュール時間を定義する必要があるようです。

または、 protothreads を使用することもできます

1
Francesco Boi

arduinos を使用できます

Arduino環境用に設計されています。特徴:

  • 静的割り当てのみ(malloc/newなし)
  • 実行遅延時のコンテキスト切り替えをサポート
  • セマフォを実装します
  • CPUとメモリの両方が軽量

古いコマンドの実行中にbluetooth/network/serialから新しいコマンドを受信する必要があり、古いコマンドの遅延がある場合に使用します。 1つのスレッドは、次のループを実行するサーバースレッドです。

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
}

もう1つは、コマンドを実行するコマンドスレッドです。

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

前の答えは正しいですが、arduinoは一般にかなり高速に実行されるため、コードのタイミングを適切に調整すると、多かれ少なかれ同時にタスクを実行できます。

ベストプラクティスは、独自の関数を作成し、実際のコードをデフォルトのvoidループに入れすぎないようにすることです。

1
lkrasner

いいえ、できませんが、タイマー割り込みを使用できます。

1

Arduinoはスレッドをサポートしていません。ただし、次善の策を講じて、インターリーブで実行されているステートマシンを中心にコードを構造化できます。

タスクをステートマシンとして実装する方法はたくさんありますが、このライブラリ( https://github.com/Elidio/StateMachine )をお勧めします。このライブラリは、プロセスのほとんどを抽象化します。

次のように、ステートマシンをクラスとして作成できます。

#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);
      }
};

マクロSTATEMACHINE()はクラスの継承を抽象化し、マクロCREATE_STATE()は状態ラッパーの作成を抽象化し、マクロINIT_STATE()はメソッドラッピングを抽象化し、マクロSTATE()は状態ラッパーを抽象化しますステートマシンクラス内の参照。

状態遷移は、ステートマシンクラスと状態の間の<<演算子によって抽象化されます。遅延状態遷移が必要な場合は、その演算子を整数で使用するだけです。整数は、ミリ秒。

ステートマシンを使用するには、まずそれをインスタンス化する必要があります。セットアップ関数でnewを使用してインスタンス化するときに、グローバル空間でクラスへの参照を宣言すると、うまくいく場合があります

Blink *led1, *led2, *led3;


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

次に、states on loopを実行します。

void loop() {
    (*led2)();
    (*led1)();
    (*led3)();
}
0
Luiz Menezes