add oled 12864
This commit is contained in:
1 parent
d163397de4
commit
4c68deb6bb
6 files changed
+326
-1
No files matched your search
+201
@@ -0,0 +1,201 @@
|
|||||||
|
// =====================================================================
|
||||||
|
// OLEDDisplay.cpp
|
||||||
|
// =====================================================================
|
||||||
|
#include "OLEDDisplay.h"
|
||||||
|
|
||||||
|
OLEDDisplay::OLEDDisplay(uint8_t sdaPin, uint8_t sclPin, uint8_t i2cAddr)
|
||||||
|
: _display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET),
|
||||||
|
_sdaPin(sdaPin),
|
||||||
|
_sclPin(sclPin),
|
||||||
|
_i2cAddr(i2cAddr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OLEDDisplay::begin() {
|
||||||
|
Wire.begin(_sdaPin, _sclPin);
|
||||||
|
|
||||||
|
if (!_display.begin(SSD1306_SWITCHCAPVCC, _i2cAddr)) {
|
||||||
|
Serial.println(F("[OLED] Không thể khởi tạo màn hình!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextColor(SSD1306_WHITE);
|
||||||
|
_display.display();
|
||||||
|
|
||||||
|
Serial.println(F("[OLED] Đã khởi tạo thành công"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::clear() {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::centerText(const char* text, int16_t y) {
|
||||||
|
int16_t x1, y1;
|
||||||
|
uint16_t w, h;
|
||||||
|
_display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
|
||||||
|
_display.setCursor((SCREEN_WIDTH - w) / 2, y);
|
||||||
|
_display.print(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::showBootScreen(const char* nodeId) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
centerText("ESP32-S3", 10);
|
||||||
|
centerText("LD2453 RADAR", 25);
|
||||||
|
|
||||||
|
_display.setCursor(0, 45);
|
||||||
|
_display.print("Node: ");
|
||||||
|
_display.println(nodeId);
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::showWiFiConnecting(const char* ssid) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
centerText("Ket noi WiFi...", 15);
|
||||||
|
|
||||||
|
_display.setCursor(0, 35);
|
||||||
|
_display.print("SSID: ");
|
||||||
|
|
||||||
|
// Cắt SSID nếu quá dài
|
||||||
|
char shortSSID[17];
|
||||||
|
strncpy(shortSSID, ssid, 16);
|
||||||
|
shortSSID[16] = '\0';
|
||||||
|
_display.println(shortSSID);
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::showWiFiConnected(IPAddress ip) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
centerText("WiFi OK!", 15);
|
||||||
|
|
||||||
|
_display.setCursor(0, 35);
|
||||||
|
_display.print("IP: ");
|
||||||
|
_display.println(ip);
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
delay(2000); // Hiển thị 2 giây
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::showDiagnosticMode() {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
centerText("DIAGNOSTIC MODE", 10);
|
||||||
|
centerText("Serial Only", 25);
|
||||||
|
centerText("No WiFi", 40);
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::updateRadarInfo(const RadarFrame &frame, const LD2453Stats &stats) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
// Dòng 1: Tiêu đề
|
||||||
|
_display.setCursor(0, 0);
|
||||||
|
_display.print("LD2453 ");
|
||||||
|
if (stats.bytesReceived > 0) {
|
||||||
|
_display.print("RX:");
|
||||||
|
_display.print(stats.bytesReceived);
|
||||||
|
} else {
|
||||||
|
_display.print("NO DATA");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dòng 2: Frames parsed
|
||||||
|
_display.setCursor(0, 12);
|
||||||
|
_display.print("Frames: ");
|
||||||
|
_display.print(stats.framesParsed);
|
||||||
|
|
||||||
|
// Dòng 3: Errors
|
||||||
|
_display.setCursor(0, 24);
|
||||||
|
_display.print("Errors: ");
|
||||||
|
_display.print(stats.parseErrors);
|
||||||
|
|
||||||
|
// Dòng 4: PPS
|
||||||
|
_display.setCursor(0, 36);
|
||||||
|
_display.print("PPS: ");
|
||||||
|
_display.print(stats.packetsPerSecond, 1);
|
||||||
|
|
||||||
|
// Dòng 5: Target count
|
||||||
|
_display.setCursor(0, 48);
|
||||||
|
_display.print("Targets: ");
|
||||||
|
_display.print(frame.targetCount);
|
||||||
|
|
||||||
|
// Hiển thị các target nếu có
|
||||||
|
for (uint8_t i = 0; i < frame.targetCount && i < 3; i++) {
|
||||||
|
if (frame.targets[i].valid) {
|
||||||
|
_display.print(" T");
|
||||||
|
_display.print(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::updateDetectionSummary(uint8_t targetCount, bool zone1, bool zone2, bool zone3) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
// Tiêu đề
|
||||||
|
_display.setCursor(0, 0);
|
||||||
|
_display.print("DETECTION STATUS");
|
||||||
|
|
||||||
|
// Số target phát hiện
|
||||||
|
_display.setCursor(0, 15);
|
||||||
|
_display.setTextSize(2);
|
||||||
|
_display.print("T:");
|
||||||
|
_display.print(targetCount);
|
||||||
|
|
||||||
|
// Zones
|
||||||
|
_display.setTextSize(1);
|
||||||
|
_display.setCursor(0, 35);
|
||||||
|
_display.print("Zone1: ");
|
||||||
|
_display.println(zone1 ? "YES" : "NO");
|
||||||
|
|
||||||
|
_display.setCursor(0, 45);
|
||||||
|
_display.print("Zone2: ");
|
||||||
|
_display.println(zone2 ? "YES" : "NO");
|
||||||
|
|
||||||
|
_display.setCursor(0, 55);
|
||||||
|
_display.print("Zone3: ");
|
||||||
|
_display.println(zone3 ? "YES" : "NO");
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OLEDDisplay::updateStats(const LD2453Stats &stats) {
|
||||||
|
_display.clearDisplay();
|
||||||
|
_display.setTextSize(1);
|
||||||
|
|
||||||
|
// Tiêu đề
|
||||||
|
centerText("LD2453 RADAR", 0);
|
||||||
|
|
||||||
|
// Thống kê
|
||||||
|
_display.setCursor(0, 15);
|
||||||
|
_display.print("Bytes RX: ");
|
||||||
|
_display.println(stats.bytesReceived);
|
||||||
|
|
||||||
|
_display.setCursor(0, 27);
|
||||||
|
_display.print("Frames: ");
|
||||||
|
_display.println(stats.framesParsed);
|
||||||
|
|
||||||
|
_display.setCursor(0, 39);
|
||||||
|
_display.print("Errors: ");
|
||||||
|
_display.println(stats.parseErrors);
|
||||||
|
|
||||||
|
_display.setCursor(0, 51);
|
||||||
|
_display.print("PPS: ");
|
||||||
|
_display.print(stats.packetsPerSecond, 1);
|
||||||
|
|
||||||
|
_display.display();
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// =====================================================================
|
||||||
|
// OLEDDisplay.h
|
||||||
|
// Quản lý hiển thị màn hình OLED I2C 128x64
|
||||||
|
// =====================================================================
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
#include "LD2453Parser.h"
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 128
|
||||||
|
#define SCREEN_HEIGHT 64
|
||||||
|
#define OLED_RESET -1 // Reset pin (hoặc -1 nếu dùng chung với ESP32 reset)
|
||||||
|
|
||||||
|
class OLEDDisplay {
|
||||||
|
public:
|
||||||
|
OLEDDisplay(uint8_t sdaPin, uint8_t sclPin, uint8_t i2cAddr);
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Hiển thị trạng thái khởi động
|
||||||
|
void showBootScreen(const char* nodeId);
|
||||||
|
|
||||||
|
// Hiển thị trạng thái kết nối WiFi
|
||||||
|
void showWiFiConnecting(const char* ssid);
|
||||||
|
void showWiFiConnected(IPAddress ip);
|
||||||
|
|
||||||
|
// Hiển thị chế độ Diagnostic
|
||||||
|
void showDiagnosticMode();
|
||||||
|
|
||||||
|
// Hiển thị thông tin radar (DIAGNOSTIC_MODE)
|
||||||
|
void updateRadarInfo(const RadarFrame &frame, const LD2453Stats &stats);
|
||||||
|
|
||||||
|
// Hiển thị tóm tắt detection (full mode)
|
||||||
|
void updateDetectionSummary(uint8_t targetCount, bool zone1, bool zone2, bool zone3);
|
||||||
|
|
||||||
|
// Hiển thị thống kê khi không có frame
|
||||||
|
void updateStats(const LD2453Stats &stats);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Adafruit_SSD1306 _display;
|
||||||
|
uint8_t _sdaPin;
|
||||||
|
uint8_t _sclPin;
|
||||||
|
uint8_t _i2cAddr;
|
||||||
|
|
||||||
|
void centerText(const char* text, int16_t y);
|
||||||
|
};
|
||||||
@@ -44,14 +44,24 @@ capture) is fully implemented and ready to go.
|
|||||||
|
|
||||||
## Wiring
|
## Wiring
|
||||||
|
|
||||||
|
### LD2453 Radar
|
||||||
```
|
```
|
||||||
LD2453 ESP32-S3
|
LD2453 ESP32-S3
|
||||||
V -> 3V3
|
V -> 3V3
|
||||||
G -> GND
|
G -> GND
|
||||||
T/TX -> RADAR_RX_PIN (default GPIO18)
|
T/TX -> RADAR_RX_PIN (default GPIO18)
|
||||||
R/RX -> RADAR_TX_PIN (default GPIO17)
|
R/RX -> RADAR_TX_PIN (default GPIO17)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### OLED Display I2C 128x64
|
||||||
|
```
|
||||||
|
OLED ESP32-S3
|
||||||
|
VCC -> 3V3
|
||||||
|
GND -> GND
|
||||||
|
SCL -> GPIO7 (OLED_SCL_PIN)
|
||||||
|
SDA -> GPIO6 (OLED_SDA_PIN)
|
||||||
|
```
|
||||||
|
|
||||||
Change `RADAR_RX_PIN` / `RADAR_TX_PIN` in `config.h` to match your
|
Change `RADAR_RX_PIN` / `RADAR_TX_PIN` in `config.h` to match your
|
||||||
wiring — any two free GPIOs that support UART on your ESP32-S3 board
|
wiring — any two free GPIOs that support UART on your ESP32-S3 board
|
||||||
will work, since the ESP32 Arduino core remaps UART pins in software.
|
will work, since the ESP32 Arduino core remaps UART pins in software.
|
||||||
@@ -83,10 +93,42 @@ ESP32_LD2453/
|
|||||||
LD2453Parser.h/.cpp - UART acquisition + frame parsing (STUBBED, see above)
|
LD2453Parser.h/.cpp - UART acquisition + frame parsing (STUBBED, see above)
|
||||||
ZoneManager.h/.cpp - rectangular zone occupancy logic
|
ZoneManager.h/.cpp - rectangular zone occupancy logic
|
||||||
WebServerManager.h/.cpp - Wi-Fi, REST API, WebSocket broadcast
|
WebServerManager.h/.cpp - Wi-Fi, REST API, WebSocket broadcast
|
||||||
|
OLEDDisplay.h/.cpp - OLED I2C 128x64 display manager
|
||||||
config.example.h - copy to config.h and edit
|
config.example.h - copy to config.h and edit
|
||||||
README.md
|
README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## OLED Display Features
|
||||||
|
|
||||||
|
Màn hình OLED 128x64 hiển thị các thông tin:
|
||||||
|
|
||||||
|
### DIAGNOSTIC_MODE = 1 (Serial Debug Mode)
|
||||||
|
- **Màn hình boot**: Hiển thị logo và Node ID
|
||||||
|
- **Chế độ Diagnostic**: Thông báo Serial-only mode
|
||||||
|
- **Thống kê radar mỗi 5 giây**:
|
||||||
|
- Số bytes nhận được từ LD2453
|
||||||
|
- Số frames đã parse
|
||||||
|
- Số lỗi parse
|
||||||
|
- Packets per second (PPS)
|
||||||
|
- Số target phát hiện được
|
||||||
|
|
||||||
|
### DIAGNOSTIC_MODE = 0 (Full WiFi Mode)
|
||||||
|
- **Kết nối WiFi**: Hiển thị SSID đang kết nối
|
||||||
|
- **WiFi thành công**: Hiển thị địa chỉ IP
|
||||||
|
- **Detection realtime**:
|
||||||
|
- Số target phát hiện (T:0-3)
|
||||||
|
- Trạng thái 3 zones (YES/NO)
|
||||||
|
|
||||||
|
### Cấu hình OLED trong config.h
|
||||||
|
```cpp
|
||||||
|
#define OLED_ENABLED 1 // 1 = bật OLED, 0 = tắt
|
||||||
|
#define OLED_SDA_PIN 6 // Chân SDA
|
||||||
|
#define OLED_SCL_PIN 7 // Chân SCL
|
||||||
|
#define OLED_I2C_ADDR 0x3C // Địa chỉ I2C (thường là 0x3C hoặc 0x3D)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Lưu ý**: Nếu màn hình không hoạt động, hãy thử đổi `OLED_I2C_ADDR` từ `0x3C` sang `0x3D`.
|
||||||
|
|
||||||
## Stage 1: diagnostic mode (do this first)
|
## Stage 1: diagnostic mode (do this first)
|
||||||
|
|
||||||
1. Copy `config.example.h` to `config.h`.
|
1. Copy `config.example.h` to `config.h`.
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
// No-op if no clients are connected.
|
// No-op if no clients are connected.
|
||||||
void broadcastFrame(const RadarFrame &frame);
|
void broadcastFrame(const RadarFrame &frame);
|
||||||
|
|
||||||
|
IPAddress getLocalIP() const { return WiFi.localIP(); }
|
||||||
bool isWifiConnected() const { return WiFi.status() == WL_CONNECTED; }
|
bool isWifiConnected() const { return WiFi.status() == WL_CONNECTED; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -35,6 +35,14 @@
|
|||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
#define NODE_ID "RADAR_A"
|
#define NODE_ID "RADAR_A"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// OLED Display (I2C 128x64)
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
#define OLED_ENABLED 1 // 1 = enable OLED display, 0 = disable
|
||||||
|
#define OLED_SDA_PIN 6 // I2C SDA pin
|
||||||
|
#define OLED_SCL_PIN 7 // I2C SCL pin
|
||||||
|
#define OLED_I2C_ADDR 0x3C // I2C address (0x3C or 0x3D, check your module)
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Debug / diagnostic switches
|
// Debug / diagnostic switches
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ HardwareSerial &RadarSerial = Serial2;
|
|||||||
LD2453Parser radar;
|
LD2453Parser radar;
|
||||||
ZoneManager zoneManager;
|
ZoneManager zoneManager;
|
||||||
|
|
||||||
|
#if OLED_ENABLED
|
||||||
|
OLEDDisplay oledDisplay(OLED_SDA_PIN, OLED_SCL_PIN, OLED_I2C_ADDR);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !DIAGNOSTIC_MODE
|
#if !DIAGNOSTIC_MODE
|
||||||
WebServerManager webServer(zoneManager);
|
WebServerManager webServer(zoneManager);
|
||||||
#endif
|
#endif
|
||||||
@@ -104,8 +108,22 @@ void loop() {
|
|||||||
|
|
||||||
#if DIAGNOSTIC_MODE
|
#if DIAGNOSTIC_MODE
|
||||||
printDiagnostics(frame, radar.getStats());
|
printDiagnostics(frame, radar.getStats());
|
||||||
|
|
||||||
|
#if OLED_ENABLED
|
||||||
|
oledDisplay.updateRadarInfo(frame, radar.getStats());
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
webServer.broadcastFrame(frame);
|
webServer.broadcastFrame(frame);
|
||||||
|
|
||||||
|
#if OLED_ENABLED
|
||||||
|
// Hiển thị tóm tắt detection và zones
|
||||||
|
oledDisplay.updateDetectionSummary(
|
||||||
|
frame.targetCount,
|
||||||
|
zoneManager.isZoneOccupied(0),
|
||||||
|
zoneManager.isZoneOccupied(1),
|
||||||
|
zoneManager.isZoneOccupied(2)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +143,11 @@ void loop() {
|
|||||||
Serial.print(F("Packets/sec: "));
|
Serial.print(F("Packets/sec: "));
|
||||||
Serial.println(stats.packetsPerSecond, 1);
|
Serial.println(stats.packetsPerSecond, 1);
|
||||||
lastStatsReport = now;
|
lastStatsReport = now;
|
||||||
|
|
||||||
|
#if OLED_ENABLED
|
||||||
|
// Cập nhật OLED ngay cả khi không có frame
|
||||||
|
oledDisplay.updateStats(stats);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
webServer.loop();
|
webServer.loop();
|
||||||
|
|||||||
Reference in new issue
Block a user