From 40399b446e162cce7f448d9413ba31822db9d3d6 Mon Sep 17 00:00:00 2001 From: No-Signal Date: Sun, 29 Dec 2024 13:42:14 +0000 Subject: [PATCH 1/2] Adding ability to log CAN frames to SD card --- Software/Software.ino | 22 +++ Software/USER_SETTINGS.h | 1 + Software/src/communication/can/comm_can.cpp | 9 ++ Software/src/communication/can/comm_can.h | 2 - Software/src/devboard/sdcard/sdcard.cpp | 151 ++++++++++++++++++ Software/src/devboard/sdcard/sdcard.h | 23 +++ Software/src/devboard/utils/types.h | 7 + .../devboard/webserver/can_logging_html.cpp | 6 + Software/src/devboard/webserver/webserver.cpp | 18 +++ 9 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 Software/src/devboard/sdcard/sdcard.cpp create mode 100644 Software/src/devboard/sdcard/sdcard.h diff --git a/Software/Software.ino b/Software/Software.ino index 60cc30d2..306bd994 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -18,6 +18,7 @@ #include "src/communication/rs485/comm_rs485.h" #include "src/communication/seriallink/comm_seriallink.h" #include "src/datalayer/datalayer.h" +#include "src/devboard/sdcard/sdcard.h" #include "src/devboard/utils/events.h" #include "src/devboard/utils/led_handler.h" #include "src/devboard/utils/logging.h" @@ -78,12 +79,16 @@ MyTimer core_task_timer_10s(INTERVAL_10_S); int64_t connectivity_task_time_us; MyTimer connectivity_task_timer_10s(INTERVAL_10_S); +int64_t logging_task_time_us; +MyTimer logging_task_timer_10s(INTERVAL_10_S); + MyTimer loop_task_timer_10s(INTERVAL_10_S); MyTimer check_pause_2s(INTERVAL_2_S); TaskHandle_t main_loop_task; TaskHandle_t connectivity_loop_task; +TaskHandle_t logging_loop_task; Logging logging; @@ -98,6 +103,11 @@ void setup() { TASK_CONNECTIVITY_PRIO, &connectivity_loop_task, WIFI_CORE); #endif +#ifdef LOG_CAN_TO_SD + xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, &logging_task_time_us, + TASK_CONNECTIVITY_PRIO, &logging_loop_task, WIFI_CORE); +#endif + init_events(); init_CAN(); @@ -137,6 +147,18 @@ void loop() { #endif } +#ifdef LOG_CAN_TO_SD +void logging_loop(void* task_time_us) { + + init_logging_buffer(); + init_sdcard(); + + while (true) { + write_can_frame_to_sdcard(); + } +} +#endif + #ifdef WIFI void connectivity_loop(void* task_time_us) { diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index a73799c5..bacd3d9a 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -73,6 +73,7 @@ #endif //#define DEBUG_CAN_DATA //Enable this line to print incoming/outgoing CAN & CAN-FD messages to USB serial (WARNING, raises CPU load, do not use for production) +//#define LOG_CAN_TO_SD //Enable this line to log incoming/outgoing CAN & CAN-FD messages to SD card //#define INTERLOCK_REQUIRED //Nissan LEAF specific setting, if enabled requires both high voltage conenctors to be seated before starting //#define CAN_ADDON //Enable this line to activate an isolated secondary CAN Bus using add-on MCP2515 chip (Needed for some inverters / double battery) #define CRYSTAL_FREQUENCY_MHZ 8 //CAN_ADDON option, what is your MCP2515 add-on boards crystal frequency? diff --git a/Software/src/communication/can/comm_can.cpp b/Software/src/communication/can/comm_can.cpp index 8fa2ab3d..4a04959d 100644 --- a/Software/src/communication/can/comm_can.cpp +++ b/Software/src/communication/can/comm_can.cpp @@ -1,5 +1,6 @@ #include "comm_can.h" #include "../../include.h" +#include "src/devboard/sdcard/sdcard.h" // Parameters @@ -107,6 +108,10 @@ void transmit_can(CAN_frame* tx_frame, int interface) { } print_can_frame(*tx_frame, frameDirection(MSG_TX)); +#ifdef LOG_CAN_TO_SD + add_can_frame_to_buffer(*tx_frame, frameDirection(MSG_TX)); +#endif + switch (interface) { case CAN_NATIVE: CAN_frame_t frame; @@ -186,6 +191,10 @@ void send_can() { void receive_can(CAN_frame* rx_frame, int interface) { print_can_frame(*rx_frame, frameDirection(MSG_RX)); +#ifdef LOG_CAN_TO_SD + add_can_frame_to_buffer(*rx_frame, frameDirection(MSG_RX)); +#endif + if (interface == can_config.battery) { receive_can_battery(*rx_frame); #ifdef CHADEMO_BATTERY diff --git a/Software/src/communication/can/comm_can.h b/Software/src/communication/can/comm_can.h index 48e3c9c3..38ca2da8 100644 --- a/Software/src/communication/can/comm_can.h +++ b/Software/src/communication/can/comm_can.h @@ -15,8 +15,6 @@ #include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h" #endif //CANFD_ADDON -enum frameDirection { MSG_RX, MSG_TX }; //RX = 0, TX = 1 - /** * @brief Initialization function for CAN. * diff --git a/Software/src/devboard/sdcard/sdcard.cpp b/Software/src/devboard/sdcard/sdcard.cpp new file mode 100644 index 00000000..9cb2ff61 --- /dev/null +++ b/Software/src/devboard/sdcard/sdcard.cpp @@ -0,0 +1,151 @@ +#include "sdcard.h" +#include "freertos/ringbuf.h" + +File can_log_file; +RingbufHandle_t can_bufferHandle; + +bool can_logging_paused = false; +bool can_file_open = false; +bool delete_can_file = false; +bool sd_card_active = false; + +void delete_can_log() { + can_logging_paused = true; + delete_can_file = true; +} + +void resume_can_writing() { + can_logging_paused = false; + can_log_file = SD.open(CAN_LOG_FILE, FILE_APPEND); + can_file_open = true; +} + +void pause_can_writing() { + can_logging_paused = true; +} + +void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir) { + + if (!sd_card_active) + return; + + CAN_log_frame log_frame = {frame, msgDir}; + if (xRingbufferSend(can_bufferHandle, &log_frame, sizeof(log_frame), 0) != pdTRUE) { + Serial.println("Failed to send CAN frame to ring buffer!"); + return; + } +} + +void write_can_frame_to_sdcard() { + + if (!sd_card_active) + return; + + size_t receivedMessageSize; + CAN_log_frame* log_frame = + (CAN_log_frame*)xRingbufferReceive(can_bufferHandle, &receivedMessageSize, pdMS_TO_TICKS(10)); + + if (log_frame != NULL) { + + if (can_logging_paused) { + if (can_file_open) { + can_log_file.close(); + can_file_open = false; + } + if (delete_can_file) { + SD.remove(CAN_LOG_FILE); + delete_can_file = false; + can_logging_paused = false; + } + vRingbufferReturnItem(can_bufferHandle, (void*)log_frame); + return; + } + + if (can_file_open == false) { + can_log_file = SD.open(CAN_LOG_FILE, FILE_APPEND); + can_file_open = true; + } + + uint8_t i = 0; + can_log_file.print("("); + can_log_file.print(millis() / 1000.0); + (log_frame->direction == MSG_RX) ? can_log_file.print(") RX0 ") : can_log_file.print(") TX1 "); + can_log_file.print(log_frame->frame.ID, HEX); + can_log_file.print(" ["); + can_log_file.print(log_frame->frame.DLC); + can_log_file.print("] "); + for (i = 0; i < log_frame->frame.DLC; i++) { + can_log_file.print(log_frame->frame.data.u8[i] < 16 ? "0" : ""); + can_log_file.print(log_frame->frame.data.u8[i], HEX); + if (i < log_frame->frame.DLC - 1) + can_log_file.print(" "); + } + can_log_file.println(""); + + vRingbufferReturnItem(can_bufferHandle, (void*)log_frame); + } +} + +void init_logging_buffer() { + can_bufferHandle = xRingbufferCreate(64 * 1024, RINGBUF_TYPE_BYTEBUF); + if (can_bufferHandle == NULL) { + Serial.println("Failed to create CAN ring buffer!"); + return; + } +} + +void init_sdcard() { + + pinMode(SD_CS_PIN, OUTPUT); + digitalWrite(SD_CS_PIN, HIGH); + pinMode(SD_SCLK_PIN, OUTPUT); + pinMode(SD_MOSI_PIN, OUTPUT); + pinMode(SD_MISO_PIN, INPUT); + + SPI.begin(SD_SCLK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN); + if (!SD.begin(SD_CS_PIN)) { + Serial.println("SD Card initialization failed!"); + return; + } + + Serial.println("SD Card initialization successful."); + sd_card_active = true; + + print_sdcard_details(); +} + +void print_sdcard_details() { + + Serial.print("SD Card Type: "); + switch (SD.cardType()) { + case CARD_MMC: + Serial.println("MMC"); + break; + case CARD_SD: + Serial.println("SD"); + break; + case CARD_SDHC: + Serial.println("SDHC"); + break; + case CARD_UNKNOWN: + Serial.println("UNKNOWN"); + break; + case CARD_NONE: + Serial.println("No SD Card found"); + break; + } + + if (SD.cardType() != CARD_NONE) { + Serial.print("SD Card Size: "); + Serial.print(SD.cardSize() / 1024 / 1024); + Serial.println(" MB"); + + Serial.print("Total space: "); + Serial.print(SD.totalBytes() / 1024 / 1024); + Serial.println(" MB"); + + Serial.print("Used space: "); + Serial.print(SD.usedBytes() / 1024 / 1024); + Serial.println(" MB"); + } +} diff --git a/Software/src/devboard/sdcard/sdcard.h b/Software/src/devboard/sdcard/sdcard.h new file mode 100644 index 00000000..0f792358 --- /dev/null +++ b/Software/src/devboard/sdcard/sdcard.h @@ -0,0 +1,23 @@ +#ifndef SDCARD_H +#define SDCARD_H + +#include +#include +#include "../../communication/can/comm_can.h" +#include "../hal/hal.h" + +#define CAN_LOG_FILE "/canlog.txt" + +void init_logging_buffer(); + +void init_sdcard(); +void print_sdcard_details(); + +void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir); +void write_can_frame_to_sdcard(); + +void pause_can_writing(); +void resume_can_writing(); +void delete_can_log(); + +#endif diff --git a/Software/src/devboard/utils/types.h b/Software/src/devboard/utils/types.h index 126aff26..d5cbf2c7 100644 --- a/Software/src/devboard/utils/types.h +++ b/Software/src/devboard/utils/types.h @@ -51,6 +51,13 @@ typedef struct { } data; } CAN_frame; +enum frameDirection { MSG_RX, MSG_TX }; //RX = 0, TX = 1 + +typedef struct { + CAN_frame frame; + frameDirection direction; +} CAN_log_frame; + std::string getBMSStatus(bms_status_enum status); #endif diff --git a/Software/src/devboard/webserver/can_logging_html.cpp b/Software/src/devboard/webserver/can_logging_html.cpp index 77f1975e..e64de232 100644 --- a/Software/src/devboard/webserver/can_logging_html.cpp +++ b/Software/src/devboard/webserver/can_logging_html.cpp @@ -24,6 +24,9 @@ String can_logger_processor(const String& var) { content += ""; content += " "; content += " "; +#ifdef LOG_CAN_TO_SD + content += " "; +#endif content += ""; // Start a new block for the CAN messages @@ -52,6 +55,9 @@ String can_logger_processor(const String& var) { content += "