IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series ESP32 & Cảm biến: Bài 5 – Đọc cảm biến nghiêng (Tilt Switch): phát hiện nghiêng/đổ & theo dõi realtime

Ở bài này, chúng ta dùng Tilt Switch (cảm biến nghiêng/đổ) để phát hiện thiết bị bị nghiêng hoặc lật. Đây là cảm biến rất đơn giản, giá rẻ, phù hợp cho các ứng dụng:

  • Phát hiện đổ/nghiêng thiết bị
  • Cảnh báo xê dịch, rung lắc mạnh
  • Kết hợp với PIR/Reed/SW-420 để tăng độ tin cậy

Bài viết gồm 2 ví dụ code:

  1. Đọc trạng thái nghiêng local (Serial)
  2. Gửi trạng thái nghiêng lên IoTLabs Cloud MQTT để theo dõi realtime

1) Tilt Switch là gì?

  • Tilt Switch là công tắc cơ học đóng/mở khi bị nghiêng
  • Bên trong thường là bi kim loại hoặc viên bi dẫn điện
  • Không đo góc chính xác → chỉ báo trạng thái

Nguyên lý

  • Thẳng/đặt đúng → mạch mở (hoặc đóng tuỳ loại)
  • Nghiêng/đổ → mạch đóng (hoặc mở)

📌 Lưu ý: có nhiều loại Tilt Switch logic ngược nhau → cần test thực tế.

2) Chuẩn bị

Phần cứng

  • ESP32-C3 SuperMini (Tenstar Robot)
  • Tilt Switch (KY-020, SW-200D, hoặc tương tự)
  • Dây nối

Chân sử dụng

  • TILT_PIN → GPIO0
  • GND → GND

✅ Không cần cấp 5V/3.3V cho Tilt Switch (chỉ là công tắc)

3) Nối dây Tilt Switch với ESP32

Cách ổn định nhất là dùng pull-up nội bộ.

Tilt Switch        ESP32-C3 SuperMini
-----------------------------------
1 chân ------------ GPIO0
1 chân ------------ GND

Trong code:

pinMode(GPIO0, INPUT_PULLUP);

Logic đọc (phổ biến)

Trạng tháiGPIO đọc
Bình thườngHIGH
Nghiêng/đổLOW

(Nếu bạn thấy ngược → chỉ cần đảo logic trong code)

4) Đặc điểm tín hiệu cần lưu ý

  • Tilt Switch có thể bật/tắt liên tục khi rung nhẹ
  • Cần:
    • Phát hiện thay đổi trạng thái
    • debounce/cooldown đơn giản

Ví dụ 1 — Code local đơn giản (phát hiện nghiêng)

Mục tiêu: in trạng thái Bình thường / Nghiêng ra Serial.

// ===== Tilt Switch Local Read =====
const int TILT_PIN = 0;

int lastState = HIGH;

void setup() {
  Serial.begin(115200);
  delay(200);

  pinMode(TILT_PIN, INPUT_PULLUP);
  Serial.println("Tilt switch monitor started...");
}

void loop() {
  int state = digitalRead(TILT_PIN);

  if (state != lastState) {
    if (state == LOW) {
      Serial.println("⚠️ Thiết bị BỊ NGHIÊNG / ĐỔ!");
    } else {
      Serial.println("🟢 Thiết bị trở lại BÌNH THƯỜNG");
    }
    lastState = state;
  }

  delay(50);
}

5) Chuẩn dữ liệu realtime cho IoTLabs Cloud

Topic

iotlabs/<orgId>/devices/<deviceId>/telemetry

Payload JSON

{
  "ts": 1760000000,
  "metrics": {
    "tilt": 1
  },
  "status": {
    "tilt": "tilted"
  }
}
tiltÝ nghĩa
0bình thường
1nghiêng / đổ

Ví dụ 2 — Gửi trạng thái nghiêng lên IoTLabs Cloud MQTT

Chiến lược:

  • Chỉ gửi khi trạng thái thay đổi
  • cooldown để tránh spam
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

// ===== CONFIG =====
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_PASS";

const char* MQTT_HOST = "mqtt.iotlabs.vn";
const int   MQTT_PORT = 8883;
const char* MQTT_USER = "YOUR_MQTT_USER";
const char* MQTT_PASS = "YOUR_MQTT_PASS";
const char* MQTT_TOPIC =
  "iotlabs/<orgId>/devices/<deviceId>/telemetry";

// ===== TILT =====
const int TILT_PIN = 0;
int lastState = HIGH;

unsigned long lastEventMs = 0;
const unsigned long COOLDOWN_MS = 1000;

WiFiClientSecure net;
PubSubClient mqtt(net);

void connectWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(400);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
}

void connectMQTT() {
  net.setInsecure(); // demo nhanh
  mqtt.setServer(MQTT_HOST, MQTT_PORT);

  while (!mqtt.connected()) {
    if (mqtt.connect("esp32c3-tilt", MQTT_USER, MQTT_PASS)) {
      Serial.println("MQTT connected");
      break;
    }
    delay(1000);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(TILT_PIN, INPUT_PULLUP);

  connectWiFi();
  connectMQTT();
}

void loop() {
  if (!mqtt.connected()) connectMQTT();
  mqtt.loop();

  int state = digitalRead(TILT_PIN);
  unsigned long now = millis();

  if (state != lastState && now - lastEventMs > COOLDOWN_MS) {
    lastEventMs = now;
    lastState = state;

    long ts = millis() / 1000;

    String payload = "{";
    payload += "\"ts\":" + String(ts) + ",";
    payload += "\"metrics\":{\"tilt\":" + String(state == LOW ? 1 : 0) + "},";
    payload += "\"status\":{\"tilt\":\"";
    payload += (state == LOW ? "tilted" : "normal");
    payload += "\"}}";

    mqtt.publish(MQTT_TOPIC, payload.c_str());
    Serial.println(payload);
  }

  delay(50);
}

6) Lỗi thường gặp & kinh nghiệm

  • Rung nhẹ cũng trigger
    • Tăng cooldown (1–2s)
    • Gắn tilt chắc chắn hơn
  • Logic bị ngược
    • Đảo điều kiện LOW/HIGH
  • GPIO0 là chân boot
    • Không kéo LOW lúc boot → đảm bảo tilt không ở trạng thái nghiêng khi khởi động

7) Ứng dụng thực tế

  • Cảnh báo thiết bị bị đổ/nghiêng
  • Kết hợp SW-420 để xác nhận va chạm + nghiêng
  • Kết hợp PIR/Reed để tăng độ tin cậy
  • Thiết bị pin + deep sleep (bài nâng cao)

Bài tiếp theo (Level 1)

👉 Bài 6: Hướng dẫn đọc cảm biến Hall A3144 bằng ESP32: phát hiện từ trường/nam châm & theo dõi realtime.