SW-420振動センサーとArduino:衝撃の検知とアラーム
SW-420振動センサーとArduinoの使い方。仕組み、感度調整、パルスの計数と衝撃の時間測定、防犯アラーム、地震アラームの限界とMPU6050、ESP32のTelegram通知まで解説します。
Arduinoの振動センサーのプロジェクトでいちばんよく使われるのが、安くてシンプルなSW-420モジュールです。デジタルピン1本で、表面が揺れた、誰かがドアをノックした、引き出しが開けられた、機械が動き始めた、といったことを知らせてくれます。モジュールには、ばね式の振動スイッチ、LM393コンパレーターIC、感度を設定する小さなポテンショメーターが載っています。使い方は簡単ですが、最初に試すと多くの人が同じ2つの問題にぶつかります。センサーが一部の振動を見逃すことと、ときどきまったく理由なくアラームが鳴ることです。
このガイドでは、SW-420の中にあるばね式接点の仕組み、出力が短いパルスとして届く理由、感度の正しい設定方法を学びます。続いて割り込みでパルスを数え、衝撃がどれくらい続き、どれくらい強かったかを測り、誤報を減らす防犯アラームを作ります。地震アラームというアイデアが見た目ほど単純ではない理由と、MPU6050加速度センサーで何ができるようになるかも説明します。最後に、振動を検知したときにESP32でスマホへTelegramのメッセージを送り、Raspberry Pi Pico用のMicroPythonのコードも書きます。

SW-420振動センサーとは?仕組みは?
このモジュールの本当の検知部は、小さな円筒形の金属ケースに入った常時閉(NC)の振動スイッチです。ケースの中にはばねと導電性の部品があり、センサーが静止しているときは両者が触れていて接点は閉じています。センサーが揺れるとばねが振れ、接点は1回あたり1ミリ秒未満のごく短い間隔で開閉を繰り返します。スイッチ自体には方向性がないので、どの方向からの振動にも反応します。モジュールのLM393は、このスイッチが作る電圧をポテンショメーターで決めたしきい値と比べ、きれいなデジタル出力(DO)を出します。多くのモジュールでは、静止中はDOがLOW、振動中はHIGHになり、基板の信号LEDが振動に合わせて消えたり点滅したりします。互換品の基板によっては論理が逆のこともあるので、まずシリアルモニタで手元のモジュールを確認してください。
| 項目 | 値 |
|---|---|
| 検知部 | SW-420、常時閉のばね式振動スイッチ |
| 電源 | 3.3〜5 V |
| 出力 | デジタル(DO)、LM393コンパレーター経由 |
| 感度調整 | 基板上のポテンショメーター |
| 方向 | 方向性なし、どの方向からの振動にも反応 |
| 出力信号 | 振動中に短いパルスが連続して出る |
| ピン | VCC、GND、DO |
| 基板サイズ | 約32 × 14 mm、M3の取り付け穴1個 |
SW-420とArduinoの配線
| モジュールのピン | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 | 3V3(OUT) |
| GND | GND | GND | GND |
| DO | D2(割り込みピンINT0) | GPIO 27 | GP15 |
感度:ポテンショメーターはどう調整する?
ポテンショメーターはコンパレーターのしきい値を決めます。感度が高すぎると、テーブルにコップを置いた振動、近くを通るトラック、さらには自分のブザーの振動まで拾ってしまいます。低すぎると、強くたたいたときにしか反応しません。正しく設定するには、実際に使う面にモジュールをネジで固定し、基板の信号LEDを見ながら調整します。静止中はLEDが安定していて、指で面を軽くたたくと反応する位置までポテンショメーターを回し、そこから感度をほんの少し下げて余裕を持たせます。この設定は面の材質によって変わります。同じ設定でも、木のテーブルではとても敏感で、コンクリートの壁ではほとんど反応しないことがあります。
最初のテスト:振動を検知して短いパルスをとらえる
初心者が最初に書くコードは、たいていloop()の中でdigitalRead()でピンを読み、HIGHならLEDを点灯するものです。強くたたけばこれでも動きますが、軽い振動ではほとんど何も起きません。SW-420の出力がHIGHになるのはわずか数百マイクロ秒のことがあり、その瞬間にloop()がSerial.print()やdelay()で忙しいとパルスを見逃すからです。解決策は、パルスを割り込みでとらえ、次のパルスまでの時刻を記録することです。次のコードはパルスごとに時刻を記録し、最後のパルスから1秒間LEDを点灯させるので、ごく短い振動でも目で確認できます。
1const byte VIB_PIN = 2; // SW-420 DO (INT0)
2const byte LED_PIN = 13; // dahili LED / onboard LED
3const unsigned long HOLD_MS = 1000; // son darbeden sonra LED süresi / LED time after the last pulse
4
5volatile unsigned long lastPulseMs = 0;
6volatile bool pulseSeen = false;
7
8void onVibration() { // her darbede çalışır / runs on every pulse
9 lastPulseMs = millis();
10 pulseSeen = true;
11}
12
13void setup() {
14 pinMode(VIB_PIN, INPUT);
15 pinMode(LED_PIN, OUTPUT);
16 attachInterrupt(digitalPinToInterrupt(VIB_PIN), onVibration, RISING); // LOW → HIGH geçişi / LOW to HIGH edge
17 Serial.begin(9600);
18}
19
20void loop() {
21 noInterrupts();
22 unsigned long last = lastPulseMs;
23 bool seen = pulseSeen;
24 pulseSeen = false;
25 interrupts();
26
27 if (seen) Serial.println(F("Titresim / vibration"));
28 digitalWrite(LED_PIN, (last > 0 && millis() - last < HOLD_MS) ? HIGH : LOW);
29}割り込みは、ピンがLOWからHIGHに変わるエッジごとに実行されます。Unoでこの種の外部割り込みが使えるのはD2とD3だけです。モジュールの論理が逆なら、RISINGの代わりにFALLINGと書いてください。パルスの連続は立ち上がりと立ち下がりの両方のエッジでできているので、カウントは変わりません。割り込み関数はできるだけ短くし、中でSerialは使いません。表示はloop()で行います。loop()で変数を読む間だけ割り込みを一時的に止めると、複数バイトの変数が読み取りの途中で変わって壊れた値になるのを防げます。
パルスの計数と時間測定:衝撃はどれくらい続き、どれくらい強かった?
SW-420は加速度を測りませんが、出るパルスの数から衝撃の強さをある程度推測できます。軽くたたくと数個、ドアを勢いよく閉めると数十個、ドリルの振動なら1秒に数百個のパルスが出ます。次のコードは割り込みでパルスを数え、それをイベントにまとめます。最初のパルスでイベントが始まり、500 msの間新しいパルスが来なければイベントが終わります。イベントごとに、継続時間、パルスの合計数、1秒あたりのパルス密度を表示します。こうして身の回りで起きるイベントの「指紋」を作り、アラームのしきい値を勘ではなく測定にもとづいて決められます。
1const byte VIB_PIN = 2; // SW-420 DO (INT0)
2const unsigned long QUIET_MS = 500; // bu kadar sessizlik olayı bitirir / this much silence ends an event
3
4volatile unsigned long pulseCount = 0;
5volatile unsigned long lastPulseMs = 0;
6
7bool inEvent = false;
8unsigned long eventStart = 0;
9unsigned long eventStartCount = 0;
10
11void onVibration() {
12 pulseCount++;
13 lastPulseMs = millis();
14}
15
16void setup() {
17 pinMode(VIB_PIN, INPUT);
18 attachInterrupt(digitalPinToInterrupt(VIB_PIN), onVibration, RISING);
19 Serial.begin(9600);
20 Serial.println(F("Sure(ms) Darbe/pulses Darbe/sn (pulses/s)"));
21}
22
23void loop() {
24 noInterrupts();
25 unsigned long count = pulseCount;
26 unsigned long last = lastPulseMs;
27 interrupts();
28
29 if (!inEvent && count != eventStartCount) { // yeni olay başladı / a new event started
30 inEvent = true;
31 eventStart = last;
32 }
33 if (inEvent && millis() - last > QUIET_MS) { // olay bitti / the event is over
34 unsigned long duration = last - eventStart;
35 unsigned long pulses = count - eventStartCount;
36 float density = duration > 0 ? pulses * 1000.0 / duration : pulses;
37 Serial.print(duration);
38 Serial.print(F(" "));
39 Serial.print(pulses);
40 Serial.print(F(" "));
41 Serial.println(density, 0);
42 eventStartCount = count;
43 inEvent = false;
44 }
45}コードを動かしたら、テーブルをいろいろな方法でたたいたり、引き出しを開けたり、ドアを閉めたりして、出てくる数値をメモします。1回の短いタップでは、継続時間はほぼゼロで、パルス数は1桁のことが多いです。長く続く振動では、継続時間もパルス数も大きくなります。この2つの値を組み合わせると、単なる「振動あり・なし」よりずっと強力です。たとえば金庫に取り付けたセンサーなら、「300 ms以上続き、パルスが20個以上あるイベント」というルールで、そばを歩く人の足音を除外しつつ、金庫をこじ開けようとする人はとらえられます。
SW-420で作る防犯アラームと誤報の減らし方
窓ガラス、自転車、引き出し、金庫に取り付けたSW-420は、シンプルな防犯アラームの中心になります。よいアラームと悪いアラームの差は、検知そのものより、誤報をどう取り除くかにあります。次のコードはこれを3段階で行います。警戒を開始してから10秒の退出猶予時間を設け、1回のノックではなく1秒以内に5個以上のパルスを検出したときに作動し、サイレンが鳴る15秒間は新しいパルスを無視します。警戒・解除はD4のボタンで行い、アクティブブザーはD8、状態表示LEDはD13につなぎます。より本格的なシステムについては「Arduinoのアラームシステム」のガイドを参照してください。
1const byte VIB_PIN = 2; // SW-420 DO (INT0)
2const byte BUTTON_PIN = 4; // kur / kapat butonu, D4 ile GND arası / arm-disarm button
3const byte BUZZER_PIN = 8; // aktif buzzer / active buzzer
4const byte LED_PIN = 13; // durum LED'i / status LED
5const unsigned int MIN_PULSES = 5; // pencerede gereken darbe / pulses needed in the window
6const unsigned long WINDOW_MS = 1000; // sayım penceresi / counting window
7const unsigned long EXIT_DELAY_MS = 10000; // kurduktan sonra çıkış süresi / exit delay after arming
8const unsigned long ALARM_MS = 15000; // siren süresi / siren duration
9
10enum AlarmState { DISARMED, ARMING, ARMED, ALARM };
11AlarmState state = DISARMED;
12
13volatile unsigned int pulses = 0;
14unsigned long stateTime = 0;
15unsigned long windowStart = 0;
16unsigned long lastPress = 0;
17bool lastButton = HIGH;
18
19void onVibration() {
20 pulses++;
21}
22
23void setState(AlarmState s) {
24 state = s;
25 stateTime = millis();
26 digitalWrite(BUZZER_PIN, LOW);
27 noInterrupts();
28 pulses = 0; // eski darbeleri sil / discard old pulses
29 interrupts();
30 windowStart = millis();
31}
32
33void setup() {
34 pinMode(VIB_PIN, INPUT);
35 pinMode(BUTTON_PIN, INPUT_PULLUP);
36 pinMode(BUZZER_PIN, OUTPUT);
37 pinMode(LED_PIN, OUTPUT);
38 attachInterrupt(digitalPinToInterrupt(VIB_PIN), onVibration, RISING);
39 Serial.begin(9600);
40}
41
42void loop() {
43 bool button = digitalRead(BUTTON_PIN);
44 if (button == LOW && lastButton == HIGH && millis() - lastPress > 200) {
45 lastPress = millis();
46 setState(state == DISARMED ? ARMING : DISARMED);
47 Serial.println(state == ARMING ? F("Kuruluyor / arming") : F("Kapatildi / disarmed"));
48 }
49 lastButton = button;
50
51 if (millis() - windowStart >= WINDOW_MS) { // her saniye darbe sayısına bak / check the pulse count every second
52 noInterrupts();
53 unsigned int n = pulses;
54 pulses = 0;
55 interrupts();
56 windowStart = millis();
57 if (state == ARMED && n >= MIN_PULSES) {
58 setState(ALARM);
59 Serial.print(F("ALARM! darbe / pulses: "));
60 Serial.println(n);
61 }
62 }
63
64 switch (state) {
65 case DISARMED:
66 digitalWrite(LED_PIN, LOW);
67 break;
68 case ARMING: // hızlı yanıp sönme: çıkış süresi / fast blink: exit delay
69 digitalWrite(LED_PIN, (millis() / 250) % 2);
70 if (millis() - stateTime >= EXIT_DELAY_MS) setState(ARMED);
71 break;
72 case ARMED:
73 digitalWrite(LED_PIN, HIGH);
74 break;
75 case ALARM: // kesik kesik siren / intermittent siren
76 digitalWrite(BUZZER_PIN, (millis() / 300) % 2);
77 if (millis() - stateTime >= ALARM_MS) setState(ARMED);
78 break;
79 }
80}誤報を減らすために、コード以外でもできることはたくさんあります。
- しっかり固定する:モジュールはM3のネジか硬い接着剤で面に固定します。ぐらぐらする基板はそれ自体が振動します。
- ブザーを離す:サイレンがセンサーと同じ基板や同じケースに付いていると、自分の振動でアラームを再び作動させてしまうことがあります。
- 感度は設置場所で調整する:ポテンショメーターは机の上ではなく、センサーを最終的に取り付ける面で調整します。
- ケーブルは短く、固定する:空中で揺れる長いケーブルはノイズを拾います。必要ならDOとGNDの間に100 nFを入れます。
- センサーを2個使う:重要な場所では、2個のセンサーが短時間のうちに両方作動することを条件にすると、誤報を大きく減らせます。
- 別のセンサーで確認する:振動をPIR人感センサーやドアセンサーと組み合わせると信頼性が上がります。
SW-420で地震アラームは作れる?限界とMPU6050
地震アラームは振動センサーのプロジェクトのアイデアとして特に人気があり、学びの多いプロジェクトです。ただし、その限界を知っておくことが大切です。SW-420が伝えられるのは「何かが揺れた」ことだけで、揺れの加速度、方向、周波数は測れません。そのため、ドアを勢いよく閉めたとき、トラックが通ったとき、洗濯機が脱水しているとき、本物の地震のどれにも同じように反応します。さらに重要なのは、1個のセンサーは揺れがその場所に届いてはじめて揺れを検知するということです。公式の地震の早期警報システム(日本では気象庁の緊急地震速報)は、震源に近い多数の観測点の測定を組み合わせ、揺れが届く前に遠くの地域へ警報を届けます。家庭のArduinoはその代わりにはならず、命を守るための安全装置として使ってはいけません。
地震のプロジェクトをもっと意味のあるものにしたいなら、MPU6050加速度・ジャイロセンサーモジュールに進みましょう。MPU6050は3軸の加速度を16ビットの分解能で測り、測定範囲を±2 g〜±16 gから選べます。これにより、揺れの最大加速度(PGA)を計算したり、加速度が何秒続いたかと周波数を見て、ドアを閉めた衝撃と長く続く地面の揺れを区別したり、データを記録してあとから調べたりできます。2つのセンサーを併用するのも理にかなっています。SW-420はごくわずかな電力で待機して最初の振動でマイコンを起こし、詳しい測定はMPU6050が行います。

| 項目 | SW-420 | MPU6050 |
|---|---|---|
| 何を測る? | 振動のあり・なし | 3軸の加速度と角速度 |
| 出力 | デジタルのパルス(DO) | I2C、16ビットのデジタルデータ |
| 感度 | ポテンショメーターで、おおまか | ソフトウェアで、±2 g〜±16 g |
| 方向 | なし | あり(X、Y、Z) |
| 地震のプロジェクト | 「何かが揺れた」という警告だけ | 最大加速度、継続時間、周波数の分析 |
| コード | 数行、ライブラリ不要 | ライブラリとフィルタリングが必要 |
| 価格 | とても安い | 安い |
振動を検知したらESP32からTelegramで通知
ESP32を使えば、外出中に金庫や自転車、機械に何かあったとき、振動センサーがスマホに知らせてくれます。そのためには、TelegramでBotFatherを使ってボットを作り、トークンと自分のチャットIDを取得し、Arduino IDEにUniversalTelegramBotとArduinoJsonのライブラリをインストールする必要があります。これらの手順は「ESP32のTelegramボット」のガイドで詳しく説明しています。次のコードは割り込みでパルスを数え、1秒間に5個以上のパルスを検出するとメッセージを送ります。1分間に数十件の通知でスマホが埋まらないよう、メッセージの間隔は最低60秒あけます。ESP32はデュアルコアなので、カウンターはportMUXのロックで保護します。
1#include <WiFi.h>
2#include <WiFiClientSecure.h>
3#include <UniversalTelegramBot.h>
4#include <ArduinoJson.h>
5
6const char* WIFI_SSID = "AgAdi"; // Wi-Fi adın (2,4 GHz) / your Wi-Fi name (2.4 GHz)
7const char* WIFI_PASS = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
8#define BOT_TOKEN "1234567890:AAExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // BotFather'ın verdiği token / token from BotFather
9#define CHAT_ID "123456789" // kendi Telegram ID'n / your own Telegram ID
10
11const int VIB_PIN = 27; // SW-420 DO (modül 3V3 ile) / module powered from 3V3
12const unsigned long MIN_PULSES = 5; // 1 sn'de gereken darbe / pulses needed in 1 s
13const unsigned long WINDOW_MS = 1000;
14const unsigned long COOLDOWN_MS = 60000; // iki mesaj arası en az 60 sn / at least 60 s between messages
15
16volatile unsigned long pulseCount = 0;
17portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
18unsigned long windowStart = 0;
19unsigned long lastAlert = 0;
20bool alertSent = false;
21
22WiFiClientSecure client;
23UniversalTelegramBot bot(BOT_TOKEN, client);
24
25void IRAM_ATTR onVibration() { // kesme fonksiyonu RAM'de / interrupt handler in RAM
26 portENTER_CRITICAL_ISR(&mux);
27 pulseCount++;
28 portEXIT_CRITICAL_ISR(&mux);
29}
30
31void setup() {
32 Serial.begin(115200);
33 pinMode(VIB_PIN, INPUT);
34 attachInterrupt(digitalPinToInterrupt(VIB_PIN), onVibration, RISING);
35
36 WiFi.mode(WIFI_STA);
37 WiFi.begin(WIFI_SSID, WIFI_PASS);
38 while (WiFi.status() != WL_CONNECTED) {
39 delay(500);
40 Serial.print(".");
41 }
42 Serial.println();
43 client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // api.telegram.org kök sertifikası / root certificate
44 bot.sendMessage(CHAT_ID, "Titreşim alarmı hazır / vibration alarm ready", "");
45 windowStart = millis();
46}
47
48void loop() {
49 if (millis() - windowStart < WINDOW_MS) return;
50 windowStart = millis();
51
52 portENTER_CRITICAL(&mux); // sayacı güvenle oku ve sıfırla / read and reset safely
53 unsigned long n = pulseCount;
54 pulseCount = 0;
55 portEXIT_CRITICAL(&mux);
56
57 if (n >= MIN_PULSES && (!alertSent || millis() - lastAlert >= COOLDOWN_MS)) {
58 lastAlert = millis();
59 alertSent = true;
60 String msg = "Titreşim algılandı / vibration detected: " + String(n) + " darbe / pulses";
61 Serial.println(msg);
62 if (!bot.sendMessage(CHAT_ID, msg, "")) {
63 Serial.println("Mesaj gonderilemedi / message failed");
64 }
65 }
66}Telegramへのメッセージ送信には1〜2秒かかることがあります。その間ループは待ちますが、割り込みは動き続けるので、届いたパルスはカウンターにたまり、失われません。センサーを電池で動かしたい場合は、ESP32をディープスリープにして、esp_sleep_enable_ext0_wakeup()でSW-420のDOピンをウェイクアップ要因にします。するとESP32は振動があったときだけ起きてメッセージを送り、再びスリープに戻ります。この場合、ウェイクアップ用のピンにはRTC GPIOのいずれかを選んでください。GPIO 27はこのグループに入っています。
Raspberry Pi PicoでSW-420を使う(MicroPython)
Picoでは、モジュールを3V3(OUT)ピンから給電し、DOをGP15につなぎます。次のコードはArduino版と同じイベントの考え方を使います。割り込みでパルスを数え、最初のパルスでボードの内蔵LEDを点灯し、500 ms何も来なければイベントの継続時間とパルス数を表示します。Pin("LED")という名前で、PicoでもPico Wでも内蔵LEDを選べます。
1from machine import Pin, disable_irq, enable_irq
2import time
3
4vib = Pin(15, Pin.IN) # SW-420 DO (modül 3V3 ile) / module powered from 3V3
5led = Pin("LED", Pin.OUT) # dahili LED / onboard LED
6QUIET_MS = 500 # olayı bitiren sessizlik / silence that ends an event
7
8pulses = 0
9def on_vibration(pin):
10 global pulses
11 pulses += 1
12
13vib.irq(trigger=Pin.IRQ_RISING, handler=on_vibration)
14
15event_start = None
16event_pulses = 0
17last_pulse = 0
18while True:
19 state = disable_irq() # sayacı güvenle oku / read the counter safely
20 n = pulses
21 pulses = 0
22 enable_irq(state)
23
24 now = time.ticks_ms()
25 if n:
26 if event_start is None: # yeni olay / new event
27 event_start = now
28 event_pulses = 0
29 led.on()
30 event_pulses += n
31 last_pulse = now
32 elif event_start is not None and time.ticks_diff(now, last_pulse) > QUIET_MS:
33 duration = time.ticks_diff(last_pulse, event_start)
34 print("Titresim / vibration: %d ms, %d darbe / pulses" % (duration, event_pulses))
35 event_start = None
36 led.off()
37 time.sleep_ms(20)振動センサーを使ったプロジェクトのアイデア
- 自転車・バイクのアラーム:駐車中の車体が揺らされると鳴り、ESP32でスマホに知らせる小さなボックス。
- 洗濯終了のお知らせ:振動が5分間止まったら「洗濯が終わりました」というメッセージを送るセンサー。
- 秘密のノック検知器:決まったリズムでノックすると開くロック。衝撃イベントの間の時間を比べて実現します。
- 機械の稼働時間カウンター:コンプレッサー、ポンプ、3Dプリンターが1日に何時間動いたかを記録するカウンター。
- 電子金庫:暗証番号のロックと組み合わせ、金庫がこじ開けられるとアラームを鳴らす保護機能。パスワード入力用の「キーパッド」のガイドと組み合わせられます。
- ゲームやインタラクティブなテーブル:テーブルをたたくと光と音が出るドラムや反応ゲーム。
よくある間違いと対処法
| 症状 | 考えられる原因 | 対処法 |
|---|---|---|
| 軽い振動を検知しない | loop()の中でdigitalRead()でパルスを読んでいて見逃している | attachInterrupt()で割り込みを使う |
| センサーが何度も作動する | 感度が高すぎる、または基板がぐらついている | ポテンショメーターを設置場所で調整し、基板をネジで固定する |
| アラームが勝手にまた鳴る | ブザーの振動がセンサーに伝わっている | ブザーはセンサーから離し、別の面に取り付ける |
| 論理が逆に動く | 互換品のモジュールでDO出力が反転している | シリアルモニタで確認し、必要ならFALLINGを使う |
| ESP32のピンが壊れた、または不安定 | モジュールを5 Vで給電したため、DOが5 Vを出した | モジュールを3.3 Vで給電する |
| スマホに数十件のメッセージが届く | 通知の間に待ち時間がない | コードで60秒以上のクールダウンを使う |
SW-420は、表面が揺れたことを知るためのいちばん安くて簡単な方法です。その本当の力は、割り込みでパルスをとらえて数え、結果を継続時間や密度と合わせて読み取ったときに発揮されます。感度は設置場所で調整し、誤報はソフトウェアで取り除き、揺れの強さや方向が必要になったらMPU6050に進みましょう。BlueGraysアプリでは、「ブザーの使い方」「人感センサーで動きを検出」「Telegramで通知するESP32の動体検知アラームシステム」のプロジェクトを、「スマート電子金庫」のプロジェクトとともに、ステップごとの回路図とコード付きで見ることができます。
よくある質問
振動センサーはどのように動作しますか?
SW-420のような振動センサーには、金属ケースの中にばねと導電性の部品が入っています。静止しているときは接点が閉じていて、揺れるとばねが振れ、接点がごく短い間隔で開閉を繰り返します。モジュールのLM393コンパレーターが、ポテンショメーターで設定したしきい値にもとづいて、この変化をきれいなデジタル信号に変えます。
SW-420の感度はどう調整しますか?
モジュールのポテンショメーターでコンパレーターのしきい値が変わります。実際に使う面にセンサーを固定し、静止中は信号LEDが安定していて、軽くたたくと反応する位置までポテンショメーターを回してから、感度を少し下げて余裕を持たせます。設定は面の材質によって変わるので、机の上ではなく設置場所で行ってください。
SW-420が一部の振動を見逃すのはなぜですか?
振動中、SW-420の出力はごく短いパルスしか出しません。コードがloop()の中でdigitalRead()でピンを読んでいて、その瞬間にdelay()やSerial.print()で忙しいと、パルスを見逃します。attachInterrupt()で割り込みを使い、割り込み関数の中でパルスを数えれば解決します。
振動センサーで地震検知器は作れますか?
学習用の簡単な揺れアラームなら作れますが、SW-420は振動があることを検知するだけで、強さや方向は測れず、ドアを勢いよく閉めたような出来事と地震を区別できません。1個のセンサーは、揺れがセンサーのところに届いてはじめて気づきます。より意味のある測定にはMPU6050のような加速度センサーを使い、こうしたプロジェクトを公式の早期警報システムの代わりにしないでください。
SW-420はESP32で使えますか?
はい。モジュールをESP32の3V3ピンから給電し、DO出力をGPIO 27などのデジタルピンにつなぎます。モジュールを5 Vで給電するとDO出力も5 Vになり、ESP32のピンを壊すおそれがあります。ESP32では割り込み関数をIRAM_ATTRで宣言し、共有するカウンターはportMUXのロックで保護してください。
SW-420とSW-18010Pの違いは何ですか?
どちらもばね式の振動スイッチですが、接点の構成が違います。SW-420は常時閉で、静止中は接点が閉じていて振動で開きます。SW-18010Pのような常時開のタイプは、静止中は開いていて振動で短時間閉じます。モジュールとして使う場合は、シリアルモニタで出力レベルを確認すれば十分です。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
ブザーの使い方
呼び鈴やアラームがどうやって音を出すのか、気になったことはありませんか?Arduinoが小さなブザーを短い間隔で鳴らし、音を出す、止める、を繰り返します。電気で音が生まれる仕組みを学び、メロディーを演奏するプロジェクトへの第一歩を踏み出せます。

ボタンでLEDを点灯(押している間のみ)
呼び鈴のように、押している間は点灯し、離すと消灯します。Arduinoはボタンの状態を常に読み取り、押されている間はLEDを点灯させ、指を離した瞬間に消灯させます。このシンプルな回路で、ボードが外部からの操作を検知する仕組みを学べます。

人感センサーで動きを検出
誰かが部屋に入ると知らせる、シンプルな見張り役です。人感センサーが人体から放出される熱を捉え、Arduinoは動きがある間LEDを点灯させ、動きが止まると消灯させます。玄関先で自動点灯する照明や、警報システムの基本となる仕組みです。

モーションセンサーで作るドアベルとライト
玄関に誰かが近づくと、呼び鈴を押す前にわかります。モーションセンサーが人を検知するとLEDが点灯し、ブザーが高い音から低い音へ3音のチャイムを鳴らします。メロディーが終わるとライトが消え、センサーは再び待機します。音と光の両方で知らせるシンプルな玄関の見張り役です。

ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)
PIRセンサーが動きを検知するとブザーとLEDを作動させ、同時にTelegramで持ち主に即座に通知するスマート防犯アラームです。アラームが繰り返される頻度を抑えるため、30秒のクールダウン(待ち時間)を設けています。この仕組みはPIRの検知が正しいかを確認したり、誤検知をなくしたりするものではありません。家の防犯、ガレージの監視、倉庫や作業部屋などに使えます。ESP32-CAMなら写真付きの通知を追加でき、通常のESP32 DevKit V1ではテキストで通知します。

スマート電子金庫
貴重品を保管できる、暗証番号で開く小さな金庫です。キーパッドで4桁の暗証番号を入力すると、正しければサーボモーターが解錠し、緑色のLEDが点灯してディスプレイに金庫の状態が表示されます。キーを押すたびにブザーが短く鳴ります。3回間違えると30秒間ロックアウトされます。暗証番号はいつでも変更でき、電源が切れても保持されます。

レーザー防犯システム
映画のレーザーを使った強盗シーンのように、光センサーにレーザー光を当て、人が間に入って光を遮ると、赤いLEDが点灯してブザーが鳴り始めます。警報は自動では止まらず、ボタンやリモコンの電源ボタンで停止します。異常がないときは緑のLEDが点灯します。ドアや引き出しに、目に見えない見張り役を置くユニークな方法です。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

