Windows IoT CoreのArduino言語で割り込み&バックグラウンド処理
Interrupt & background tasks for Arduino on Windows IoT Core
ArduinoやPICのワンチップマイコンは基本的にマルチスレッドに対応していません。そのため、割り込み処理が発生すると、その関数を実行している間はメイン関数が滞るため、2つ以上の作業を同時進行するとなると、プログラミングに結構な手間がかかります(
FreeRTOSなどの組み込み機器に特化したOSを使う方法もあります)。
Windows IoT Coreはもちろんマルチスレッドに対応している(むしろUWPベースなのでマルチタスクのプログラミングが必須)ので、GPIO処理の早いArduinoプログラムで取得したデータをRaspberry Pi 2などのパワフルなコンピューターで処理する方法も簡単に実装できます。
Arduino言語で割り込み処理のある回路とプログラムを作ってみます。回路はタクトスイッチと抵抗を置いただけのシンプルなものです。Arduinoでは割り込みができるピンが限られていますが、Raspberry Piでは基本的にどのGPIOピンでも割り込み処理を受け付けるので、ここではGPIO4を使っています。
Windows IoT Coreでは割り込み設定(attachInterrupt)での割り込み番号はピン番号と同じになります。まずは、Visual Studioのデバッガーでボタンを押すたびに出力欄に「Pressed.」と表示されるか確認してください。
multithread.ino
#define INT_PIN GPIO4
void onPushSwitch()
{
Serial.println("Pressed.");
}
void setup()
{
Serial.begin(9200);
pinMode(INT_PIN, INPUT);
attachInterrupt(INT_PIN, onPushSwitch, FALLING);
}
void loop()
{
}
では、バックグラウンド処理を行うプログラムを作ってみましょう。Arduino Wiring ProjectはC++/CXのメインメソッドから呼び出されていますが、逆にinoファイルにランタイムクラスを入れることもできます。むろんランタイムクラスを含むプログラムはArduino Unoなどではコンパイルできませんが、そもそもマイコンを使ったArduinoではできないことを実装するため、気にしたところで意味がありません。
C++/CXによるバックグラウンド処理のプログラム例を掲載します。ここでは、命令が実行されてから5秒後にデバッガーにメッセージを表示します。「create_task」がC#における非同期処理に当たります。簡単な解説は「
C#プログラマーのためのC++/CX基礎知識」をご覧ください。
async.h
#pragma once
ref class Async sealed
{
public:
Async();
void Wait();
};
async.cpp
#include <Async.h>
#include <ppltasks.h>
using namespace concurrency;
#include <thread>
using namespace std;
Async::Async()
{
}
void Async::Wait()
{
create_task(([this]() {
this_thread::sleep_for(chrono::seconds(5));
OutputDebugString(L"Wait finish\n");
}));
}
後はこのクラスをinoファイルに組み込めば完成です。
main.ino
#include "Async.h"
#define INT_PIN GPIO4
Async ^a;
void onPushSwitch()
{
Serial.println("Pressed.");
a->Wait();
}
void setup()
{
Serial.begin(9200);
a = ref new Async();
pinMode(INT_PIN, INPUT);
attachInterrupt(INT_PIN, onPushSwitch, FALLING);
}
void loop()
{
}
このプログラムを実行すると、ボタンを押してからしばらくしてからメッセージが表示されます。通常の割り込み処理と違い、重い処理をしている間にボタンを連打しても、押した数だけ割り込み処理が発生し、その分だけ終了メッセージが表示されます。
2017/04/05