diff --git a/ESP32_CAN_Logger-a.ino b/ESP32_CAN_Logger-a.ino index 604ffb9..ab55fe6 100644 --- a/ESP32_CAN_Logger-a.ino +++ b/ESP32_CAN_Logger-a.ino @@ -275,6 +275,10 @@ char startLogicOp[4] = "OR"; char stopLogicOp[4] = "OR"; bool autoTriggerActive = false; bool autoTriggerLogCSV = false; // π Auto Triggerμ© CSV νμ μ€μ + +// π File Format μ μ₯ λ³μ +bool savedCanLogFormatCSV = false; // μ μ₯λ CAN λ‘κ·Έ νμ (BIN=false, CSV=true) + volatile bool serialLoggingEnabled = false; volatile bool serial2LoggingEnabled = false; // β Serial2 μΆκ° volatile bool sdCardReady = false; @@ -298,7 +302,7 @@ volatile uint64_t serialLogStartTime = 0; volatile uint64_t serial2LogStartTime = 0; // β Serial2 μΆκ° // κΈ°ν μ μ λ³μ -MCP2515Mode currentMcpMode = MCP_MODE_LISTEN_ONLY; +MCP2515Mode currentMcpMode; SoftWire rtcWire(RTC_SDA, RTC_SCL); char rtcSyncBuffer[20]; CAN_SPEED currentCanSpeed = CAN_1000KBPS; @@ -348,12 +352,23 @@ void resetMCP2515() { // 4. MCP2515 μ¬μ΄κΈ°ν mcp2515.reset(); delay(100); + + // β Preferencesμμ μ€μ λΆλ¬μ€κΈ° + preferences.begin("can-logger", true); + int speedIndex = preferences.getInt("can_speed", 3); + if (speedIndex >= 0 && speedIndex < 4) { + currentCanSpeed = canSpeedValues[speedIndex]; + } + int savedMode = preferences.getInt("mcp_mode", 1); + if (savedMode >= 0 && savedMode <= 3) { + currentMcpMode = (MCP2515Mode)savedMode; + } + preferences.end(); + + Serial.printf("π§ resetMCP2515: Speed=%d, Mode=%d\n", (int)currentCanSpeed, (int)currentMcpMode); + mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ); delay(10); - mcp2515.setListenOnlyMode(); - //currentMcpMode = MCP_MODE_LISTEN_ONLY; - - // 5. λͺ¨λ μ€μ (Normal/Loopback/Listen Only) if (currentMcpMode == MCP_MODE_NORMAL) { @@ -639,10 +654,15 @@ void loadSettings() { } int savedMode = preferences.getInt("mcp_mode", 1); + Serial.printf("π₯ loadSettings: MCP Mode = %d\n", savedMode); if (savedMode >= 0 && savedMode <= 3) { currentMcpMode = (MCP2515Mode)savedMode; } + // π File Format λΆλ¬μ€κΈ° + savedCanLogFormatCSV = preferences.getBool("can_format_csv", false); + Serial.printf("π₯ loadSettings: CAN Format = %s\n", savedCanLogFormatCSV ? "CSV" : "BIN"); + loadSerialSettings(); preferences.end(); } @@ -833,9 +853,19 @@ void saveAutoTriggerSettings() { preferences.putBool("enabled", autoTriggerEnabled); preferences.putBool("logCSV", autoTriggerLogCSV); // π λ‘κ·Έ νμ μ μ₯ + Serial.printf("πΎ Save: autoTriggerLogCSV = %d\n", autoTriggerLogCSV); preferences.putString("start_logic", startLogicOp); preferences.putString("stop_logic", stopLogicOp); + // λλ²κ·Έ: Start Triggers μ μ₯ + Serial.printf("πΎ Save: startTriggerCount = %d\n", startTriggerCount); + for (int i = 0; i < startTriggerCount; i++) { + Serial.printf(" [%d] ID=0x%X, Bit=%d, Len=%d, Op=%s, Val=%ld, En=%d\n", + i, startTriggers[i].canId, startTriggers[i].startBit, + startTriggers[i].bitLength, startTriggers[i].op, + startTriggers[i].value, startTriggers[i].enabled); + } + preferences.putInt("start_count", startTriggerCount); for (int i = 0; i < startTriggerCount; i++) { char key[32]; @@ -884,6 +914,7 @@ void loadAutoTriggerSettings() { autoTriggerEnabled = preferences.getBool("enabled", false); autoTriggerLogCSV = preferences.getBool("logCSV", false); // π λ‘κ·Έ νμ λ‘λ + Serial.printf("π₯ Load: autoTriggerLogCSV = %d\n", autoTriggerLogCSV); preferences.getString("start_logic", startLogicOp, sizeof(startLogicOp)); preferences.getString("stop_logic", stopLogicOp, sizeof(stopLogicOp)); @@ -914,6 +945,15 @@ void loadAutoTriggerSettings() { startTriggers[i].enabled = preferences.getBool(key, true); } + // λλ²κ·Έ: Start Triggers μΆλ ₯ + Serial.printf("π₯ Load: startTriggerCount = %d\n", startTriggerCount); + for (int i = 0; i < startTriggerCount; i++) { + Serial.printf(" [%d] ID=0x%X, Bit=%d, Len=%d, Op=%s, Val=%ld, En=%d\n", + i, startTriggers[i].canId, startTriggers[i].startBit, + startTriggers[i].bitLength, startTriggers[i].op, + startTriggers[i].value, startTriggers[i].enabled); + } + stopTriggerCount = preferences.getInt("stop_count", 0); if (stopTriggerCount > MAX_TRIGGERS) stopTriggerCount = MAX_TRIGGERS; @@ -960,6 +1000,12 @@ void saveSettings() { } preferences.putInt("mcp_mode", (int)currentMcpMode); + Serial.printf("πΎ MCP Mode μ μ₯: %d\n", (int)currentMcpMode); + + // π File Format μ μ₯ + preferences.putBool("can_format_csv", savedCanLogFormatCSV); + Serial.printf("πΎ CAN Format μ μ₯: %s\n", savedCanLogFormatCSV ? "CSV" : "BIN"); + saveSerialSettings(); preferences.end(); } @@ -1082,6 +1128,7 @@ void rtcSyncTask(void *parameter) { // MCP2515 λͺ¨λ // ======================================== bool setMCP2515Mode(MCP2515Mode mode) { + Serial.printf("π§ MCP Mode λ³κ²½ μμ²: %d β ", (int)mode); const char* modeName; MCP2515::ERROR result; @@ -1652,7 +1699,75 @@ void sequenceTask(void *parameter) { // WebSocket μ΄λ²€νΈ μ²λ¦¬ (μ€μ!) // ======================================== void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) { - if (type == WStype_TEXT) { + // π WebSocket μ°κ²° μ νμ¬ μ€μ μ μ‘ + if (type == WStype_CONNECTED) { + Serial.printf("[%u] β WebSocket μ°κ²°λ¨\n", num); + + // κΈ°λ³Έ μ€μ μ μ‘ + DynamicJsonDocument settings(512); + settings["type"] = "currentSettings"; + + int speedIndex = 3; + for (int i = 0; i < 4; i++) { + if (canSpeedValues[i] == currentCanSpeed) { + speedIndex = i; + break; + } + } + settings["canSpeed"] = speedIndex; + settings["mcpMode"] = (int)currentMcpMode; + settings["autoTriggerEnabled"] = autoTriggerEnabled; + settings["autoTriggerLogCSV"] = autoTriggerLogCSV; + + String json; + serializeJson(settings, json); + webSocket.sendTXT(num, json); + + // Auto Trigger μ€μ λ μ μ‘ + if (autoTriggerEnabled) { + delay(50); // λ©μμ§ κ°κ²© + + 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"); + for (int i = 0; i < startTriggerCount; i++) { + JsonObject t = startArray.createNestedObject(); + char idStr[10]; + sprintf(idStr, "0x%03X", startTriggers[i].canId); + t["canId"] = idStr; + t["startBit"] = startTriggers[i].startBit; + t["bitLength"] = startTriggers[i].bitLength; + t["op"] = startTriggers[i].op; + t["value"] = (long)startTriggers[i].value; + t["enabled"] = startTriggers[i].enabled; + } + + JsonArray stopArray = autoTrigger.createNestedArray("stopTriggers"); + for (int i = 0; i < stopTriggerCount; i++) { + JsonObject t = stopArray.createNestedObject(); + char idStr[10]; + sprintf(idStr, "0x%03X", stopTriggers[i].canId); + t["canId"] = idStr; + t["startBit"] = stopTriggers[i].startBit; + t["bitLength"] = stopTriggers[i].bitLength; + t["op"] = stopTriggers[i].op; + t["value"] = (long)stopTriggers[i].value; + t["enabled"] = stopTriggers[i].enabled; + } + + String autoJson; + serializeJson(autoTrigger, autoJson); + webSocket.sendTXT(num, autoJson); + } + } + else if (type == WStype_TEXT) { DynamicJsonDocument doc(44384); DeserializationError error = deserializeJson(doc, payload); @@ -2242,6 +2357,23 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) serializeJson(response, json); webSocket.sendTXT(num, json); } + // π CAN File Format μ μ₯ λͺ λ Ή (λ©μΈ νμ΄μ§μ©) + else if (strcmp(cmd, "saveCanFormat") == 0) { + const char* format = doc["format"]; + if (format) { + savedCanLogFormatCSV = (strcmp(format, "csv") == 0); + saveSettings(); + Serial.printf("πΎ CAN File Format μ μ₯: %s\n", savedCanLogFormatCSV ? "CSV" : "BIN"); + } + + DynamicJsonDocument response(128); + response["type"] = "canFormatSaved"; + response["format"] = savedCanLogFormatCSV ? "csv" : "bin"; + + String json; + serializeJson(response, json); + webSocket.sendTXT(num, json); + } else if (strcmp(cmd, "setStartTriggers") == 0) { JsonArray triggers = doc["triggers"]; strcpy(startLogicOp, doc["logic"] | "OR"); @@ -2698,6 +2830,9 @@ void webUpdateTask(void *parameter) { doc["lowVoltage"] = powerStatus.lowVoltage; doc["mcpMode"] = (int)currentMcpMode; + // π μ μ₯λ File Format μ μ‘ + doc["savedCanFormat"] = savedCanLogFormatCSV ? "csv" : "bin"; + if (loggingEnabled && currentFilename[0] != '\0') { doc["currentFile"] = String(currentFilename); } else { @@ -2925,12 +3060,20 @@ void setup() { mcp2515.reset(); delay(100); + // β loadSettings()μμ μ΄λ―Έ λΆλ¬μμΌλ―λ‘ μ€λ³΅ μ κ±° mcp2515.setBitrate(currentCanSpeed, MCP_8MHZ); delay(10); - mcp2515.setListenOnlyMode(); - //currentMcpMode = MCP_MODE_LISTEN_ONLY; - currentMcpMode =(MCP2515Mode)preferences.getInt("mcp_mode", 1); - + Serial.printf("π§ Setup: MCP Mode = %d\n", (int)currentMcpMode); + + // 5. λͺ¨λ μ€μ (Normal/Loopback/Listen Only) + if (currentMcpMode == MCP_MODE_NORMAL) { + mcp2515.setNormalMode(); + } else if (currentMcpMode == MCP_MODE_LOOPBACK) { + mcp2515.setLoopbackMode(); + } else { + mcp2515.setListenOnlyMode(); + } + delay(50); // λ²νΌ ν΄λ¦¬μ΄ @@ -3139,4 +3282,3 @@ void loop() { lastPrint = millis(); } } - diff --git a/index.h b/index.h index 9583775..d6ca756 100644 --- a/index.h +++ b/index.h @@ -971,6 +971,8 @@ const char index_html[] PROGMEM = R"rawliteral( (Text - Excel Ready) + +