読者です 読者をやめる 読者になる 読者になる

mbed OS 5でのイベント処理(mbed events libraryの使い方)

はじめに

この記事はmbed Advent Calendar 2016の4日目の記事です。

mbed OS 5でイベント駆動なプログラムを書くためのライブラリ mbed-events-library の使い方を紹介します。 なお、ドキュメントに書いてあるコードは古いのか正常に動かないところがあったので、GithubのREADMEを参照して検証しました。

mbed-events-libraryが追加されたことで、従来の RtosTimer はdeprecated*1となったようです。

動かしてみる

青mbed(LPC1768)を使って実験しました。 p18 にPullUpでタクトスイッチをつけています。

1. 即実行されるイベント

EventQueueインスタンスを作成し、callメソッドを呼び出すことで即実行されるイベントを追加することができます。

dispatch メソッドを実行するとイベントループが廻り続けるため、最後に while(true) といった記述は必要ありません。

サンプルコードと実際の動作

#include "mbed.h"

DigitalOut led1(LED1);
InterruptIn sw1(p18);

// イベントキューを作成する
EventQueue queue;

// LEDのON/OFFを切り替える関数
void toggle_led() {
    led1 = !led1;
}

// タクトスイッチが押されたときに実行される関数
void pushed() {
    // 即実行されるイベント
    queue.call(&toggle_led);
}

int main() {
    // スイッチピンをPullUpにする
    sw1.mode(PullUp);

    // タクトスイッチが押されたときの割り込み処理
    sw1.fall(&pushed);

    // イベントループが廻り続ける
    queue.dispatch();
}

動作させたのが以下の動画です。スイッチを押すとLEDがON/OFFします。

f:id:mia_0032:20161203210614g:plain

2. 指定時間後に実行されるイベント

EventQueueインスタンスに対して call_in メソッドを呼び出すことで 指定ミリ秒後に実行されるイベントを作成することができます。

サンプルコードと実際の動作

先ほどのコードに queue.call_in(2000, &toggle_led); を追加し、ボタンを押してから2000ミリ秒(2秒)後に消える処理を追加しました。

#include "mbed.h"

DigitalOut led1(LED1);
InterruptIn sw1(p18);

// イベントキューを作成する
EventQueue queue;

// LEDのON/OFFを切り替える関数
void toggle_led() {
    led1 = !led1;
}

// タクトスイッチが押されたときに実行される関数
void pushed() {
    // 即実行されるイベント
    queue.call(&toggle_led);
    // 2000ms後に実行されるイベント
    queue.call_in(2000, &toggle_led);
}

int main() {
    // スイッチピンをPullUpにする
    sw1.mode(PullUp);

    // タクトスイッチが押されたときの割り込み処理
    sw1.fall(&pushed);

    // イベントループが廻り続ける
    queue.dispatch();
}

動作させたのが以下のようになります。スイッチを押すとLEDがONし、2秒後にOFFになります。

f:id:mia_0032:20161203210632g:plain

なお、ON/OFFするイベントをひたすらキューに積んでいる形になるため、連打するとON/OFFの順番は崩れます・・・

3. 指定時間ごとに定期実行されるイベント

EventQueueインスタンスに対して call_every メソッドを呼び出すことで 指定ミリ秒ごとに実行されるイベントを作成することができます。

サンプルコードと実際の動作

先ほどのコードからスイッチの処理を取り除き、call_every で1秒ごとに実行されるイベントを追加したものになります。

#include "mbed.h"

DigitalOut led1(LED1);

// イベントキューを作成する
EventQueue queue;

// LEDのON/OFFを切り替える関数
void toggle_led() {
    led1 = !led1;
}

int main() {
    // 1000msごとに定期実行するイベント
    queue.call_every(1000, &toggle_led);

    // イベントループが廻り続ける
    queue.dispatch();
}

動作させると以下のように、1秒ごとにLEDのON/OFFを繰り返します。

f:id:mia_0032:20161203210643g:plain

おわりに

今回のコードは以下のリポジトリに公開しています。 mbed import してお使いください。

github.com

以前、mbed OSのTechnical Preview版のときはMINARと呼ばれるイベントスケジューラーがあり、それを検証したことがありました。

そのときは結構な行数のコードが必要だったのですが、mbed-events-library は非常に簡潔なで直感的なコードで同様のことが実現できるようになったようです。

どんどん進化していますね。