外部イベントの検知~ポーリング~
スイッチが押された・センサが反応したといった,いつ起こるか分からない 「非同期イベント」を検知する方法として,割り込みとポーリングという 2 つの代表的な検知方法がある.
ポーリングは「イベントが発生していないかを定期的にチェックする」という 方法である.while 文などでループを回しながらイベントが発生していないか を if 文で確認するような操作に相当する.この方法ではチェックするための ループが回るのに時間がかかると,リアルタイムに非同期イベントを検知でき ないということが生じる.そのため,マルチタスクなプログラムを作成し,メ インループと非同期イベント検知のためのループを別々に回すようにすれば, ほぼリアルタイムに非同期イベントの発生を検知できる.
ESP-IDF におけるマルチタスク
ESP32 は CPU コアが 2 つあるデュアルコア構成となっているので, マルチタスクなプログラムを作成する際は,これらのコアの それぞれで別々の処理を行わせることになる.
ESP-IDF は OS としてオープンソースのリアルタイム OS である FreeRTOS (Real Time Operating System) を使用しており,そのタスク管理機能を 使うと CPU コアそれぞれで別々の処理をさせることができる.
以下のサンプルでは vTaskDelay, xTaskCreate といった関数が出てくるが, これは freeRTOS の機能である.
ポーリング (マルチタスク) を使ったプログラム
ポーリングはマルチタスクで実現する.メインループ以外の非同期イベント 検知用ループを用意しておけばよい. マルチタスクのプログラム中では xTaskCreate 関数を用いる必要がある. この関数の詳細は, FreeRTOSのドキュメント を参照されたい.
プロジェクトの準備
サンプルプロジェクトをコピーする.
$ cd ~/esp $ cp -r esp-idf/examples/get-started/sample_project ./polling $ cd polling
プログラムの作成
このサンプルプロジェクトのメインファイルは main ディレクトリ以下の main.c であるので, そのファイルを編集する.エディタとして,vi, emacs, gedit, code などが使える.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#define INPUT_PIN 34
#define LED_PIN1 13
#define LED_PIN2 14
// LED1 を 5 秒間隔で回すタスク
static void task1(void * pvParameters) {
int count = 0;
while (1) {
gpio_set_level(LED_PIN1, count % 2);
vTaskDelay( 5000 / portTICK_PERIOD_MS ); //5秒間隔
count++;
}
}
// LED2 の ON/OFF
static void task2(void * pvParameters) {
int count = 0;
while (1) {
gpio_set_level(LED_PIN2, count % 2);
vTaskDelay( 100 / portTICK_PERIOD_MS ); //若干待つ.
count++;
}
}
void app_main(void)
{
//LED 初期化
gpio_reset_pin(LED_PIN1); // ピンのリセット
gpio_set_direction(LED_PIN1, GPIO_MODE_OUTPUT); // ピンを出力で利用
gpio_reset_pin(LED_PIN2); // ピンのリセット
gpio_set_direction(LED_PIN2, GPIO_MODE_OUTPUT); // ピンを出力で利用
//マルチタスク.(引数の 1 は優先順位)
xTaskCreate(task1, "LED1", 2048, NULL, 1, NULL);
xTaskCreate(task2, "LED2", 2048, NULL, 1, NULL);
}
プログラムを実行する.
$ make flash monitor
上記の割り込みのプログラムと同様に,スイッチの ON/OFF に従って LED2 が即座に点灯/消灯することが確認できるだろう.
実践課題 3
実践課題 2 で作成したプログラムをマルチタスクのプログラムに書き換え, 同様の動作が実現されるようにしなさい.なお,デバウンス時間は設定しなくて良い.