mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Adding ability to log CAN frames to SD card
This commit is contained in:
parent
47c99f9c3a
commit
40399b446e
9 changed files with 237 additions and 2 deletions
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
151
Software/src/devboard/sdcard/sdcard.cpp
Normal file
151
Software/src/devboard/sdcard/sdcard.cpp
Normal file
|
@ -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");
|
||||
}
|
||||
}
|
23
Software/src/devboard/sdcard/sdcard.h
Normal file
23
Software/src/devboard/sdcard/sdcard.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef SDCARD_H
|
||||
#define SDCARD_H
|
||||
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
#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
|
|
@ -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
|
||||
|
|
|
@ -24,6 +24,9 @@ String can_logger_processor(const String& var) {
|
|||
content += "</style>";
|
||||
content += "<button onclick='refreshPage()'>Refresh data</button> ";
|
||||
content += "<button onclick='exportLog()'>Export to .txt</button> ";
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
content += "<button onclick='deleteLogFile()'>Delete log file</button> ";
|
||||
#endif
|
||||
content += "<button onclick='stopLoggingAndGoToMainPage()'>Back to main page</button>";
|
||||
|
||||
// Start a new block for the CAN messages
|
||||
|
@ -52,6 +55,9 @@ String can_logger_processor(const String& var) {
|
|||
content += "<script>";
|
||||
content += "function refreshPage(){ location.reload(true); }";
|
||||
content += "function exportLog() { window.location.href = '/export_can_log'; }";
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
content += "function deleteLogFile() { window.location.href = '/delete_can_log'; }";
|
||||
#endif
|
||||
content += "function stopLoggingAndGoToMainPage() {";
|
||||
content += " fetch('/stop_can_logging').then(() => window.location.href = '/');";
|
||||
content += "}";
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../../datalayer/datalayer.h"
|
||||
#include "../../datalayer/datalayer_extended.h"
|
||||
#include "../../lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
||||
#include "../sdcard/sdcard.h"
|
||||
#include "../utils/events.h"
|
||||
#include "../utils/led_handler.h"
|
||||
#include "../utils/timer.h"
|
||||
|
@ -78,6 +79,7 @@ void init_webserver() {
|
|||
request->send_P(200, "text/plain", "Logging stopped");
|
||||
});
|
||||
|
||||
#ifndef LOG_CAN_TO_SD
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String logs = String(datalayer.system.info.logged_can_messages);
|
||||
|
@ -104,6 +106,22 @@ void init_webserver() {
|
|||
response->addHeader("Content-Disposition", String("attachment; filename=\"") + String(filename) + "\"");
|
||||
request->send(response);
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
pause_can_writing();
|
||||
request->send(SD, CAN_LOG_FILE, String(), true);
|
||||
resume_can_writing();
|
||||
});
|
||||
|
||||
// Define the handler to delete can log
|
||||
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
delete_can_log();
|
||||
request->send_P(200, "text/plain", "Log file deleted");
|
||||
});
|
||||
#endif
|
||||
|
||||
// Define the handler to export debug log
|
||||
server.on("/export_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue