「ESPr Developer」をIoTで使う場合、外から取り込んだ信号をトリガーとして処理を行なったり、一定時間ごとに処理を行なったりすることが多くあります。
リンク
このような用途に対し、これまではloop関数の中で直接対処していましたが、今回、「割り込み処理」について少し調べたのでまとめておきます。
タイマー割り込み
ESPr Developer でタイマー割り込みを行う方法は、以下のとおりです。
【使用例1】
#include <Ticker.h>
Ticker ticker;
void function() {
// 定期的な処理
}
void setup() {
ticker.attach(30, function);
}
【関数】
- ticker.attach(sec, function):タイマー割り込み(秒単位)
- ticker.attach_ms(msec, function):タイマー割り込み(msec単位)
- ticker.detach():タイマー割り込みを停止
- sec:割り込み時間(sec単位)
- msec:割り込み時間(msec単位)
- function:割り込み発生時に呼び出す関数(割り込み関数)
なお、割り込み関数の中では、ネットワーク通信などの処理は行えません。
これを行うためには、割り込み関数の中でフラグを立て、loop関数内でフラグに応じて処理を行なったあと、フラグを落とします。
【使用例2】
#include <Ticker.h>
Ticker ticker;
volatile boolean flag = false;
void function_flag() {
flag = true;
}
void function_exec() {
// 定期的な処理
flag = false;
}
void setup() {
ticker.attach(30, function_flag);
}
void loop() {
if(flag) {
function_exec();
}
}
端子割り込み
入力端子の信号変化に応じて、割り込みを行う方法は、以下のとおりです。
【関数】
- attachInterrupt(digitalPinToInterrupt(pin), function, mode)
- pin:ピン番号 ※digitalPinToInterruptで「ピン番号」を「割り込み番号」に変換する。
- function:割り込み発生時に呼び出す関数(割り込み関数)
- 割り込み関数は引数と戻り値が不要なもののみ。
- delay関数は機能しない。
- millis関数の戻り値は増加しない。
- シリアル通信により受信したデータは、失われる可能性がある。
- 割り込み関数の中で値が変化する変数には、volatile修飾子をつけて宣言する。
- mode:割り込みを発生させるトリガ
- LOW:ピンがLOWのとき。
- CHANGE:ピンが変化したとき。
- RISING:ピンがLOWからHIGHに変化したとき。
- FALLING:ピンがHIGHからLOWに変化したとき。
ESPr Developerでは、IO16以外のGPIO端子が、割り込みに使用できる模様です。
この関数では、入力端子の変化に応じて割り込みを行います。内部での処理結果に応じて割り込みを行いたい場合は、内部処理の結果を一旦外に出し、それを外部信号として再び取り込む必要があるようです。
【使用例】
これらを踏まえて、以下の処理を行うスケッチを作ってみました。
- スイッチを押すと、LEDが点灯する。
- 10秒たつと、LEDが消灯する。
- LED点灯中にスイッチを押すと、それから10秒LEDが点灯し続ける。
#include <Ticker.h>
Ticker ticker;
volatile boolean state = false;
#define PIN_SW 12
#define PIN_LED 4
void onDetected() {
if(state) {
ticker.detach();
ticker.attach(10, onTimer);
} else {
ticker.attach(10, onTimer);
digitalWrite(PIN_LED, HIGH);
state = true;
}
}
void onTimer() {
ticker.detach();
digitalWrite(PIN_LED, LOW);
state = false;
}
void setup() {
pinMode(PIN_SW, INPUT);
attachInterrupt(digitalPinToInterrupt(PIN_SW), onDetected, RISING);
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, LOW);
}
void loop() {
}
リンク