ESPr Developer をIoTで使う場合、外から取り込んだ信号をトリガーとして処理を行なったり、一定時間ごとに処理を行なったりすることが多くあります。
リンク
このような用途に対し、これまではloop関数の中で直接対処していましたが、今回、「割り込み処理」について少し調べたのでまとめておきます。
タイマー割り込み
ESPr Developerでタイマー割り込みを行う方法は、以下のとおりです。
【使用例】
#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関数内でフラグに応じて処理を行なったあと、フラグを落とします。
【使用例】
#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() { }
リンク