チャタリングについて
スイッチのon/offの直後に、出力が振動してしまう現象のことを チャタリング
と呼ぶ。
現実のスイッチは、on/off切り替え時に一発でピタッと接点がくっつくことがなく、跳ねたり擦れたりして、接地が振動してしまうため発生してしまう。
上記の記事より
チャタリングの現象確認
オシロスコープは持っていないので、ログで現象を確認した。
以下、変更した箇所のみ。
...
void ARDUINO_ISR_ATTR isr() {
const unsigned long now = millis();
diff_times[numberKeyPresses] = now - falled_time_ms;
numberKeyPresses += 1;
pressed = true;
falled_time_ms = now;
}
void checkPressed() {
if (pressed) {
for(int i = 0 ; i < numberKeyPresses; i++){
Serial.printf("diff time %u ms\n", diff_times[i]);
}
Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses);
pressed = false;
}
}
private:
const uint8_t PIN;
volatile uint32_t numberKeyPresses = 0;
volatile bool pressed = false;
volatile unsigned long falled_time_ms = 0;
volatile unsigned long diff_times[128] = {};
};
...
// ここを変えないとreboot祭りになってしまった。
Button* button1;
void setup() {
Serial.begin(115200);
button1 = new Button(BUTTON1);
}
void loop() {
button1->checkPressed();
}
これを書き込んで、4回スイッチを押した結果が下記。
4回目押した際に、チャタリングっぽい挙動がでていた。
diff time 1187 ms
Button on pin 16 has been pressed 1 times
diff time 1187 ms
diff time 951 ms
Button on pin 16 has been pressed 2 times
diff time 1187 ms
diff time 951 ms
diff time 1065 ms
Button on pin 16 has been pressed 3 times
diff time 1187 ms
diff time 951 ms
diff time 1065 ms
diff time 1106 ms
Button on pin 16 has been pressed 4 times
diff time 1187 ms
diff time 951 ms
diff time 1065 ms
diff time 1106 ms
diff time 89 ms
diff time 0 ms
diff time 0 ms
Button on pin 16 has been pressed 7 times
チャタリングの対策方法について
チャタリングの対策方法に関しては、ハードウェアによる解決とソフトウェアによる解決がある。
今回は、パーツを増やしたくなかったのでソフトウェアによる解決について説明する。
ソフトウェアによるチャタリング対策
単純に一定時間待つディレイ方式や、チャタリング期間より長い周期でサンプルするサンプリング方式などがあるよう。
....
void ARDUINO_ISR_ATTR isr() {
const unsigned long now = millis();
const unsigned long diff = now - falled_time_ms;
diff_times[numberKeyPresses] = diff;
if(diff > CHATTERING_TIME_MS){
numberKeyPresses += 1;
pressed = true;
}
falled_time_ms = now;
}
自分の環境ではCHATTERING_TIME_MSを150ぐらいにするとちょうどよかった。チャタリングは数100μs~数ms程度らしい※が、結構大きめにしないとダメだった。
微細な振動のチャタリングというよりは、スイッチ自体が大きく跳ねたりしてるのかな?
diff time 64765 ms
Button on pin 16 has been pressed 1 times
diff time 64765 ms
diff time 488 ms
Button on pin 16 has been pressed 2 times
diff time 64765 ms
diff time 488 ms
diff time 417 ms
Button on pin 16 has been pressed 3 times
diff time 64765 ms
diff time 488 ms
diff time 417 ms
diff time 578 ms
Button on pin 16 has been pressed 4 times
終わりに
esp32のサンプルコードに対して、チャタリング対策を入れてみた。
ディレイ方式やサンプリング方式など、一般的なやり方とサンプルコードの実装方式が合わなかったので、別のやり方をとったが、自分が使う分には問題なさそう。