From ebc60e9a279991ad0462e0b86c3f1a61e2ffe18d Mon Sep 17 00:00:00 2001 From: byun Date: Tue, 27 Jan 2026 19:22:25 +0000 Subject: [PATCH] =?UTF-8?q?stop=EC=8B=9C=20flush=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ESP32_CAN_Logger-a.ino | 88 +++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/ESP32_CAN_Logger-a.ino b/ESP32_CAN_Logger-a.ino index 9b551e4..b8e56be 100644 --- a/ESP32_CAN_Logger-a.ino +++ b/ESP32_CAN_Logger-a.ino @@ -237,7 +237,7 @@ SPIClass hspi(HSPI); // 10MHz: 안정적이지만 느림 // 20MHz: 권장 (고속 + 안정성) // 25MHz: 불안정할 수 있음 -MCP2515 mcp2515(HSPI_CS, 40000000, &hspi); +MCP2515 mcp2515(HSPI_CS, 80000000, &hspi); HardwareSerial SerialComm(1); // UART1 HardwareSerial Serial2Comm(2); // ⭐ UART2 추가 WebServer server(80); @@ -916,41 +916,51 @@ void checkAutoTriggers(struct can_frame &frame) { } if (anyMatch && result) { - // 🎯 파일 닫기 로직 추가 - if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(2000)) == pdTRUE) { - // ⭐⭐⭐ 더블 버퍼: 현재 쓰기 버퍼의 남은 데이터 flush - if (writeBufferIndex > 0 && logFile) { - size_t written = logFile.write(currentWriteBuffer, writeBufferIndex); - logFile.flush(); - Serial.printf("✓ Auto Trigger 최종 쓰기 버퍼 플러시: %d bytes\n", written); - writeBufferIndex = 0; - } + // 🎯 파일 닫기 로직 + Serial.println("🎯 Auto Trigger: 중지 조건 만족"); + + // ⭐⭐⭐ 1단계: 로깅 중지 (새 데이터 수신 차단) + loggingEnabled = false; + autoTriggerActive = false; + + if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(5000)) == pdTRUE) { - // ⭐ flush 태스크가 작업 중이면 완료 대기 + // ⭐⭐⭐ 2단계: flush 태스크 완료 대기 + Serial.println("⏳ Flush 태스크 완료 대기 중..."); int waitCount = 0; - while (flushInProgress && waitCount < 500) { + while (flushInProgress && waitCount < 1000) { // 최대 10초 vTaskDelay(10); waitCount++; } - - // CSV 형식: 최종 플러시 - if (canLogFormatCSV && logFile) { - logFile.flush(); + if (waitCount > 0) { + Serial.printf("✓ Flush 완료: %d ms 대기\n", waitCount * 10); } + // ⭐⭐⭐ 3단계: 현재 쓰기 버퍼의 남은 데이터 flush + if (writeBufferIndex > 0 && logFile) { + size_t written = logFile.write(currentWriteBuffer, writeBufferIndex); + Serial.printf("✓ 쓰기 버퍼 최종 플러시: %d bytes\n", written); + writeBufferIndex = 0; + } + + // ⭐⭐⭐ 4단계: 최종 flush + if (logFile) { + logFile.flush(); + Serial.println("✓ 최종 flush 완료"); + } + + // ⭐⭐⭐ 5단계: 파일 닫기 if (logFile) { size_t finalSize = logFile.size(); logFile.close(); Serial.printf("✓ Auto Trigger 파일 닫힘: %s (%lu bytes)\n", currentFilename, finalSize); } - loggingEnabled = false; - autoTriggerActive = false; currentFilename[0] = '\0'; writeBufferIndex = 0; flushBufferSize = 0; - Serial.println("🎯 Auto Trigger: 로깅 중지!"); + Serial.println("🎯 Auto Trigger: 로깅 중지 완료!"); Serial.printf(" 조건: ID 0x%03X 만족\n", frame.can_id); xSemaphoreGive(sdMutex); @@ -1527,7 +1537,8 @@ void sdFlushTask(void *parameter) { // ⭐ SD 뮤텍스 획득 (최대 5초 대기) if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(5000)) == pdTRUE) { - if (logFile && sdCardReady && loggingEnabled) { + // ⭐⭐⭐ loggingEnabled 체크 제거! (중지 시에도 flush 필요) + if (logFile && sdCardReady) { // ⭐ flush 버퍼를 SD에 쓰기 size_t written = logFile.write(currentFlushBuffer, flushSize); @@ -2099,42 +2110,49 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) if (loggingEnabled) { Serial.println("🛑 로깅 중지 요청..."); - if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(2000)) == pdTRUE) { - // ⭐⭐⭐ 더블 버퍼: 현재 쓰기 버퍼의 남은 데이터 flush - if (writeBufferIndex > 0 && logFile) { - size_t written = logFile.write(currentWriteBuffer, writeBufferIndex); - logFile.flush(); - Serial.printf("✓ 최종 쓰기 버퍼 플러시: %d bytes\n", written); - writeBufferIndex = 0; - } + // ⭐⭐⭐ 1단계: 로깅 중지 (새 데이터 수신 차단) + loggingEnabled = false; + + if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(5000)) == pdTRUE) { - // ⭐ flush 태스크가 작업 중이면 완료 대기 + // ⭐⭐⭐ 2단계: flush 태스크 완료 대기 (진행 중인 flush) + Serial.println("⏳ Flush 태스크 완료 대기 중..."); int waitCount = 0; - while (flushInProgress && waitCount < 500) { + while (flushInProgress && waitCount < 1000) { // 최대 10초 vTaskDelay(10); waitCount++; } if (waitCount > 0) { - Serial.printf("✓ Flush 태스크 완료 대기: %d ms\n", waitCount * 10); + Serial.printf("✓ Flush 태스크 완료: %d ms 대기\n", waitCount * 10); } - // ⭐⭐⭐ CSV 형식: 최종 플러시 - if (canLogFormatCSV && logFile) { + // ⭐⭐⭐ 3단계: 현재 쓰기 버퍼의 남은 데이터 flush + if (writeBufferIndex > 0 && logFile) { + size_t written = logFile.write(currentWriteBuffer, writeBufferIndex); + Serial.printf("✓ 쓰기 버퍼 최종 플러시: %d bytes\n", written); + writeBufferIndex = 0; + } + + // ⭐⭐⭐ 4단계: 최종 flush (메타데이터 동기화) + if (logFile) { logFile.flush(); - Serial.println("✓ CSV 최종 플러시"); + Serial.println("✓ 최종 flush 완료"); } + // ⭐⭐⭐ 5단계: 파일 닫기 if (logFile) { size_t finalSize = logFile.size(); logFile.close(); Serial.printf("✓ 파일 닫힘: %s (%lu bytes)\n", currentFilename, finalSize); } - loggingEnabled = false; currentFilename[0] = '\0'; writeBufferIndex = 0; flushBufferSize = 0; + xSemaphoreGive(sdMutex); + + Serial.println("✅ 로깅 중지 완료!"); } else { Serial.println("✗ sdMutex 획득 실패!"); }