0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Raspberry Pi 3 でタクトスイッチをトグル動作にしてチャタリングを体験したい

0
Last updated at Posted at 2026-07-20

プロローグ

スイッチの特性によりON/OFF動作で接触部の金属が瞬間的にビヨヨーンと何度か跳ね返るため思ったように動作しないことらしい。
正式には「バウンシング」というようだが、一般的には「チャタリング」も多く使われていてYouTubeで「チャタリング」で検索すると、マウスがシングルクリックがダブルクリックになってしまうような現象がよくヒットする。
このチャタリングを解消する方法としては、回路にコンデンサを追加したりするハードウェア的な方法やプログラムで何とかするソフトウェア的な方法や、はたまたマウスの誤動作なら呉556的なものをシュッとする方法もあるようだが、ここではもちろんプログラムで何とかする方法を試すことにする。

回路

前回の内部プルアップ抵抗を使ったタクトスイッチでLEDを光らせるやつを流用する。

internal_pull-up_回路図.png

ソースコード

スイッチをトグル動作(押すたびにONとOFFが切り替わる)にした方がチャタリングが再現しやすそうなので、トグル動作にしてみる。
ここへきてONとOFFが逆なのがややこしくてたまらない。

toggle_swicth1.c
#include <stdio.h>
#include <wiringPi.h>

#define LED_PIN_BCM 17
#define BUTTON_PIN_BCM 18

int main(void) {
    if (wiringPiSetupPinType(WPI_PIN_BCM) == -1) {
        printf("setup wiringPi failed.");
        return 1;
    }

    // pull up
    pullUpDnControl(BUTTON_PIN_BCM, PUD_UP);
    
    int prev = HIGH;        // 前回スイッチ状態 (HIGH=Not Pressed)
    int current = HIGH;     // 今回スイッチ状態
    int alt = HIGH;         // 点灯状態 (HIGH=Off)

    pinMode(LED_PIN_BCM, OUTPUT);
    pinMode(BUTTON_PIN_BCM, INPUT);
    digitalWrite(LED_PIN_BCM, alt);    // Led off

    while (1) {
        // 今回状態を前回状態へ
        prev = current;
        // スイッチ状態を取得
        current = digitalRead(BUTTON_PIN_BCM);

        // スイッチの切り替わりを検出 (LOW=Pressed)
        if (prev == HIGH && current == LOW) {
            // 点灯切り替え
            alt = !alt;
            printf("switch on. prev:%d current:%d Led %s.\n", prev, current, alt == LOW ? "on" : "off");
            digitalWrite(LED_PIN_BCM, alt);
        }
     }

    return 0;
}

実行

$ gcc ./toggle_swicth1.c -o toggle_swicth1 -lwiringPi
$ ./toggle_swicth1

時々、ON→OFFにしようとしてONのままになったりその逆だったりになる。
思ったほどには起きないが、一度起きると何度も続けて起きる感じがある。
チャタリング発生時は標準出力に出している switch on. ... がワンプッシュで2回出ていてOFFになったのがまたONに戻っている。

チャタリング対策

スイッチが押された時と離された時にも20ミリ秒の待機を入れる。

toggle_swicth2.c
#include <stdio.h>
#include <wiringPi.h>

#define LED_PIN_BCM 17
#define BUTTON_PIN_BCM 18
#define DELAY_MS 20

int main(void) {
    if (wiringPiSetupPinType(WPI_PIN_BCM) == -1) {
        printf("setup wiringPi failed.");
        return 1;
    }

    // pull up
    pullUpDnControl(BUTTON_PIN_BCM, PUD_UP);
    
    int prev = HIGH;        // 前回スイッチ状態 (HIGH=Not Pressed)
    int current = HIGH;     // 今回スイッチ状態
    int alt = HIGH;         // 点灯状態 (HIGH=Off)

    pinMode(LED_PIN_BCM, OUTPUT);
    pinMode(BUTTON_PIN_BCM, INPUT);
    digitalWrite(LED_PIN_BCM, alt);    // Led off

    while (1) {
        // 今回状態を前回状態へ
        prev = current;
        // スイッチ状態を取得
        current = digitalRead(BUTTON_PIN_BCM);

        // スイッチの切り替わり(ON)を検出 (LOW=Pressed)
        if (prev == HIGH && current == LOW) {
            // 点灯切り替え
            alt = !alt;
            printf("switch on. prev:%d current:%d Led %s.\n", prev, current, alt == LOW ? "on" : "off");
            digitalWrite(LED_PIN_BCM, alt);
            delay(DELAY_MS);
        // スイッチの切り替わり(OFF)を検出
        } else if (prev == LOW && current == HIGH) {
            printf("switch off. prev:%d current:%d Led %s.\n", prev, current, alt == LOW ? "on" : "off");
            delay(DELAY_MS);
        }
     }

    return 0;
}

まぁ直った。とりあえず再現しなくなった。

エピローグ

タクトスイッチにも飽きてきたけれどもうちょっとやる。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?