概要
Arduino Unoに使用されているAVRはシングルスレッドのため、x86 CPUのようなマルチスレッド処理はできませんが、代わりにプロトスレッド処理を組み込むライブラリがあります。
https://playground.arduino.cc/Code/TimedAction/
プロトスレッドとは簡易的なマルチスレッドであり、各スレッドはノンプリエンプティブ(あるタスクがCPUを専有している間は他の処理を開始できない)です。
今回はこのライブラリを用いて、Arduinoにマルチスレッド的な動作を組み込みます。
環境
- Arduino UNO
- Sparkfun Wireless Motor Driver Shield
- サーボ:SG90
ライブラリ導入
- このページの"Download here: Attach:TimedAction-1_6.zip"からzipをダウンロード&解凍。中身をarduinoIDEのライブラリディレクトリに入れてください。
- このままですとコンパイル時にエラーが出る場合があるので、1で配置した中身のTimedAction.hの
#include "WProgram.h"
を#include "Arduino.h"
に変更してください。
コード
サーボは2秒毎に反転動作、LEDは3秒毎にLチカさせてます。
#include <TimedAction.h>
#include <Servo.h>
Servo swivel;
#define ledPin 13
boolean ledState = false;
boolean servoState = false;
void blink();
void toggle_servo();
TimedAction ledAction = TimedAction(3000,blink);
TimedAction servoAction = TimedAction(2000,toggle_servo);
void setup(){
delay(5000);
pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,ledState);
swivel.attach(11); // Attach servo to pin 11
swivel.write(90);
}
void loop(){
ledAction.check();
servoAction.check();
}
void blink(){
ledState ? ledState=false : ledState=true;
digitalWrite(ledPin,ledState);
}
void toggle_servo(){
servoState ? servoState=false : servoState=true;
if (servoState){
swivel.write(90);
}else{
swivel.write(100);
}
}
動作検証
サーボは2秒毎、LEDは3秒毎に動作をしています。
今後
ここでプリエンプティブな実装を行っているので、試したいです。
Haskellによる実装
以下にてHaskellのAtomライブラリを使用した並列処理を掲載しています。
https://zenn.dev/4ergfbv547uezdf/scraps/2fe2002b0ebfb0
コード載せていないですがArduinoでも利用可能でした。ただしこのライブラリの難易度は超高いです。
参考サイト
https://playground.arduino.cc/Code/TimedAction/
https://learn.sparkfun.com/tutorials/wireless-motor-driver-shield-hookup-guide/all