From 0c200c78991e50bbe4329aee7b418210563833cb Mon Sep 17 00:00:00 2001 From: byun Date: Thu, 13 Nov 2025 04:13:13 +0000 Subject: [PATCH] 2 --- test_i2c_reset/ESP32_CAN_Logger.ino | 480 ---------------------------- 1 file changed, 480 deletions(-) diff --git a/test_i2c_reset/ESP32_CAN_Logger.ino b/test_i2c_reset/ESP32_CAN_Logger.ino index 0db5681..5ed794c 100644 --- a/test_i2c_reset/ESP32_CAN_Logger.ino +++ b/test_i2c_reset/ESP32_CAN_Logger.ino @@ -25,7 +25,6 @@ #include "graph.h" #include "graph_viewer.h" #include "settings.h" -#include "serial_terminal.h" // GPIO 핀 정의 #define CAN_INT_PIN 27 @@ -47,10 +46,6 @@ #define RTC_SCL 26 #define DS3231_ADDRESS 0x68 -// Serial2 핀 (RS232 통신) -#define SERIAL2_RX 16 -#define SERIAL2_TX 17 - // 버퍼 설정 #define CAN_QUEUE_SIZE 2000 // 1000 → 2000으로 증가 #define FILE_BUFFER_SIZE 16384 // 8192 → 16384 (16KB)로 증가 @@ -58,8 +53,6 @@ #define RECENT_MSG_COUNT 100 #define MAX_TX_MESSAGES 20 #define MAX_COMMENT_LEN 128 -#define SERIAL_BUFFER_SIZE 1024 -#define SERIAL_LOG_BUFFER_SIZE 32768 // RTC 동기화 설정 #define RTC_SYNC_INTERVAL_MS 60000 // 1분마다 RTC와 동기화 @@ -126,29 +119,6 @@ struct FileComment { char comment[MAX_COMMENT_LEN]; }; -// Serial 설정 구조체 -struct SerialTermConfig { - uint32_t baudRate; - uint8_t dataBits; - uint8_t parity; - uint8_t stopBits; - bool enabled; - bool echoEnabled; - bool timestampEnabled; - bool autoSaveEnabled; - char logFilename[MAX_FILENAME_LEN]; -}; - -// 시리얼 데이터 버퍼 -struct SerialDataBuffer { - char data[SERIAL_LOG_BUFFER_SIZE]; - uint32_t writeIndex; - uint32_t readIndex; - bool overflow; - SemaphoreHandle_t mutex; -}; - - // 시간 동기화 상태 struct TimeSyncStatus { bool synchronized; @@ -203,24 +173,6 @@ WebServer server(80); WebSocketsServer webSocket = WebSocketsServer(81); Preferences preferences; -// 시리얼 터미널 전역 변수 -SerialTermConfig serialTermConfig = { - 9600, 8, 0, 1, false, true, true, false, "serial_log.txt" -}; -SerialDataBuffer serialBuffer; -WebSocketsServer serialWebSocket = WebSocketsServer(82); -QueueHandle_t serialQueue; -TaskHandle_t serialTaskHandle = NULL; -File serialLogFile; -volatile uint32_t serialRxCount = 0; -volatile uint32_t serialTxCount = 0; -volatile uint32_t serialRxPerSecond = 0; -volatile uint32_t serialTxPerSecond = 0; -uint32_t lastSerialCountTime = 0; -uint32_t lastSerialRxCount = 0; -uint32_t lastSerialTxCount = 0; - - // Forward declaration void IRAM_ATTR canISR(); @@ -323,9 +275,6 @@ void loadSettings() { if (enableSTAMode && strlen(staSSID) > 0) { Serial.printf("✓ WiFi STA 모드: 활성화 (SSID: %s)\n", staSSID); } - - // 시리얼 설정 로드 - loadSerialSettings(); } void saveSettings() { @@ -356,430 +305,6 @@ void saveSettings() { Serial.println("⚠️ 재부팅 후 WiFi 설정이 적용됩니다."); } - -// ======================================== -// 시리얼 터미널 함수들 -// ======================================== - -void loadSerialSettings() { - preferences.begin("serial-term", false); - - serialTermConfig.baudRate = preferences.getUInt("baud", 9600); - serialTermConfig.dataBits = preferences.getUChar("databits", 8); - serialTermConfig.parity = preferences.getUChar("parity", 0); - serialTermConfig.stopBits = preferences.getUChar("stopbits", 1); - serialTermConfig.enabled = preferences.getBool("enabled", false); - serialTermConfig.echoEnabled = preferences.getBool("echo", true); - serialTermConfig.timestampEnabled = preferences.getBool("timestamp", true); - serialTermConfig.autoSaveEnabled = preferences.getBool("autosave", false); - preferences.getString("logfile", serialTermConfig.logFilename, sizeof(serialTermConfig.logFilename)); - - if (strlen(serialTermConfig.logFilename) == 0) { - strcpy(serialTermConfig.logFilename, "serial_log.txt"); - } - - preferences.end(); - - Serial.printf("✓ 시리얼 설정 로드: %d-%d-%c-%d\n", - serialTermConfig.baudRate, - serialTermConfig.dataBits, - serialTermConfig.parity == 0 ? 'N' : (serialTermConfig.parity == 1 ? 'E' : 'O'), - serialTermConfig.stopBits); -} - -void saveSerialSettings() { - preferences.begin("serial-term", false); - - preferences.putUInt("baud", serialTermConfig.baudRate); - preferences.putUChar("databits", serialTermConfig.dataBits); - preferences.putUChar("parity", serialTermConfig.parity); - preferences.putUChar("stopbits", serialTermConfig.stopBits); - preferences.putBool("enabled", serialTermConfig.enabled); - preferences.putBool("echo", serialTermConfig.echoEnabled); - preferences.putBool("timestamp", serialTermConfig.timestampEnabled); - preferences.putBool("autosave", serialTermConfig.autoSaveEnabled); - preferences.putString("logfile", serialTermConfig.logFilename); - - preferences.end(); - - Serial.println("✓ 시리얼 설정 저장 완료"); -} - -void configureSerial2() { - Serial2.end(); - - uint32_t config = SERIAL_8N1; - - switch(serialTermConfig.dataBits) { - case 5: config = SERIAL_5N1; break; - case 6: config = SERIAL_6N1; break; - case 7: config = SERIAL_7N1; break; - case 8: default: config = SERIAL_8N1; break; - } - - if (serialTermConfig.parity == 1) { - switch(serialTermConfig.dataBits) { - case 5: config = SERIAL_5E1; break; - case 6: config = SERIAL_6E1; break; - case 7: config = SERIAL_7E1; break; - case 8: default: config = SERIAL_8E1; break; - } - } else if (serialTermConfig.parity == 2) { - switch(serialTermConfig.dataBits) { - case 5: config = SERIAL_5O1; break; - case 6: config = SERIAL_6O1; break; - case 7: config = SERIAL_7O1; break; - case 8: default: config = SERIAL_8O1; break; - } - } - - if (serialTermConfig.stopBits == 2) { - switch(serialTermConfig.dataBits) { - case 5: - if (serialTermConfig.parity == 0) config = SERIAL_5N2; - else if (serialTermConfig.parity == 1) config = SERIAL_5E2; - else config = SERIAL_5O2; - break; - case 6: - if (serialTermConfig.parity == 0) config = SERIAL_6N2; - else if (serialTermConfig.parity == 1) config = SERIAL_6E2; - else config = SERIAL_6O2; - break; - case 7: - if (serialTermConfig.parity == 0) config = SERIAL_7N2; - else if (serialTermConfig.parity == 1) config = SERIAL_7E2; - else config = SERIAL_7O2; - break; - case 8: default: - if (serialTermConfig.parity == 0) config = SERIAL_8N2; - else if (serialTermConfig.parity == 1) config = SERIAL_8E2; - else config = SERIAL_8O2; - break; - } - } - - Serial2.begin(serialTermConfig.baudRate, config, SERIAL2_RX, SERIAL2_TX); - Serial.printf("✓ Serial2 구성: %d baud, config=0x%X\n", serialTermConfig.baudRate, config); -} - -void addToSerialBuffer(const char* data, size_t len, bool isTx) { - if (!serialBuffer.mutex) return; - - xSemaphoreTake(serialBuffer.mutex, portMAX_DELAY); - - if (serialTermConfig.timestampEnabled) { - char timestamp[32]; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *tm_info = localtime(&tv.tv_sec); - snprintf(timestamp, sizeof(timestamp), "[%02d:%02d:%02d.%03ld] %s: ", - tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, - tv.tv_usec / 1000, isTx ? "TX" : "RX"); - - size_t tsLen = strlen(timestamp); - for (size_t i = 0; i < tsLen; i++) { - serialBuffer.data[serialBuffer.writeIndex] = timestamp[i]; - serialBuffer.writeIndex = (serialBuffer.writeIndex + 1) % SERIAL_LOG_BUFFER_SIZE; - if (serialBuffer.writeIndex == serialBuffer.readIndex) { - serialBuffer.overflow = true; - serialBuffer.readIndex = (serialBuffer.readIndex + 1) % SERIAL_LOG_BUFFER_SIZE; - } - } - } - - for (size_t i = 0; i < len; i++) { - serialBuffer.data[serialBuffer.writeIndex] = data[i]; - serialBuffer.writeIndex = (serialBuffer.writeIndex + 1) % SERIAL_LOG_BUFFER_SIZE; - if (serialBuffer.writeIndex == serialBuffer.readIndex) { - serialBuffer.overflow = true; - serialBuffer.readIndex = (serialBuffer.readIndex + 1) % SERIAL_LOG_BUFFER_SIZE; - } - } - - xSemaphoreGive(serialBuffer.mutex); -} - -String getSerialBufferData() { - if (!serialBuffer.mutex) return ""; - - String result; - xSemaphoreTake(serialBuffer.mutex, portMAX_DELAY); - - uint32_t idx = serialBuffer.readIndex; - while (idx != serialBuffer.writeIndex) { - result += serialBuffer.data[idx]; - idx = (idx + 1) % SERIAL_LOG_BUFFER_SIZE; - } - - xSemaphoreGive(serialBuffer.mutex); - return result; -} - -void clearSerialBuffer() { - if (!serialBuffer.mutex) return; - - xSemaphoreTake(serialBuffer.mutex, portMAX_DELAY); - serialBuffer.readIndex = serialBuffer.writeIndex; - serialBuffer.overflow = false; - xSemaphoreGive(serialBuffer.mutex); -} - -bool saveSerialLog() { - if (!sdCardReady) return false; - - String data = getSerialBufferData(); - if (data.length() == 0) return true; - - xSemaphoreTake(sdMutex, portMAX_DELAY); - - File file = SD.open(serialTermConfig.logFilename, FILE_APPEND); - if (!file) { - xSemaphoreGive(sdMutex); - return false; - } - - size_t written = file.print(data); - file.close(); - - xSemaphoreGive(sdMutex); - - if (written > 0) { - clearSerialBuffer(); - return true; - } - return false; -} - -void serialTask(void *pvParameters) { - char rxBuffer[SERIAL_BUFFER_SIZE]; - size_t rxIndex = 0; - - Serial.println("✓ Serial Task 시작 (Core 0, Priority 1)"); - - while (true) { - if (serialTermConfig.enabled && Serial2.available()) { - while (Serial2.available() && rxIndex < SERIAL_BUFFER_SIZE - 1) { - char c = Serial2.read(); - rxBuffer[rxIndex++] = c; - serialRxCount++; - - if (serialTermConfig.echoEnabled) { - Serial2.write(c); - serialTxCount++; - } - } - - if (rxIndex > 0) { - addToSerialBuffer(rxBuffer, rxIndex, false); - - String data; - for (size_t i = 0; i < rxIndex; i++) { - if (rxBuffer[i] >= 32 && rxBuffer[i] < 127) { - data += rxBuffer[i]; - } else if (rxBuffer[i] == '\r' || rxBuffer[i] == '\n') { - data += rxBuffer[i]; - } else { - char hex[5]; - snprintf(hex, sizeof(hex), "<%02X>", (uint8_t)rxBuffer[i]); - data += hex; - } - } - serialWebSocket.broadcastTXT(data); - - if (serialTermConfig.autoSaveEnabled && rxIndex > 100) { - saveSerialLog(); - } - - rxIndex = 0; - } - } - - vTaskDelay(pdMS_TO_TICKS(10)); - } -} - -void handleSerialTerminal() { - server.send_P(200, "text/html", SERIAL_TERMINAL_HTML); -} - -void handleSerialConfig() { - String json = "{"; - json += "\"baudRate\":" + String(serialTermConfig.baudRate) + ","; - json += "\"dataBits\":" + String(serialTermConfig.dataBits) + ","; - json += "\"parity\":" + String(serialTermConfig.parity) + ","; - json += "\"stopBits\":" + String(serialTermConfig.stopBits) + ","; - json += "\"enabled\":" + String(serialTermConfig.enabled ? "true" : "false") + ","; - json += "\"echo\":" + String(serialTermConfig.echoEnabled ? "true" : "false") + ","; - json += "\"timestamp\":" + String(serialTermConfig.timestampEnabled ? "true" : "false") + ","; - json += "\"autosave\":" + String(serialTermConfig.autoSaveEnabled ? "true" : "false") + ","; - json += "\"logFilename\":\"" + String(serialTermConfig.logFilename) + "\","; - json += "\"rxCount\":" + String(serialRxCount) + ","; - json += "\"txCount\":" + String(serialTxCount) + ","; - json += "\"rxPerSec\":" + String(serialRxPerSecond) + ","; - json += "\"txPerSec\":" + String(serialTxPerSecond); - json += "}"; - - server.send(200, "application/json", json); -} - -void handleSerialSetConfig() { - if (server.hasArg("plain")) { - String body = server.arg("plain"); - - if (body.indexOf("baudRate") >= 0) { - int idx = body.indexOf("baudRate\":") + 10; - serialTermConfig.baudRate = body.substring(idx, body.indexOf(',', idx)).toInt(); - } - if (body.indexOf("dataBits") >= 0) { - int idx = body.indexOf("dataBits\":") + 10; - serialTermConfig.dataBits = body.substring(idx, body.indexOf(',', idx)).toInt(); - } - if (body.indexOf("parity") >= 0) { - int idx = body.indexOf("parity\":") + 8; - serialTermConfig.parity = body.substring(idx, body.indexOf(',', idx)).toInt(); - } - if (body.indexOf("stopBits") >= 0) { - int idx = body.indexOf("stopBits\":") + 10; - serialTermConfig.stopBits = body.substring(idx, body.indexOf(',', idx)).toInt(); - } - if (body.indexOf("enabled") >= 0) { - serialTermConfig.enabled = body.indexOf("\"enabled\":true") >= 0; - } - if (body.indexOf("echo") >= 0) { - serialTermConfig.echoEnabled = body.indexOf("\"echo\":true") >= 0; - } - if (body.indexOf("timestamp") >= 0) { - serialTermConfig.timestampEnabled = body.indexOf("\"timestamp\":true") >= 0; - } - if (body.indexOf("autosave") >= 0) { - serialTermConfig.autoSaveEnabled = body.indexOf("\"autosave\":true") >= 0; - } - if (body.indexOf("logFilename") >= 0) { - int idx = body.indexOf("logFilename\":\"") + 14; - String filename = body.substring(idx, body.indexOf('\"', idx)); - filename.toCharArray(serialTermConfig.logFilename, sizeof(serialTermConfig.logFilename)); - } - - configureSerial2(); - saveSerialSettings(); - - server.send(200, "application/json", "{\"status\":\"ok\"}"); - } else { - server.send(400, "application/json", "{\"status\":\"error\"}"); - } -} - -void handleSerialSend() { - if (server.hasArg("data")) { - String data = server.arg("data"); - - if (serialTermConfig.enabled) { - data.replace("\\r", "\r"); - data.replace("\\n", "\n"); - - Serial2.print(data); - serialTxCount += data.length(); - - addToSerialBuffer(data.c_str(), data.length(), true); - - server.send(200, "application/json", "{\"status\":\"ok\"}"); - } else { - server.send(400, "application/json", "{\"status\":\"error\",\"message\":\"Serial not enabled\"}"); - } - } else { - server.send(400, "application/json", "{\"status\":\"error\",\"message\":\"No data\"}"); - } -} - -void handleSerialSaveLog() { - if (saveSerialLog()) { - server.send(200, "application/json", "{\"status\":\"ok\"}"); - } else { - server.send(500, "application/json", "{\"status\":\"error\"}"); - } -} - -void handleSerialClearBuffer() { - clearSerialBuffer(); - server.send(200, "application/json", "{\"status\":\"ok\"}"); -} - -void serialWebSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { - switch(type) { - case WStype_DISCONNECTED: - Serial.printf("[%u] Serial WebSocket Disconnected\n", num); - break; - - case WStype_CONNECTED: { - IPAddress ip = serialWebSocket.remoteIP(num); - Serial.printf("[%u] Serial WebSocket Connected from %d.%d.%d.%d\n", - num, ip[0], ip[1], ip[2], ip[3]); - - String data = getSerialBufferData(); - if (data.length() > 0) { - serialWebSocket.sendTXT(num, data); - } - break; - } - - case WStype_TEXT: - if (serialTermConfig.enabled && length > 0) { - Serial2.write(payload, length); - serialTxCount += length; - addToSerialBuffer((const char*)payload, length, true); - } - break; - - default: - break; - } -} - -void setupSerial() { - serialBuffer.writeIndex = 0; - serialBuffer.readIndex = 0; - serialBuffer.overflow = false; - serialBuffer.mutex = xSemaphoreCreateMutex(); - - configureSerial2(); - - serialQueue = xQueueCreate(100, sizeof(char) * SERIAL_BUFFER_SIZE); - - xTaskCreatePinnedToCore( - serialTask, - "SerialTask", - 4096, - NULL, - 1, - &serialTaskHandle, - 0 - ); - - serialWebSocket.begin(); - serialWebSocket.onEvent(serialWebSocketEvent); - - server.on("/serial", HTTP_GET, handleSerialTerminal); - server.on("/serial/config", HTTP_GET, handleSerialConfig); - server.on("/serial/setconfig", HTTP_POST, handleSerialSetConfig); - server.on("/serial/send", HTTP_POST, handleSerialSend); - server.on("/serial/savelog", HTTP_POST, handleSerialSaveLog); - server.on("/serial/clear", HTTP_POST, handleSerialClearBuffer); - - Serial.println("✓ 시리얼 터미널 초기화 완료 (CAN과 독립 동작)"); -} - -void updateSerialStats() { - uint32_t currentTime = millis(); - if (currentTime - lastSerialCountTime >= 1000) { - serialRxPerSecond = serialRxCount - lastSerialRxCount; - serialTxPerSecond = serialTxCount - lastSerialTxCount; - lastSerialRxCount = serialRxCount; - lastSerialTxCount = serialTxCount; - lastSerialCountTime = currentTime; - } -} - - void saveCANSettings() { preferences.begin("can-logger", false); @@ -2309,9 +1834,6 @@ void setup() { } }); - // 시리얼 터미널 초기화 - setupSerial(); - server.begin(); // Queue 생성 @@ -2362,8 +1884,6 @@ void setup() { void loop() { server.handleClient(); - serialWebSocket.loop(); - updateSerialStats(); vTaskDelay(pdMS_TO_TICKS(10)); static uint32_t lastPrint = 0;