Tilt switch là công nghệ cảm biến thô nhất trong bộ kit — không có IC, không có điện tử: chỉ là ống kim loại nhỏ chứa bi dẫn điện. Đơn giản nhưng hoạt động cực kỳ đáng tin cậy cho các ứng dụng phát hiện nghiêng/lật.
Nguyên Lý Hoạt Động
1. Cơ Chế Bi Kim Loại Dẫn Điện
SW-520D là ống trụ kim loại nhỏ (~6mm × 12mm) với 2 đầu dây ở một đầu:
SW-520D — Cắt dọc:
Đầu tiếp điểm
┌──┴──┐
Bi 1 ○─────→│ ⊙ ⊙ │← 2 chân
Bi 2 ○ │ │
└─────┘
ống kim loại
Khi ĐẦU TIẾP ĐIỂM XUỐNG DƯỚI:
○ ○ ← bi lăn về phía tiếp điểm
│ │
⊙ ⊙ ← bi tiếp xúc 2 chân → mạch ĐÓNG → điện thông
Khi ĐẦU TIẾP ĐIỂM LÊN TRÊN:
○ ○ ← bi lăn ra xa
⊙ ⊙ ← không tiếp xúc → mạch HỞ → điện không thông
2. Tác Động Của Trọng Lực
Hành vi phụ thuộc hoàn toàn vào trọng lực và định hướng lắp:
Góc nghiêng so với mặt nằm ngang:
45°+ ─────────────────────────── Bi tiếp xúc tiếp điểm (ĐÓNG)
← Vùng "đóng" phụ thuộc
-45° vào định hướng lắp
─────────────────────────── Bi rời tiếp điểm (HỞ)
-45°−
Không có ngưỡng góc chính xác — SW-520D không đo góc mà chỉ phát hiện có lật hay không dựa trên lực trọng trường đủ để bi lăn.
3. So Sánh Với Các Tilt Sensor Khác
| SW-520D (bi lăn) | MPU-6050 (gyro/accel) | Mercury switch | |
|---|---|---|---|
| Độ chính xác góc | Không đo được | 0.1° | Không đo được |
| Đo 3 trục | Không | Có | Không |
| Phức tạp | Rất đơn giản | I2C, library | Đơn giản |
| An toàn | An toàn | An toàn | Thủy ngân độc |
| Rung | Bounce nhiều | Không | Bounce |
| Dùng khi nào | Phát hiện lật đơn giản | Đo góc chính xác | Lỗi thời |
Thông Số Kỹ Thuật
| Thông số | Giá trị |
|---|---|
| Điện áp tối đa | 12V |
| Dòng tối đa | 30mA |
| Điện trở tiếp xúc | <1Ω (khi đóng) |
| Kích thước | ~6mm × 12mm |
| Nhiệt độ hoạt động | -10°C đến 70°C |
| Output loại | Digital (ON/OFF) |
Sơ Đồ Chân (Pinout)
Module KY-020 (trong kit 37 module)
KY-020 — Nhìn từ mặt trước:
┌──────────────────────────────┐
│ [SW-520D] │
│ [Điện trở pull-up 10kΩ] │
│ [LED trạng thái] │
└──────────────────────────────┘
GND VCC S
(-) (3.3-5V) (Signal OUT)
| Chân | Ký hiệu | Mô tả |
|---|---|---|
| GND | – | Mass |
| VCC | + | Nguồn 3.3V-5V |
| S | Signal | Output — LOW khi mạch đóng (bi tiếp xúc) |
Logic output (với pull-up trên module):
- Module thẳng đứng (đầu tiếp điểm xuống): S = LOW (bi đóng mạch)
- Module nghiêng/lật (bi rời xa tiếp điểm): S = HIGH
Tùy hướng lắp module, logic có thể ngược. Kiểm tra thực tế với Serial Monitor trước khi code.
Kết Nối Phần Cứng
KY-020 với ESP32 DevKit V1
ESP32 DevKit V1 KY-020 Module
───────────────────── ─────────────────
3V3 ─────────────────→ VCC
GND ─────────────────→ GND
GPIO4 (Input) ─────────→ S (Signal)
GPIO4: input-capable, không phải strapping pin.
Định hướng lắp: Module thường lắp dọc với 3 chân kết nối ở dưới. Kiểm tra logic trước khi dùng trong ứng dụng.
KY-020 với Arduino Uno
Arduino Uno KY-020 Module
───────────────────── ─────────────────
5V ─────────────────→ VCC
GND ─────────────────→ GND
Pin 2 (Input_PU)──────→ S ← Pin 2: hỗ trợ interrupt
Code Arduino IDE
Code Đọc Trạng Thái Cơ Bản — Arduino Uno
/*
* Tilt Switch SW-520D — Đọc trạng thái nghiêng cơ bản
* Board: Arduino Uno
* Kết nối: VCC→5V, GND→GND, S→Pin2
*
* Module có pull-up → khi bi tiếp xúc: S = LOW
* Kiểm tra thực tế để xác định logic đúng
*/
const int TILT_PIN = 2;
const int LED_PIN = 13;
void setup() {
Serial.begin(9600);
pinMode(TILT_PIN, INPUT); // Module đã có pull-up
pinMode(LED_PIN, OUTPUT);
Serial.println("=== Tilt Switch SW-520D ===");
Serial.println("Xoay module để kiểm tra logic HIGH/LOW");
}
int lastState = -1; // Lưu trạng thái trước để phát hiện thay đổi
void loop() {
int tiltVal = digitalRead(TILT_PIN);
// Chỉ in khi có thay đổi (không spam Serial)
if (tiltVal != lastState) {
lastState = tiltVal;
if (tiltVal == LOW) {
Serial.println("LOW → Bi tiếp xúc (mạch ĐÓNG) — module ở hướng này");
digitalWrite(LED_PIN, HIGH);
} else {
Serial.println("HIGH → Bi không tiếp xúc (mạch HỞ)");
digitalWrite(LED_PIN, LOW);
}
}
delay(20); // Nhỏ debounce
}
Code Phát Hiện Lật — Đếm Flip Count (Arduino Uno)
/*
* Tilt Switch — Đếm số lần lật (flip counter)
* Board: Arduino Uno
* Kết nối: VCC→5V, GND→GND, S→Pin2
*
* Dùng interrupt để đếm chính xác, không bỏ sót
*/
const int TILT_PIN = 2;
const int LED_PIN = 13;
volatile int flipCount = 0; // Tổng số lần thay đổi trạng thái
volatile bool tiltChanged = false; // Cờ báo có thay đổi
// Định nghĩa trạng thái logic (điều chỉnh theo module thực tế)
// LOW = "bình thường", HIGH = "nghiêng" — hoặc ngược lại
#define TILTED_STATE HIGH
void onTiltChange() {
flipCount++;
tiltChanged = true;
}
void setup() {
Serial.begin(9600);
pinMode(TILT_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
// Trigger trên cả 2 chiều (CHANGE): mỗi lần bi lăn = 1 event
attachInterrupt(digitalPinToInterrupt(TILT_PIN), onTiltChange, CHANGE);
Serial.println("=== Flip Counter ===");
Serial.println("Flips: 0");
}
void loop() {
if (tiltChanged) {
tiltChanged = false;
int currentState = digitalRead(TILT_PIN);
bool isTilted = (currentState == TILTED_STATE);
digitalWrite(LED_PIN, isTilted ? HIGH : LOW);
Serial.print("Flip #");
Serial.print(flipCount);
Serial.print(" — ");
Serial.println(isTilted ? "NGHIÊNG" : "THẲNG");
}
}
Code Anti-Theft Alarm — Báo Động Khi Bị Di Chuyển (Arduino Uno)
/*
* Tilt Switch — Báo động anti-theft: báo khi thiết bị bị di chuyển
* Board: Arduino Uno
* Kết nối: VCC→5V, GND→GND, S→Pin2, Buzzer→Pin9
*
* Cách dùng:
* 1. Đặt thiết bị ở vị trí muốn bảo vệ
* 2. Nhấn Reset → 5 giây "cài đặt" (arm)
* 3. Ai di chuyển thiết bị → buzzer kêu
*/
const int TILT_PIN = 2;
const int BUZZER_PIN = 9;
const int LED_PIN = 13;
const int ARM_DELAY = 5000; // 5 giây để đặt thiết bị xuống
volatile bool alarmTriggered = false;
bool armed = false;
int baselineState = LOW; // Trạng thái "bình thường" sau khi arm
void onTiltChange() {
if (armed) {
int currentState = digitalRead(TILT_PIN);
if (currentState != baselineState) {
alarmTriggered = true;
}
}
}
void setup() {
Serial.begin(9600);
pinMode(TILT_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
attachInterrupt(digitalPinToInterrupt(TILT_PIN), onTiltChange, CHANGE);
Serial.println("=== Anti-Theft Alarm ===");
Serial.println("Đặt thiết bị xuống, chờ 5 giây...");
// Blink LED trong lúc đếm ngược
for (int i = 5; i > 0; i--) {
Serial.print(i); Serial.print("...");
digitalWrite(LED_PIN, HIGH); delay(500);
digitalWrite(LED_PIN, LOW); delay(500);
}
// Ghi lại trạng thái baseline
baselineState = digitalRead(TILT_PIN);
armed = true;
digitalWrite(LED_PIN, HIGH); // LED luôn sáng = đang armed
Serial.println("\nBÁO ĐỘNG ĐÃ BẬT! (armed)");
Serial.println("Di chuyển thiết bị sẽ kích hoạt báo động");
}
void loop() {
if (alarmTriggered) {
Serial.println("!!! BÁO ĐỘNG - Thiết bị bị di chuyển !!!");
// Kêu còi liên tục 10 giây
unsigned long alarmStart = millis();
while (millis() - alarmStart < 10000) {
digitalWrite(BUZZER_PIN, HIGH); delay(200);
digitalWrite(BUZZER_PIN, LOW); delay(200);
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Blink nhanh
}
// Reset alarm (để arm lại cần nhấn Reset)
alarmTriggered = false;
armed = false;
Serial.println("Alarm reset. Nhấn Reset để arm lại.");
}
}
Code ESP32 — Tilt Detection Non-Blocking
/*
* Tilt Switch KY-020 — ESP32, phát hiện nghiêng non-blocking
* Board: ESP32 DevKit V1
* Kết nối: VCC→3V3, GND→GND, S→GPIO4
*/
const int TILT_PIN = 4;
const int LED_PIN = 5;
volatile bool tiltState = false;
volatile bool stateChanged = false;
unsigned long lastChangeTime = 0;
const unsigned long DEBOUNCE_MS = 50; // Debounce bi lăn
void IRAM_ATTR onTiltISR() {
// Debounce trong ISR (đơn giản — không dùng millis() trong ISR)
stateChanged = true;
tiltState = (digitalRead(TILT_PIN) == LOW); // LOW = bi tiếp xúc
}
void setup() {
Serial.begin(115200);
pinMode(TILT_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
attachInterrupt(digitalPinToInterrupt(TILT_PIN), onTiltISR, CHANGE);
Serial.println("=== Tilt Switch ESP32 ===");
}
void loop() {
if (stateChanged) {
unsigned long now = millis();
if (now - lastChangeTime > DEBOUNCE_MS) {
lastChangeTime = now;
stateChanged = false;
if (tiltState) {
Serial.println("Module nằm — bi tiếp xúc (LOW)");
digitalWrite(LED_PIN, HIGH);
} else {
Serial.println("Module đứng hoặc nghiêng — bi không tiếp xúc (HIGH)");
digitalWrite(LED_PIN, LOW);
}
}
}
}
Kết Quả Mong Đợi
=== Tilt Switch SW-520D ===
Xoay module để kiểm tra logic HIGH/LOW
LOW → Bi tiếp xúc (mạch ĐÓNG) — module ở hướng này
HIGH → Bi không tiếp xúc (mạch HỞ)
LOW → Bi tiếp xúc (mạch ĐÓNG) — module ở hướng này
Ứng Dụng Thực Tế
| Ứng dụng | Chi tiết |
|---|---|
| Báo động anti-theft | Kêu còi khi thiết bị bị di chuyển |
| Phát hiện ngã (fall detection) | Robot ngã → đứng lại |
| Đèn tự động khi mở nắp | Mở nắp hộp → đèn sáng |
| Đếm số lần lật container | Logistics: đếm số lần xử lý |
| Công tắc vị trí cơ học | Arm/disarm theo vị trí đặt |
Lưu Ý Khi Sử Dụng
1. Bounce (rung tiếp điểm) rất nhiều
Bi kim loại rung khi lăn → tạo ra hàng chục tín hiệu giả. Debounce ~50ms là minimum. Dùng CHANGE interrupt + bộ lọc thời gian, không dùng delay() trong ISR.
2. Kiểm tra logic thực tế
Logic HIGH/LOW phụ thuộc vào hướng lắp module. Luôn kiểm tra với Serial Monitor trước khi code ứng dụng. Không giả định trước.
3. Không đo được góc
SW-520D chỉ cho biết “lật hay không” — không biết góc nghiêng. Cần đo góc → dùng MPU-6050 (Bài 30) hoặc ADXL345.
4. Rung cơ học gây false trigger
Đặt thiết bị trên bề mặt rung (xe, máy móc) → tilt switch kích hoạt liên tục. Giải pháp: tăng debounce, hoặc cần nhiều lần trigger liên tiếp mới tính là sự kiện thật.


