背景
esp32に限らず、タイマー割り込みを使う際はずーっと同じタイマー間隔で延々とタイマーを入れ続けることが多いかと思います。
でも例えば「2回点滅してちょっと休む」を繰り返すLEDチカチカとかをやろうとすると、同じ時間で繰り返すではやりづらい...※ちょっとロジックを工夫すれば同じ間隔でのタイマーでもできますけど、なんか気持ち悪い
その場合、繰り返しのタイマーを使うのではなく、こんな感じでワンショットタイマーを繰り返し実行したいのです。
- 1回だけのタイマー割り込み(ワンショットタイマー)をセットする
- 時間が経過しタイマーが弾ける(タイマー処理が実行される)
- そのタイマー処理内で、再度時間を指定してタイマー割り込みをセット ※このタイミングで任意のタイマー時刻」をセットする
- 次のタイマー処理が実行される
- ※以降、繰り返し
しかし、ESP32でワンショットタイマーを使うという記事が見つからず、逆にうまく行かない、という例を見つけるぐらいでした。
実際うまく行ったのか?
結論としては、以下となりました。
- esp32-arduino V3系ではOK
- esp32-arduino V2系ではNG
esp32-arduino V2系で本当はやりたかったのですが、今の所 V3系でしかできませんでした。
なぜかV2系では、2回目の設定したタイマー処理が実行されません。
esp32-V3系でワンショットタイマーが動作したプログラム
動作確認時のesp32-arduinoのバージョンはv3.0.7です(2024/12/29 時点の最新)。
hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile uint32_t isrCounter = 0;
volatile uint32_t lastIsrAt = 0;
volatile bool timer_3s = false; // チェック時の値でタイマー時間を決める。false:1秒、true:3秒をセット
void ARDUINO_ISR_ATTR onTimer(){
uint32_t timer_val;
portENTER_CRITICAL_ISR(&timerMux);
isrCounter = isrCounter + 1;
lastIsrAt = millis();
// タイマー時間を決める(1秒 or 3秒)
timer_3s = !timer_3s;
if(timer_3s) {
timer_val = 3000000;
} else {
timer_val = 1000000;
}
timerRestart(timer); // タイマーを再スタート。★★★この行が重要★★★
timerAlarm(timer, timer_val, false, 0); // タイマーを再設定
portEXIT_CRITICAL_ISR(&timerMux);
xSemaphoreGiveFromISR(timerSemaphore, NULL);
}
void setup() {
Serial.begin(115200);
timerSemaphore = xSemaphoreCreateBinary();
timer = timerBegin(1000000);
timerAttachInterrupt(timer, &onTimer);
timerAlarm(timer, 1000000, false, 0); // 第3引数をfalse指定で、繰り返し無し=ワンショットタイマー。その際は第4引数は無効
}
void loop() {
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
uint32_t isrCount = 0, isrTime = 0;
portENTER_CRITICAL(&timerMux);
isrCount = isrCounter;
isrTime = lastIsrAt;
portEXIT_CRITICAL(&timerMux);
// タイマー割り込みが実行された時刻を表示
Serial.print("onTimer no. ");
Serial.print(isrCount);
Serial.print(" at ");
Serial.print(isrTime);
Serial.println(" ms");
}
}
まとめ
本来やりたかったesp32-arduino V2系ではできなかったのですが、V3系では可能なことを確認できたのでまずはよし、としようと思います。
なお、この記事は、【札幌現地+オンライン開催】力強くブログを108記事アウトプットする日の 20241229のブログの一つとして書きました。
参加した皆さん、お疲れ様です!