2016年6月27日月曜日

Arduinoでマルチタスクを実現する方法


マルチタスク(マルチスレッド)を実現するまでにまあまあ時間がかかったので、まとめます。

ライブラリ[SchedulerARMAVR]の準備

下記リポジトリの一部にあります。

fabriceo/SCoop

このように設置しました。
cd [arduino sketch dir]/libraries
git clone git@github.com:fabriceo/SCoop.git
ln -s SCoop/SchedulerARMAVR ./

2016.11.06現在、Arduino IDE1.6.10以上で上記のライブラリを使うとコンパイルエラーが発生します。
pull requestがマージされればエラーは解消されますが、それまでは下記のようにプルリク元のライブラリを使うのが良さそうです。
cd [arduino sketch dir]/libraries
git clone -b coopSchedule-used-attribute git@github.com:per1234/SCoop.git
ln -s SCoop/SchedulerARMAVR ./

プログラムの作成

LEDを違うタイミングで点滅させてみます。
multi_threading_test
#include <SchedulerARMAVR.h>

int red_led_pin   = 2;
int green_led_pin = 3;
int blue_led_pin  = 4;

void setup() {
  pinMode(red_led_pin,   OUTPUT);
  pinMode(green_led_pin, OUTPUT);
  pinMode(blue_led_pin,  OUTPUT);
  Scheduler.startLoop(loop2);
  Scheduler.startLoop(loop3);
}

void loop() {
  led_on_and_off(red_led_pin, 500, 500);
}

void loop2() {
  led_on_and_off(green_led_pin, 1000, 1000);
}

void loop3() {
  led_on_and_off(blue_led_pin, 1500, 1500);
}

void led_on_and_off(int led_pin, int power_on_millisec, int power_off_millisec) {
  digitalWrite(led_pin, HIGH);
  delay(power_on_millisec);
  digitalWrite(led_pin, LOW);
  delay(power_off_millisec);
}

delay無しのloopは動かなかったので、delayが必要ない処理でも「delay(10)」位を記述するのが良さそうです。

回路の作成

3つのLEDを点滅できる回路を作りました。


動作確認

うまくいけばこのようにLEDが光ります。


余談

Arduinoの公式ページで紹介されている Scheduler はArduino DUEのマルチタスクしかサポートされていないため、Arduino Nano向けのコンパイルはできませんでした。
そのため、 フォーラム(Topic: Multithreading Using Arduino Due) で紹介されていたSchedulerARMAVRを利用しました。

しかし、その古くからあるSchedulerもAVR系(一般的なArduinoに使われているマイコン)のマルチタスクをサポートしようとする流れがあります。
興味のある方はご覧ください。(出来ればコミットもしてもらえると嬉しいです。)

porting scheduler for Avr

以上です。

更新情報

2016.11.06
Arduino IDE 1.6.10以上で発生するコンパイルエラーの回避方法を記述しました。
2016.11.16
「Arduinoの公式ページで紹介されているScheduler」の説明文を修正しました。

0 件のコメント :

コメントを投稿