Компоненты · 9 мин чтения

Датчик вибрации SW-420 и Arduino: обнаружение ударов и сигнализация

Датчик вибрации SW-420 и Arduino: как он работает, настройка чувствительности, подсчёт импульсов и длительности ударов, охранная сигнализация, пределы идеи с землетрясением, MPU6050 и Telegram на ESP32.

В проектах с датчиком вибрации на Arduino чаще всего используют дешёвый и простой модуль SW-420. Всего через один цифровой пин он сообщает, что поверхность тряхнуло, в дверь постучали, ящик открыли или станок начал работать. На модуле стоят пружинный вибровыключатель, микросхема компаратора LM393 и маленький потенциометр для настройки чувствительности. Пользоваться им легко, но с первой попытки почти у всех возникают одни и те же две проблемы: датчик пропускает часть вибраций, а иногда поднимает тревогу вообще без причины.

В этом руководстве разберём, как работает пружинный контакт внутри SW-420, почему его выходной сигнал приходит короткими импульсами и как правильно настроить чувствительность. Затем посчитаем импульсы с помощью прерывания, измерим, сколько длится удар и насколько он сильный, и соберём охранную сигнализацию с меньшим числом ложных срабатываний. Поговорим и о том, почему идея сигнализации землетрясения не так проста, как кажется, и что в этой задаче даёт акселерометр MPU6050. В конце отправим сообщение в Telegram на телефон с ESP32 при обнаружении вибрации и напишем код на MicroPython для Raspberry Pi Pico.

Модуль датчика вибрации SW-420
Модуль SW-420: пружинный вибровыключатель в металлическом корпусе, компаратор LM393, потенциометр чувствительности и пины VCC, GND, DO.

Что такое датчик вибрации SW-420 и как он работает?

Настоящий чувствительный элемент модуля — нормально замкнутый (NC) вибровыключатель в маленьком цилиндрическом металлическом корпусе. Внутри корпуса находятся пружина и токопроводящая деталь; когда датчик неподвижен, они касаются друг друга и контакт замкнут. Когда датчик трясут, пружина раскачивается, и контакт размыкается и замыкается очень короткими сериями, каждая короче миллисекунды. Сам выключатель ненаправленный, то есть реагирует на вибрацию с любой стороны. LM393 на модуле сравнивает напряжение от этого выключателя с порогом, заданным потенциометром, и выдаёт чистый цифровой выход (DO). На большинстве модулей DO в покое в состоянии LOW, а во время вибрации — HIGH, и сигнальный светодиод на плате гаснет или мерцает вместе с вибрацией; на некоторых клонах логика может быть инверсной, поэтому сначала проверь свой модуль в мониторе порта.

ПараметрЗначение
Чувствительный элементSW-420, нормально замкнутый пружинный вибровыключатель
Питание3,3–5 V
ВыходЦифровой (DO), через компаратор LM393
Настройка чувствительностиПотенциометр на плате
НаправленностьНенаправленный, реагирует на вибрацию с любой стороны
Выходной сигналСерии коротких импульсов во время вибрации
ПиныVCC, GND, DO
Размер платыОколо 32 × 14 мм, отверстие под крепёж M3

Подключение SW-420 к Arduino

Пин модуляArduino UnoESP32Raspberry Pi Pico
VCC5V3V33V3(OUT)
GNDGNDGNDGND
DOD2 (пин прерывания INT0)GPIO 27GP15
На ESP32 и Pico всегда питай модуль от 3,3 V. Выход LM393 поднимается до напряжения питания модуля; если питать модуль от 5 V, на пине DO тоже будет 5 V, и это может повредить вход, рассчитанный на 3,3 V. От 3,3 V модуль работает без проблем; возможно, только придётся заново настроить чувствительность при этом напряжении.

Чувствительность: как настроить потенциометр?

Потенциометр задаёт порог компаратора. Если чувствительность слишком высокая, датчик ловит стакан, поставленный на стол, проезжающий мимо грузовик и даже вибрацию собственного зуммера; если слишком низкая, он реагирует только на сильный удар. Для правильной настройки прикрути модуль к той поверхности, на которой он будет работать, и следи за сигнальным светодиодом на плате. Поверни потенциометр до точки, где в покое светодиод горит ровно, но реагирует, когда слегка стучишь по поверхности пальцем; затем чуть-чуть уменьши чувствительность, чтобы оставить запас. Эта настройка зависит от материала поверхности: одно и то же положение может быть очень чувствительным на деревянном столе и «глухим» на бетонной стене.

Первая проверка: обнаруживаем вибрацию и ловим короткие импульсы

Первый код новичка обычно читает пин через digitalRead() в loop() и зажигает светодиод, когда видит HIGH. При сильном ударе это работает, но при лёгкой вибрации чаще всего ничего не происходит: выход SW-420 может держать HIGH всего несколько сотен микросекунд, и если loop() в этот момент занята Serial.print() или delay(), импульс теряется. Решение — ловить импульс прерыванием и запоминать время до следующего. Код ниже записывает время каждого импульса и держит светодиод включённым 1 секунду после последнего импульса, так что глаз заметит даже очень короткую вибрацию.

C++ (Arduino IDE)
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. Если логика модуля инверсная, напиши FALLING вместо RISING; серии импульсов состоят и из нарастающих, и из спадающих фронтов, поэтому счёт не изменится. Функция прерывания сделана как можно короче и не использует Serial; вывод в порт выполняется в loop(). Короткое отключение прерываний при чтении переменных в loop() не даёт многобайтовой переменной измениться посреди чтения и прочитаться с ошибкой.

Подсчёт импульсов и длительности: сколько длился удар и насколько он был сильным?

SW-420 не измеряет ускорение, но число импульсов, которое он выдаёт, хорошо показывает силу удара: лёгкий стук даёт несколько импульсов, хлопок двери — десятки, а вибрация дрели — сотни в секунду. Код ниже считает импульсы через прерывание и группирует их в события: первый импульс открывает событие, а если 500 мс не приходит новый импульс, событие заканчивается. В конце каждого события выводятся длительность, общее число импульсов и плотность импульсов в секунду. Так можно составить «отпечаток» событий в своём окружении и опирать порог тревоги на измерения, а не на догадки.

C++ (Arduino IDE)
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}

Запусти код, постучи по столу по-разному, открой ящик, закрой дверь и запиши полученные числа. При коротком одиночном стуке длительность часто близка к нулю, а импульсов меньше десяти; долгая вибрация увеличивает и длительность, и число импульсов. Использовать эти два значения вместе гораздо надёжнее, чем простое «вибрация есть или нет»: например, для датчика в сейфе правило «событие длиной не меньше 300 мс и не меньше 20 импульсов» может отсеять шаги проходящего мимо человека и всё равно поймать попытку взломать сейф.

Охранная сигнализация на SW-420 и борьба с ложными срабатываниями

SW-420 на оконном стекле, велосипеде, ящике стола или сейфе может стать сердцем простой охранной сигнализации. Хорошую сигнализацию от плохой отличает не столько обнаружение, сколько то, как она отсеивает ложные срабатывания. Код ниже делает это в три слоя: после постановки на охрану даёт 10-секундную задержку на выход, срабатывает не от одиночного стука, а когда видит не меньше 5 импульсов за 1 секунду, и игнорирует новые импульсы 15 секунд, пока звучит сирена. Ставить на охрану и снимать с неё можно кнопкой на D4, активный зуммер подключён к D8, светодиод состояния — к D13. Более полную систему смотри в руководстве сигнализация на Arduino.

C++ (Arduino IDE)
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 или жёстким клеем; болтающаяся плата вибрирует сама по себе.
  • Убери зуммер подальше: если сирена стоит на той же плате или в том же корпусе, что и датчик, её собственная вибрация может снова запустить тревогу.
  • Настраивай чувствительность на месте: крути потенциометр на той поверхности, где датчик будет стоять в итоге, а не на рабочем столе.
  • Короткие и закреплённые провода: длинные провода, свободно висящие в воздухе, собирают помехи; при необходимости поставь 100 nF между DO и GND.
  • Используй два датчика: в важном месте условие «оба датчика сработали за короткое время» сильно снижает число ложных тревог.
  • Подтверждай другим датчиком: сочетание вибрации с PIR-датчиком движения или датчиком двери повышает надёжность.

Можно ли сделать сигнализацию землетрясения на SW-420? Пределы и MPU6050

Сигнализация землетрясения — одна из самых популярных идей проектов с датчиком вибрации, и проект этот познавательный; но важно понимать его пределы. SW-420 сообщает только «что-то тряхнуло»: он не может измерить ускорение, направление или частоту толчка. Поэтому он одинаково реагирует на хлопнувшую дверь, проезжающий грузовик, стиральную машину на отжиме и настоящее землетрясение. Ещё важнее, что датчик в единственном экземпляре замечает тряску только тогда, когда она уже дошла до места, где он стоит. Официальные системы раннего оповещения о землетрясениях объединяют измерения множества станций рядом с эпицентром и доставляют предупреждение в удалённые районы раньше, чем туда придут толчки; Arduino дома их не заменит, и использовать её как средство защиты жизни нельзя.

Если хочется сделать проект о землетрясениях содержательнее, переходи на модуль акселерометра и гироскопа MPU6050. MPU6050 измеряет ускорение по трём осям с 16-битным разрешением и выбираемыми диапазонами от ±2 g до ±16 g. С ним можно вычислить пиковое ускорение грунта (PGA) при толчке, отличить хлопок двери от долгого движения грунта по тому, сколько секунд длится ускорение и какая у него частота, и записывать данные, чтобы изучить их потом. Использовать оба датчика вместе тоже разумно: SW-420 ждёт, потребляя очень мало энергии, и будит микроконтроллер при первой вибрации, а подробные измерения делает MPU6050.

Модуль акселерометра и гироскопа MPU-6050
MPU-6050: трёхосевой акселерометр и гироскоп с подключением по I2C. Для измерения силы и направления толчка подходит гораздо лучше, чем SW-420.
ПараметрSW-420MPU6050
Что измеряет?Есть вибрация или нетУскорение и угловую скорость по 3 осям
ВыходЦифровые импульсы (DO)I2C, 16-битные цифровые данные
ЧувствительностьПотенциометром, грубоПрограммно, от ±2 g до ±16 g
НаправлениеНетДа (X, Y, Z)
Проект с землетрясениемТолько сигнал «что-то тряхнуло»Анализ пикового ускорения, длительности и частоты
КодНесколько строк, без библиотекНужны библиотека и фильтрация
ЦенаОчень дешёвыйДешёвый

Уведомление в Telegram от ESP32 при обнаружении вибрации

С ESP32 датчик вибрации может сообщить тебе на телефон, если с сейфом, велосипедом или станком что-то происходит, пока тебя нет дома. Для этого нужно создать бота через BotFather в Telegram, получить токен бота и свой chat ID (ID чата), а в Arduino IDE установить библиотеки UniversalTelegramBot и ArduinoJson; эти шаги подробно описаны в руководстве Telegram-бот на ESP32. Код ниже считает импульсы через прерывание, отправляет сообщение, когда видит не меньше 5 импульсов за 1 секунду, и выдерживает паузу между уведомлениями (cooldown) не меньше 60 секунд, чтобы телефон не завалило десятками уведомлений в минуту. У ESP32 два ядра, поэтому счётчик защищён блокировкой portMUX.

C++ (Arduino IDE)
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 в глубокий сон и сделай пин DO модуля SW-420 источником пробуждения через esp_sleep_enable_ext0_wakeup(); тогда ESP32 просыпается только от вибрации, отправляет сообщение и снова засыпает. В этом случае для пробуждения нужно выбрать один из пинов RTC GPIO; GPIO 27 входит в эту группу.

SW-420 с Raspberry Pi Pico (MicroPython)

На Pico питай модуль от пина 3V3(OUT) и подключи DO к GP15. Код ниже повторяет логику событий из версии для Arduino: считает импульсы через прерывание, зажигает встроенный светодиод платы при первом импульсе и после 500 мс тишины выводит длительность события и число импульсов. Имя Pin("LED") выбирает встроенный светодиод и на Pico, и на Pico W.

MicroPython
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-принтер.
  • Электронный сейф: защита, которая поднимает тревогу при попытке взломать сейф и работает вместе с кодовым замком; объедини её с руководством кодовый замок на матричной клавиатуре.
  • Игра и интерактивный стол: барабан или игра на реакцию, которая выдаёт свет и звук, когда ударяешь по столу.

Частые ошибки

СимптомВероятная причинаРешение
Лёгкая вибрация не обнаруживаетсяИмпульсы читаются через digitalRead() в loop() и теряютсяИспользуй прерывание через attachInterrupt()
Датчик срабатывает постоянноСлишком высокая чувствительность или плата болтаетсяНастрой потенциометр на месте и прикрути плату
Тревога включается снова сама собойВибрация зуммера доходит до датчикаУстанови зуммер подальше от датчика, на отдельной поверхности
Логика работает наоборотНа модуле-клоне выход DO инвертированПроверь в мониторе порта и при необходимости используй FALLING
Пин ESP32 повреждён или работает нестабильноМодуль питался от 5 V, и на DO было 5 VПитай модуль от 3,3 V
На телефон приходят десятки сообщенийНет паузы между уведомлениямиЗадай в коде паузу между уведомлениями не меньше 60 секунд
Прежде чем выбирать порог тревоги, запусти код подсчёта импульсов на несколько часов там, где будет работать датчик, и сохрани вывод монитора порта. Так видно, сколько импульсов максимум дают обычные повседневные события (шаги, двери, транспорт); поставить порог заметно выше этого значения — самый надёжный способ свести ложные срабатывания к минимуму. На этом подходе и строится фильтрация; подробности — в руководстве фильтрация данных датчиков.

SW-420 — самый дешёвый и простой способ узнать, что поверхность тряхнуло; настоящая сила датчика раскрывается, когда импульсы ловятся и считаются через прерывание, а результат оценивается вместе с длительностью и плотностью. Настраивай чувствительность на месте, отсеивай ложные срабатывания программно и переходи на MPU6050, когда нужны сила или направление толчка. В приложении BlueGrays есть проекты «Работа с зуммером», «Детектор движения на датчике движения» и «Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)», а также «Умный электронный сейф» — с пошаговыми схемами и кодом.

Частые вопросы

Как работает датчик вибрации?

В датчиках вибрации вроде SW-420 внутри металлического корпуса находятся пружина и токопроводящая деталь. Когда датчик неподвижен, контакт замкнут; когда его трясут, пружина раскачивается, и контакт размыкается и замыкается очень короткими сериями. Компаратор LM393 на модуле превращает это изменение в чистый цифровой сигнал по порогу, заданному потенциометром.

Как настроить чувствительность SW-420?

Потенциометр на модуле меняет порог компаратора. Закрепи датчик на той поверхности, где он будет работать, поверни потенциометр до точки, где сигнальный светодиод в покое горит ровно, но реагирует на лёгкий стук, а затем немного уменьши чувствительность, чтобы оставить запас. Настройка зависит от материала поверхности, поэтому делай её на месте, а не на рабочем столе.

Почему SW-420 пропускает часть вибраций?

Во время вибрации выход SW-420 выдаёт только очень короткие импульсы. Если код читает пин через digitalRead() в loop() и в этот момент занят delay() или Serial.print(), импульс теряется. Решение — использовать прерывание через attachInterrupt() и считать импульсы в функции прерывания.

Можно ли сделать детектор землетрясений на датчике вибрации?

Простую сигнализацию тряски для обучения сделать можно, но SW-420 обнаруживает только наличие вибрации: он не измеряет её силу и направление и не отличает, например, хлопок двери от землетрясения. Датчик в единственном экземпляре замечает тряску только тогда, когда она до него дошла. Для более содержательных измерений используй акселерометр вроде MPU6050 и никогда не считай такие проекты заменой официальных систем раннего оповещения.

Можно ли использовать SW-420 с ESP32?

Да. Питай модуль от пина 3V3 на ESP32 и подключи выход DO к цифровому пину, например GPIO 27. Если питать модуль от 5 V, на выходе DO тоже будет 5 V, и это может повредить пин ESP32. На ESP32 объявляй функцию прерывания с IRAM_ATTR и защищай общий счётчик блокировкой portMUX.

Чем SW-420 отличается от SW-18010P?

Оба — пружинные вибровыключатели, но устройство контакта у них разное. SW-420 нормально замкнутый: в покое контакт замкнут и размыкается от вибрации. Нормально разомкнутые типы вроде SW-18010P в покое разомкнуты и от вибрации ненадолго замыкаются. При работе с готовыми модулями достаточно проверить уровень выхода в мониторе порта.

Все проекты
Работа с зуммером
#13Новичок

Работа с зуммером

Интересно, как дверной звонок или сигнализация издают звук? Arduino заставляет маленький зуммер пищать через короткие промежутки: пик, пауза, пик, пауза. Ты видишь, как электричество превращается в зв

4.7(89)
161
Управление светодиодом кнопкой (удержание)
#9Новичок

Управление светодиодом кнопкой (удержание)

Как дверной звонок: свет горит, пока ты нажимаешь, и гаснет, когда отпускаешь. Arduino всё время слушает кнопку; пока она нажата, светодиод горит, а как только ты убираешь палец, он гаснет. Эта просте

4.8(113)
229
Детектор движения на датчике движения
#24Новичок
Premium

Детектор движения на датчике движения

Простой охранник, который сообщает, что кто-то вошёл в комнату. Датчик движения улавливает тепло человеческого тела, а Arduino держит светодиод включённым, пока есть движение, и гасит его, когда движе

4.6(47)
67
Дверной звонок и свет с датчиком движения
#25Средний
Premium

Дверной звонок и свет с датчиком движения

Когда кто-то подходит к твоей двери, ты узнаёшь об этом ещё до звонка. Как только датчик движения замечает человека, загорается светодиод, а зуммер играет мелодию из трёх нот сверху вниз; когда мелоди

4.7(54)
71
Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)
#145Продвинутый
Premium

Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)

Умная охранная сигнализация, которая при обнаружении движения PIR-датчиком включает зуммер и светодиод и одновременно сразу отправляет владельцу уведомление в Telegram. В ней есть 30-секундная пауза, ограничивающая частоту повторных тревог; этот механизм не проверяет срабатывания PIR и не устраняет ложные тревоги. Подходит для дома, гаража, склада или мастерской. С ESP32-CAM можно добавить уведомления с фото, а с обычной ESP32 DevKit V1 приходят текстовые.

0.0(0)
9
Умный электронный сейф
#92Продвинутый
Premium

Умный электронный сейф

Маленький сейф для ценных вещей, который открывается кодом. Ты вводишь на клавиатуре свой четырёхзначный код; если он верный, сервопривод открывает замок, загорается зелёный свет, а экран показывает с

4.7(42)
63
Лазерная охранная система
#23Продвинутый
Premium

Лазерная охранная система

Совсем как сцены ограблений с лазерами в фильмах: лазерный луч светит на датчик освещённости, и как только кто-то входит и прерывает луч, загорается красный светодиод и начинает звучать зуммер. Сигнал

4.8(60)
77