Files
2026-08-30 21:54:15 +07:00

15 KiB
Raw Permalink Blame History

WiFiSense — ESP32-S3 + OLED Edition

Phát hiện chuyển động thụ động qua biến động tín hiệu RSSI WiFi, hiển thị trực tiếp trên màn hình OLED 0.96", tự động cấu hình WiFi qua Captive Portal.

Platform IDE License


Mục lục


Nguyên lý hoạt động

WiFiSense không dùng camera, microphone hay cảm biến vật lý nào. Thay vào đó, nó khai thác một hiện tượng vật lý: khi có người/vật di chuyển trong phòng, sóng WiFi bị phản xạ và nhiễu loạn, khiến chỉ số RSSI (cường độ tín hiệu) dao động theo những mẫu đặc trưng.

Pipeline xử lý tín hiệu

WiFi RSSI thô
    │
    ▼
┌─────────────────┐
│  Kalman Filter  │  ← Loại bỏ nhiễu ngẫu nhiên ngắn hạn
└────────┬────────┘
         │
    ▼
┌──────────────────────┐
│ Exponential Smoothing │  ← Làm mượt tín hiệu (α = 0.15)
└──────────┬───────────┘
           │
    ▼
┌──────────────────────────────────────────────────┐
│  Cửa sổ trượt (40 mẫu ngắn + 100 mẫu dài)       │
│  • Độ lệch chuẩn (Variance)   → biên độ dao động │
│  • Rate of Change             → tốc độ thay đổi  │
│  • Peak Detection             → đỉnh đột biến    │
│  • Z-Score                    → bất thường thống │
└──────────────────────┬───────────────────────────┘
                       │
    ▼
┌────────────────────────────────┐
│  Tính Confidence Score (0100) │
└──────────────┬─────────────────┘
               │
    ▼
┌──────────────────────────────────────────────────┐
│  Persistence Counter (≥ 3 mẫu liên tiếp)         │
│  → Kết luận: MOTION / CLEAR                      │
│  → Bật LED + hiển thị OLED                       │
└──────────────────────────────────────────────────┘

Adaptive Baseline

Baseline (đường cơ sở khi không có chuyển động) tự thích nghi theo thời gian thực với tốc độ rất chậm (α = 0.008), giúp hệ thống tự điều chỉnh khi môi trường thay đổi dần (người rời phòng, thay đổi vị trí router…).


Sơ đồ luồng hệ thống

                    ┌──────────────┐
                    │   Khởi động  │
                    └──────┬───────┘
                           │
                    ┌──────▼───────┐
                    │  Đọc NVS     │  credentials đã lưu?
                    └──────┬───────┘
                   Có ▼         ▼ Không
          ┌──────────────┐  ┌──────────────────────┐
          │ Kết nối WiFi │  │  Mở AP WiFiSense-Setup│
          └──────┬───────┘  │  DNS + Captive Portal │
         OK ▼   ▼ Fail      │  Người dùng chọn mạng │
    ┌────────┐ ┌──────────┐ │  → Lưu NVS → Restart  │
    │Calibrate│ │Thử lại x3│ └──────────────────────┘
    └────┬───┘ └────┬─────┘
         │      Fail│
         │     ┌────▼──────────────┐
         │     │ Xóa NVS + Restart │
         │     └───────────────────┘
    ┌────▼──────────────────┐
    │   Loop chính           │
    │  • Lấy RSSI mỗi 500ms │
    │  • Kalman + Smooth     │
    │  • Tính Variance/Z     │
    │  • Cập nhật OLED       │
    │  • Bật/tắt LED         │
    └───────────────────────┘

Phần cứng

Linh kiện cần thiết

Linh kiện Thông số Ghi chú
Vi điều khiển ESP32-S3 (bất kỳ board) Đã test trên ESP32-S3-DevKitC-1
Màn hình OLED 0.96" SSD1306 128×64 I2C Địa chỉ I2C: 0x3C
LED 3mm hoặc 5mm, bất kỳ màu Kèm điện trở 220Ω–330Ω
Dây jumper Male-to-Male hoặc Male-to-Female

Sơ đồ đấu dây

ESP32-S3          SSD1306 OLED
─────────         ────────────
GPIO 6  ─────────  SDA
GPIO 7  ─────────  SCL
3.3V    ─────────  VCC
GND     ─────────  GND

ESP32-S3          LED
─────────         ────────────
GPIO 2  ──[330Ω]──  Anode (+)
GND     ─────────  Cathode (-)

Lưu ý: Một số board ESP32-S3 (ví dụ Waveshare) có thể có sẵn LED trên GPIO 2 — kiểm tra datasheet của board bạn đang dùng.


Cài đặt môi trường

1. Arduino IDE

Tải về tại arduino.cc/en/software (phiên bản 2.x khuyến nghị).

2. Thêm ESP32 vào Board Manager

Vào File → Preferences → Additional boards manager URLs, thêm:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Sau đó vào Tools → Board → Boards Manager, tìm esp32 của Espressif và cài đặt.

3. Cài thư viện

Vào Tools → Manage Libraries và cài đặt 2 thư viện sau:

Thư viện Tác giả Ghi chú
Adafruit SSD1306 Adafruit Tìm đúng tên này
Adafruit GFX Library Adafruit Dependency của SSD1306

Các thư viện còn lại (WiFi, WebServer, DNSServer, Preferences) đã có sẵn trong ESP32 Arduino core, không cần cài thêm.

4. Chọn board

Tools → Board → ESP32 Arduino → ESP32S3 Dev Module

Các thông số quan trọng:

Tùy chọn Giá trị
USB Mode Hardware CDC and JTAG
Flash Size 4MB (hoặc theo board của bạn)
Partition Scheme Default 4MB with spiffs
PSRAM Disabled (nếu board không có)

Nạp code

  1. Kết nối ESP32-S3 với máy tính qua USB.
  2. Mở file WiFiSense.ino trong Arduino IDE.
  3. Chọn đúng Port tại Tools → Port.
  4. Nhấn nút Upload (→) hoặc Ctrl+U.
  5. Chờ quá trình biên dịch và nạp hoàn tất (~3060 giây).

Nếu board không tự vào chế độ nạp: giữ nút BOOT, nhấn RESET, thả RESET, rồi thả BOOT.


Cách sử dụng

Lần đầu tiên (chưa có WiFi lưu)

Khi khởi động và chưa có credentials trong NVS, ESP32 sẽ tự động mở Captive Portal:

OLED hiển thị:
┌──────────────────────────────┐
│    ** SETUP MODE **          │
│──────────────────────────────│
│ 1. Ket noi WiFi:             │
│    WiFiSense-Setup           │
│ 2. Mo trinh duyet:           │
│    192.168.4.1               │
└──────────────────────────────┘

Các bước cấu hình:

  1. Dùng điện thoại hoặc máy tính, kết nối vào WiFi WiFiSense-Setup (không mật khẩu).
  2. Trình duyệt sẽ tự động mở trang cấu hình (Captive Portal). Nếu không tự mở, truy cập thủ công vào http://192.168.4.1.
  3. Chọn mạng WiFi nhà bạn từ danh sách quét được.
  4. Nhập mật khẩu WiFi → nhấn Kết nối & Lưu.
  5. ESP32 lưu thông tin vào bộ nhớ NVS và tự khởi động lại.
  6. Lần này ESP32 kết nối thẳng vào WiFi đã chọn và bắt đầu calibrate.

Các lần sau (đã có WiFi lưu)

ESP32 tự kết nối WiFi khi khởi động, không cần cấu hình lại.

Đổi WiFi

Nếu muốn kết nối sang mạng khác: xóa credentials bằng cách mất điện trong khi đang ở chế độ portal, hoặc thêm một nút bấm vật lý để gọi clearCredentials() + ESP.restart().

Calibration

Sau khi kết nối WiFi thành công, ESP32 sẽ calibrate trong ~6 giây (200 mẫu × 30ms). Trong thời gian này:

  • Giữ phòng trống (không có người di chuyển).
  • OLED hiển thị tiến trình calibration.
  • Baseline được thiết lập dựa trên RSSI trung bình.

Màn hình OLED

Sau calibration, OLED hiển thị 1 trang duy nhất cập nhật mỗi 500ms:

┌──────────────────────────────┐  ← 128px
│ WiFiSense       [ MOTION ]   │  dòng 1: tiêu đề + badge trạng thái
│──────────────────────────────│  đường kẻ
│ RSSI: -67dBm      C:  82%    │  dòng 2: RSSI thô + Confidence số
│ Conf [████████████░░░░░░]    │  dòng 3: thanh Confidence
│ Qual [█████████░░░░░░░░░]    │  dòng 4: thanh Signal Quality
│──────────────────────────────│  đường kẻ
│ Base:-66.1 Var:2.3           │  dòng 5: Baseline + Variance
│ #15                  WALKING │  dòng 6: tổng detections + cường độ
└──────────────────────────────┘

Ý nghĩa các chỉ số

Chỉ số Mô tả
RSSI Cường độ tín hiệu WiFi thô (dBm). Giá trị điển hình: -40 (gần) đến -90 (xa).
C (Confidence) Độ tin cậy phát hiện chuyển động, 0100%. Trên ~50% là có người.
Conf bar Thanh trực quan hóa Confidence.
Qual bar Chất lượng tín hiệu tổng thể (dựa trên độ ổn định dài hạn).
Base Baseline RSSI hiện tại (tự thích nghi).
Var Variance của cửa sổ 40 mẫu gần nhất — số càng cao = dao động càng mạnh.
#N Tổng số lần phát hiện chuyển động kể từ khi khởi động.
Badge MOTION (đảo màu trắng) khi phát hiện, CLEAR khi yên tĩnh.
Cường độ CALM / SLOW / WALKING / FAST / SPRINT — ước lượng mức độ di chuyển.

Troubleshooting

OLED không hiển thị gì

Nguyên nhân Giải pháp
Sai địa chỉ I2C Chạy sketch I2C Scanner để tìm địa chỉ thực. Nếu khác 0x3C, sửa #define OLED_ADDRESS thành 0x3D.
Sai chân SDA/SCL Kiểm tra lại: SDA → GPIO 6, SCL → GPIO 7.
Nguồn không đủ Đảm bảo OLED lấy nguồn 3.3V (không phải 5V đối với các module 3.3V).
Thư viện chưa cài Kiểm tra lại Library Manager: Adafruit SSD1306Adafruit GFX Library.

Không thấy WiFi "WiFiSense-Setup"

Nguyên nhân Giải pháp
ESP32 đang kết nối WiFi cũ Chờ 30 giây timeout, ESP32 sẽ tự chuyển sang AP mode.
Credentials cũ còn trong NVS Upload lại firmware có clearCredentials() trong setup() (tạm thời), sau đó upload lại bản gốc.

Trang cấu hình không tự mở trên điện thoại

Một số thiết bị Android/iOS không tự kích hoạt captive portal với DNS redirect. Mở trình duyệt và truy cập thủ công: http://192.168.4.1

Phát hiện chuyển động không chính xác

Vấn đề Giải pháp
Phát hiện khi không có người Giảm FAST_MOVEMENT_THRESHOLDSLOW_MOVEMENT_THRESHOLD, hoặc tăng PERSISTENCE_REQUIRED.
Không phát hiện khi có người Đặt ESP32 gần router hơn; tăng CALIBRATION_SAMPLES; kiểm tra không có thiết bị khác gây nhiễu.
Baseline trôi quá nhanh Giảm ADAPTIVE_ALPHA (ví dụ từ 0.008 xuống 0.003).

Mất kết nối WiFi liên tục

  • Kiểm tra khoảng cách tới router. RSSI nên ở mức > -75 dBm để ổn định.
  • Sau 3 lần mất kết nối liên tiếp (MAX_RECONNECT_ATTEMPTS = 3), ESP32 tự xóa NVS và mở lại Captive Portal — đây là hành vi thiết kế để người dùng có thể đổi mạng.
  • Tăng MAX_RECONNECT_ATTEMPTS nếu mạng nhà bạn hay bị ngắt tạm thời.

Upload thất bại (Port not found / No device)

  1. Kiểm tra cáp USB (phải là cáp data, không phải cáp sạc).
  2. Giữ nút BOOT trên board, nhấn RESET, thả RESET, thả BOOT, rồi Upload ngay.
  3. Thử port COM khác trong Arduino IDE.

Cấu trúc project

WiFiSense/
└── WiFiSense.ino    ← Toàn bộ code trong 1 file

Source-Available License

Dự án được cung cấp nguyên trạng cho mục đích học tập và sử dụng cá nhân.

Copyright (c) 2026 Trần Thanh Tân / TTAI Solutions Software. All rights reserved.

Được phép xem, tải xuống, cài đặt và sử dụng phần mềm này cho mục đích cá nhân, giáo dục và sử dụng nội bộ trong tổ chức.

Được phép sửa đổi cho mục đích cá nhân hoặc sử dụng nội bộ.

Nếu chưa có sự cho phép trước bằng văn bản của chủ sở hữu bản quyền, bạn không được:

  1. Bán, bán lại, cấp phép lại hoặc phân phối thương mại phần mềm này hay bất kỳ phần đáng kể nào trong mã nguồn của nó.
  2. Cung cấp phần mềm này, dù đã sửa đổi hay chưa, dưới dạng sản phẩm thương mại, dịch vụ lưu trữ hoặc dịch vụ SaaS trả phí.
  3. Đóng gói phần mềm này cùng phần cứng hoặc sản phẩm khác để bán lại.
  4. Xóa hoặc thay đổi thông báo bản quyền, hoặc nhận mình là tác giả của phần mềm gốc.

Mọi yêu cầu cấp phép thương mại vui lòng gửi tới: https://ttaisolutions.com