websocket 속도 , task 조정

This commit is contained in:
2026-01-21 20:55:25 +00:00
parent 8a33481a2c
commit 95e182d68e

View File

@@ -220,6 +220,23 @@ SerialSettings serial2Settings = {115200, 8, 0, 1}; // ⭐ Serial2 추가
// 전역 객체 (내부 SRAM)
SPIClass hspi(HSPI);
// SPIClass vspi(FSPI); // ⭐ SDIO 사용으로 제거
// ========================================
// MCP2515 크리스탈 설정
// ========================================
// 8MHz 크리스탈: 500 Kbps까지 안정적
// 16MHz 크리스탈: 1 Mbps 고속 통신 권장 (고부하 대응)
//
// 사용법:
// - 하드웨어에 16MHz 크리스탈 장착 시: MCP_16MHZ
// - 하드웨어에 8MHz 크리스탈 장착 시: MCP_8MHZ
//
#define MCP_CRYSTAL MCP_16MHZ // ⭐ 16MHz 크리스탈 (1 Mbps 권장)
// #define MCP_CRYSTAL MCP_8MHZ // 8MHz 크리스탈 (500 Kbps까지)
// SPI 속도: 20MHz (MCP2515 최대 속도와 균형)
// 10MHz: 안정적이지만 느림
// 20MHz: 권장 (고속 + 안정성)
// 25MHz: 불안정할 수 있음
MCP2515 mcp2515(HSPI_CS, 20000000, &hspi);
HardwareSerial SerialComm(1); // UART1
HardwareSerial Serial2Comm(2); // ⭐ UART2 추가
@@ -370,7 +387,7 @@ void resetMCP2515() {
Serial.printf(" 3. Speed=%d, Mode=%d\n", (int)currentCanSpeed, (int)currentMcpMode);
// 5. Bitrate 설정 (Configuration 모드에서)
mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
delay(10);
// 6. 필터/마스크 설정 (모든 메시지 수신)
@@ -427,7 +444,7 @@ void resetMCP2515() {
// 에러가 있으면 완전 리셋
mcp2515.reset();
delay(50);
mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
delay(10);
if (currentMcpMode == MCP_MODE_NORMAL) {
mcp2515.setNormalMode();
@@ -1386,7 +1403,7 @@ void canRxTask(void *parameter) {
delay(100);
// 2. Bitrate 재설정
mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
delay(10);
// 3. 모든 에러 플래그 클리어
@@ -1807,10 +1824,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
if (type == WStype_CONNECTED) {
Serial.printf("[%u] ✅ WebSocket 연결됨\n", num);
// 기본 설정 전송
DynamicJsonDocument settings(512);
settings["type"] = "currentSettings";
// ⭐ 모든 데이터를 하나의 JSON으로 통합 전송 (빠른 연결)
DynamicJsonDocument allData(3072); // 통합 JSON
allData["type"] = "initialData";
// 기본 설정
int speedIndex = 3;
for (int i = 0; i < 4; i++) {
if (canSpeedValues[i] == currentCanSpeed) {
@@ -1818,29 +1836,20 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
break;
}
}
settings["canSpeed"] = speedIndex;
settings["mcpMode"] = (int)currentMcpMode;
settings["autoTriggerEnabled"] = autoTriggerEnabled;
settings["autoTriggerLogCSV"] = autoTriggerLogCSV;
allData["canSpeed"] = speedIndex;
allData["mcpMode"] = (int)currentMcpMode;
allData["autoTriggerEnabled"] = autoTriggerEnabled;
allData["autoTriggerLogCSV"] = autoTriggerLogCSV;
String json;
serializeJson(settings, json);
webSocket.sendTXT(num, json);
// Auto Trigger 설정도 전송
// Auto Trigger 설정도 포함
if (autoTriggerEnabled) {
delay(50); // 메시지 간격
allData["logFormat"] = autoTriggerLogCSV ? "csv" : "bin";
allData["startLogic"] = startLogicOp;
allData["stopLogic"] = stopLogicOp;
allData["startFormula"] = startFormula;
allData["stopFormula"] = stopFormula;
DynamicJsonDocument autoTrigger(2048);
autoTrigger["type"] = "autoTriggers";
autoTrigger["enabled"] = autoTriggerEnabled;
autoTrigger["logFormat"] = autoTriggerLogCSV ? "csv" : "bin";
autoTrigger["startLogic"] = startLogicOp;
autoTrigger["stopLogic"] = stopLogicOp;
autoTrigger["startFormula"] = startFormula;
autoTrigger["stopFormula"] = stopFormula;
JsonArray startArray = autoTrigger.createNestedArray("startTriggers");
JsonArray startArray = allData.createNestedArray("startTriggers");
for (int i = 0; i < startTriggerCount; i++) {
JsonObject t = startArray.createNestedObject();
char idStr[10];
@@ -1853,7 +1862,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
t["enabled"] = startTriggers[i].enabled;
}
JsonArray stopArray = autoTrigger.createNestedArray("stopTriggers");
JsonArray stopArray = allData.createNestedArray("stopTriggers");
for (int i = 0; i < stopTriggerCount; i++) {
JsonObject t = stopArray.createNestedObject();
char idStr[10];
@@ -1865,11 +1874,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
t["value"] = (long)stopTriggers[i].value;
t["enabled"] = stopTriggers[i].enabled;
}
String autoJson;
serializeJson(autoTrigger, autoJson);
webSocket.sendTXT(num, autoJson);
}
// ⭐ 하나의 메시지로 전송 (delay 제거)
String json;
serializeJson(allData, json);
webSocket.sendTXT(num, json);
}
else if (type == WStype_TEXT) {
DynamicJsonDocument doc(44384);
@@ -2138,7 +2148,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
// ⭐⭐⭐ MCP2515 리셋 제거! (CAN 수신 중단 방지)
// 속도 변경은 로깅 중지 후 수동으로만 가능하도록 변경
// mcp2515.reset();
// mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
// mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
// setMCP2515Mode(currentMcpMode);
saveSettings();
@@ -2263,7 +2273,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
// ⭐⭐⭐ MCP2515 리셋 제거! (CAN 수신 중단 방지)
// 속도 변경은 로깅 중지 후 수동으로만 가능하도록 변경
// mcp2515.reset();
// mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
// mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
// setMCP2515Mode(currentMcpMode);
saveSettings();
@@ -2875,10 +2885,10 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
// Web Update Task
// ========================================
void webUpdateTask(void *parameter) {
const TickType_t xDelay = pdMS_TO_TICKS(200); // ⭐ 100ms → 200ms (WiFi 안정성 향상)
const TickType_t xDelay = pdMS_TO_TICKS(100); // ⭐ 200ms → 100ms (더 빠른 업데이트)
// 🆕 초기화 대기 (부팅 직후 안정화)
vTaskDelay(pdMS_TO_TICKS(2000));
// 🆕 초기화 대기 단축 (부팅 직후 안정화)
vTaskDelay(pdMS_TO_TICKS(500)); // ⭐ 2000ms → 500ms (빠른 연결)
while (1) {
webSocket.loop();
@@ -3136,7 +3146,33 @@ void webUpdateTask(void *parameter) {
void setup() {
Serial.begin(115200);
delay(1000);
// ⭐ 리셋 원인 확인 (전원 부족 감지)
esp_reset_reason_t reset_reason = esp_reset_reason();
if (reset_reason == ESP_RST_BROWNOUT) {
Serial.println("");
Serial.println("╔════════════════════════════════════════════╗");
Serial.println("║ 🚨 브라운아웃 리셋 감지! ║");
Serial.println("║ ║");
Serial.println("║ 원인: 전원 공급 부족 ║");
Serial.println("║ ║");
Serial.println("║ 필요 전류: ║");
Serial.println("║ - 평균: 300 mA ║");
Serial.println("║ - 피크: 550 mA (WiFi TX + SD Write) ║");
Serial.println("║ ║");
Serial.println("║ 해결 방법: ║");
Serial.println("║ 1. 5V 1A USB 어댑터 사용 (권장) ║");
Serial.println("║ 2. USB 케이블 교체 (짧고 굵은 케이블) ║");
Serial.println("║ 3. USB 3.0 포트 사용 (900mA 지원) ║");
Serial.println("╚════════════════════════════════════════════╝");
Serial.println("");
delay(5000); // 경고 메시지 읽을 시간
}
// ⭐ WiFi 전력 최적화 (전류 소비 감소)
WiFi.setSleep(false);
WiFi.setTxPower(WIFI_POWER_15dBm); // 19.5dBm → 15dBm (전류 절감)
Serial.println("\n========================================");
Serial.println(" Byun CAN Logger + Serial Terminal");
Serial.println(" Version 2.3 - PSRAM Optimized");
@@ -3198,7 +3234,7 @@ void setup() {
// 4. Configuration 모드에서 설정 (중요: 이 순서대로!)
Serial.println(" 3. Bitrate 설정...");
mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
delay(10);
// 5. 필터/마스크 설정 (모든 메시지 수신)
@@ -3275,7 +3311,7 @@ void setup() {
// 에러가 있으면 완전 리셋 재시도
mcp2515.reset();
delay(50);
mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ);
mcp2515.setBitrate(currentCanSpeed, MCP_CRYSTAL);
delay(10);
mcp2515.clearRXnOVRFlags();
mcp2515.clearInterrupts();
@@ -3658,8 +3694,8 @@ void setup() {
// - TX: CAN 전송
// - SEQ: 시퀀스 재생
// - MONITOR: 상태 모니터링
xTaskCreatePinnedToCore(canRxTask, "CAN_RX", 12288, NULL, 24, &canRxTaskHandle, 1); // ⭐ 8KB → 12KB, Pri 24 (최고)
xTaskCreatePinnedToCore(webUpdateTask, "WEB_UPDATE", 12288, NULL, 4, &webTaskHandle, 1); // ⭐ Core 0 → 1, Pri 4 (SD와 분리)
xTaskCreatePinnedToCore(canRxTask, "CAN_RX", 12288, NULL, 20, &canRxTaskHandle, 1); // ⭐ 8KB → 12KB, Pri 24 (최고)
xTaskCreatePinnedToCore(webUpdateTask, "WEB_UPDATE", 12288, NULL, 16, &webTaskHandle, 1); // ⭐ Core 0 → 1, Pri 4 (SD와 분리)
xTaskCreatePinnedToCore(txTask, "TX", 4096, NULL, 3, NULL, 1); // Pri 3
xTaskCreatePinnedToCore(sequenceTask, "SEQ", 4096, NULL, 2, NULL, 1); // Pri 2
xTaskCreatePinnedToCore(sdMonitorTask, "SD_MONITOR", 4096, NULL, 1, NULL, 1); // Pri 1