Files
WifiSense-ESP32/README.md
T
2026-08-30 21:33:31 +07:00

340 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](https://img.shields.io/badge/Platform-ESP32--S3-blue)
![IDE](https://img.shields.io/badge/IDE-Arduino-teal)
![License](https://img.shields.io/badge/Source-Avaiable-orange)
---
## Mục lục
- [Nguyên lý hoạt động](#nguyên-lý-hoạt-động)
- [Sơ đồ luồng hệ thống](#sơ-đồ-luồng-hệ-thống)
- [Phần cứng](#phần-cứng)
- [Cài đặt môi trường](#cài-đặt-môi-trường)
- [Nạp code](#nạp-code)
- [Cách sử dụng](#cách-sử-dụng)
- [Màn hình OLED](#màn-hình-oled)
- [Troubleshooting](#troubleshooting)
---
## 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](https://www.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 SSD1306``Adafruit 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
Mt 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_THRESHOLD``SLOW_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](https://ttaisolutions.com/).
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