diff --git a/G26-Telemetria.ino b/G26-Telemetria.ino index 271da27..28b1e07 100644 --- a/G26-Telemetria.ino +++ b/G26-Telemetria.ino @@ -1,48 +1,52 @@ -#include "include/data_processor.hpp" + +#include +#include +#include "SdFat.h" #include "include/can.hpp" -#include "include/g24_wheel_buttons.hpp" -#include "include/led_strip.hpp" -#include "include/crowpanel_controller.hpp" +#include "include/data_processor.hpp" -#include -#include +// --- CONFIGURACIÓN SD (VSPI) --- +#define SD_CS_PIN 5 +#define SPI_CLOCK SD_SCK_MHZ(20) +SdFat sd; +SdFile logFile; -DataProcessor dataProcessor; -CAN canController; -G24WheelButtons wheelButtons; -LedStrip ledStrip; -CrowPanelController crowPanelController; - -// Screen rotation variables -unsigned long lastScreenChange = 0; -int currentScreen = 1; -int screenCycle = 0; // 0 = screen1, 1 = screen2, 2 = screen3, 3 = screen4 +// Instancias +CAN can_interface; +DataProcessor processor; void setup() { Serial.begin(115200); - while (!Serial) { delay(10); } - Serial.println("Starting setup..."); - canController.set_data_proccessor(&dataProcessor); - dataProcessor.set_led_strip(&ledStrip); - dataProcessor.set_crow_panel_controller(&crowPanelController); - // wheelButtons.set_led_strip(&ledStrip); - // wheelButtons.set_can_controller(&canController); - // wheelButtons.set_data_processor(&dataProcessor); - // ledStrip.set_mutex(canController.get_mutex()); + delay(1000); + Serial.println("\n--- G26 TELEMETRY: INICIO DE SISTEMA ---"); - canController.start(); - canController.start_listening_task(); - + // 1. INICIALIZACIÓN SD + if (!sd.begin(SD_CS_PIN, SPI_CLOCK)) { + Serial.println("[FALLO] SD no detectada. El sistema continuará sin Datalogging."); + } else { + Serial.println("[OK] SD Montada."); + if (!logFile.exists("G26.csv")) { + if (logFile.open("G26.csv", O_RDWR | O_CREAT | O_AT_END)) { + // SOLO Cabeceras de lo que vamos a grabar ahora + logFile.println("Time,ECT"); + logFile.close(); + } + } + } - // wheelButtons.begin(); - - // xTaskCreate(wheelButtons.updateTask, "updateTask", 4096, &wheelButtons, 1, NULL); + // 2. VINCULACIÓN + // Le damos al procesador acceso a la SD para que guarde cuando lleguen datos + processor.setLogSystem(&sd, &logFile); + can_interface.set_data_proccessor(&processor); + + // 3. INICIO CAN + can_interface.start(); + can_interface.start_listening_task(); // Escucha en Core 1 (Background) - // Initialize with screen 1 - lastScreenChange = millis(); + Serial.println("[OK] Sistema ONLINE."); } -void loop(){ - lv_timer_handler(); - vTaskDelay(5); +void loop() { + + delay(100); } \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 0bda7bb..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -SD \ No newline at end of file diff --git a/include/common/common_libraries.hpp b/include/common/common_libraries.hpp index f03e7c4..de54e53 100644 --- a/include/common/common_libraries.hpp +++ b/include/common/common_libraries.hpp @@ -2,6 +2,7 @@ #define COMMON_LIBRARIES_HPP #include +#include "SdFat.h" #include "time.h" #include #include diff --git a/include/data_processor.hpp b/include/data_processor.hpp index 0523555..abbcf77 100644 --- a/include/data_processor.hpp +++ b/include/data_processor.hpp @@ -1,38 +1,33 @@ #ifndef DATAPROCESSOR_HPP #define DATAPROCESSOR_HPP -#include "common/common_libraries.hpp" -#include "common/display_id.hpp" -#include "led_strip.hpp" -#include "crowpanel_controller.hpp" - -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" +#include +#include "SdFat.h" +#include class DataProcessor { public: DataProcessor() = default; - char* process(std::vector data); - void send_serial(byte type, unsigned int value); - void send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int ecth, int ectl, int gear); - void send_serial_frame_1(int lfws, int rfws, int lrws, int rrws, int maph, int mapl, int ect); - void send_serial_frame_2(int lambh, int lambl, int lamth, int lamtl, int bvolth, int bvoltl, int iat); - void send_serial_frame_3(int aux1, int aux2, int aux3, int aux4, int aux5, int aux6, int aux7); - void send_serial_frame_4(int aux1, int aux2, int aux3, int aux4, int aux5, int aux6, int aux7); - void send_serial_change_display(int display); - void send_serial_screen_test(int test); - void set_led_strip(LedStrip *led_strip){ - _led_strip = led_strip; - } - void set_crow_panel_controller(CrowPanelController *crow_panel_controller) { - _crow_panel_controller = crow_panel_controller; + + // Configuración SD + void setLogSystem(SdFat* sd_inst, SdFile* file_inst) { + _sd = sd_inst; + _logFile = file_inst; } + void send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int vbatth, int vbattl, int ect); + + void send_serial_frame_1(int lmbh, int lmbl, int lmbth, int lmbtl, int fuelh, int fuell, int gear); + void send_serial_frame_2(int shut, int fan, int lmbch, int lmbcl, int brakeh, int brakel, int aux1); + void send_serial_frame_3(int aux3, int aux4, int aux5, int aux6, int aux7, int aux8, int dig1); + void send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, int dig7, int dig8, int dig9); + private: - LedStrip *_led_strip; - CrowPanelController *_crow_panel_controller; - int current_display=0; - bool change_screen_requested=false; + SdFat* _sd; + SdFile* _logFile; + CarState car; + + void flushToSD(); // Guardado físico }; #endif \ No newline at end of file diff --git a/src/data_processor.cpp b/src/data_processor.cpp index fcf6e74..83a9191 100644 --- a/src/data_processor.cpp +++ b/src/data_processor.cpp @@ -1,142 +1,37 @@ -/** - * @file data_processor.cpp - * @author Raúl Arcos Herrera - * @brief This file contains the implementation of the Data Processor class for Link G4+ ECU. - */ - #include "../include/data_processor.hpp" -void DataProcessor::send_serial(byte type, unsigned int value) { //Como parámetros se pasan el ID (type), que es el ID establecido al inicio del código para el dato que se quiera enviar. Ej: RPM_ID -> 0x51; y se envía el valor de dicho dato. - byte dato[8] = { 0x5A, 0xA5, 0x05, 0x82, 0x00, 0x00, 0x00, 0x00 }; //Se establece un arreglo de bytes con los primeros datos necesarios para que la pantalla lo interprete como mensaje (En la Wiki hay tutoriales que lo explican a fondo), como ser la longitud y el tipo de mensaje. - dato[4] = type; //Se configura en el mensaje el ID correspondiente al dato a enviar. - dato[6] = (value >> 8) & 0xFF; //Se configura el dato en los últimos 2 bytes. - dato[7] = value & 0xFF; - - Serial.write(dato, 8); //Se envía serialmente el mensaje, indicando su longituden bytes para ello. -} //RPM + TPS + vBatt + ECT void DataProcessor::send_serial_frame_0(int rpmh, int rpml, int tpsh, int tpsl, int vbatth, int vbattl, int ect){ - Serial.println("send_serial_frame_0"); - int rpm = (rpmh * 256) + rpml; int tps = (tpsh * 256) + tpsl; double vbatt = ((vbatth * 256) + vbattl) / 100.0; - _crow_panel_controller->set_value_to_label(ui_rpm, rpm); - _crow_panel_controller->set_value_to_label(ui_battvolt, vbatt); - _crow_panel_controller->set_value_to_label(ui_ect, ect); - _crow_panel_controller->set_value_to_label(ui_ect2, ect); - - // Update RPM LED bar (8000-12500 RPM range) - _crow_panel_controller->update_rpm_bar(rpm); - - // Battery voltage color (typical car battery: 12.6V resting, 13.2-14.4V running) - if (vbatt < 11.5) { - _crow_panel_controller->set_label_color(ui_battvolt, CrowPanelController::COLOR_CRITICAL); // Red for low - } else if (vbatt < 12.0) { - _crow_panel_controller->set_label_color(ui_battvolt, CrowPanelController::COLOR_WARNING); // Yellow for warning - } else if (vbatt > 15.0) { - _crow_panel_controller->set_label_color(ui_battvolt, CrowPanelController::COLOR_WARNING); // Yellow for overcharge - } else { - _crow_panel_controller->set_label_color(ui_battvolt, CrowPanelController::COLOR_NORMAL); // Green for good - } - - //El numero que muestra la temperatura siempre será blanco - _crow_panel_controller->set_label_color(ui_ect, CrowPanelController::COLOR_PANEL_DEFAULT); - _crow_panel_controller->set_label_color(ui_ect2, CrowPanelController::COLOR_PANEL_DEFAULT); - - // Engine coolant temperature (typical range: 80-105°C normal operating temp) - if (ect > 105) { - // Crítico: Rojo - _crow_panel_controller->set_panel_color(ui_PanelETC, CrowPanelController::COLOR_CRITICAL); - } else if (ect >= 95) { - // Advertencia: Amarillo (95 a 105) - _crow_panel_controller->set_panel_color(ui_PanelETC, CrowPanelController::COLOR_WARNING); - } else if (ect >= 65) { - //Temperatura Ideal: Verde (65 a 94) - _crow_panel_controller->set_panel_color(ui_PanelETC, CrowPanelController::COLOR_GOOD); - } else { // etc <= 60 Azul - _crow_panel_controller->set_panel_color(ui_PanelETC, CrowPanelController::COLOR_BLUE); - } + // 2. Escribimos en la SD + flushToSD(); } + + //LAMB + LAMBTRG + FUEL + GEAR void DataProcessor::send_serial_frame_1(int lmbh, int lmbl, int lmbth, int lmbtl, int fuelh, int fuell, int gear){ - Serial.println("send_serial_frame_1"); - int lmb = (lmbh * 256) + lmbl; - int lmbtrg = (lmbth * 256) + lmbtl; - int fuel = (fuelh * 256) + fuell; - _crow_panel_controller->set_value_to_label(ui_lambda, lmb); - _crow_panel_controller->set_value_to_label(ui_lambdatarget, lmbtrg); - _crow_panel_controller->set_value_to_label(ui_fuel, fuel); -// _crow_panel_controller->set_value_to_label(ui_gear, gear); + + int lmb = (lmbh * 256) + lmbl; + int lmbtrg = (lmbth * 256) + lmbtl; + int fuel = (fuelh * 256) + fuell; + } void DataProcessor::send_serial_frame_2(int shut, int fan, int lmbch, int lmbcl, int brakeh, int brakel, int aux1){ - Serial.println("send_serial_frame_2"); int lmbcorrect = (lmbch * 256) + lmbcl; int brake = (brakeh * 256) + brakel; char shut_str[10]; char fan_str[10]; char aux1_str[10]; - - if (shut == 3){ - strcpy(shut_str, "ON"); - } else { - strcpy(shut_str, "OFF"); - } - - if (fan == 1){ - strcpy(fan_str, "ON"); - } else { - strcpy(fan_str, "OFF"); - } - - if (aux1 == 1){ - strcpy(aux1_str, "N"); - _crow_panel_controller->set_label_color(ui_PanelGear, CrowPanelController::COLOR_GOOD); - } else { - strcpy(aux1_str, "D"); - _crow_panel_controller->set_label_color(ui_PanelGear, CrowPanelController::COLOR_PANEL_DEFAULT); - } - - - - _crow_panel_controller->set_string_to_label(ui_shutdown, shut_str); - _crow_panel_controller->set_string_to_label(ui_fan, fan_str); - _crow_panel_controller->set_value_to_label(ui_correctionlambda, lmbcorrect); - _crow_panel_controller->set_value_to_label(ui_auxstatus9, brake); - _crow_panel_controller->set_string_to_label(ui_gear, aux1_str); - - // Shutdown status color - if (shut == 3) { - _crow_panel_controller->set_label_color(ui_shutdown, CrowPanelController::COLOR_CRITICAL); // Red when shutdown is ON (emergency) - } else { - _crow_panel_controller->set_label_color(ui_shutdown, CrowPanelController::COLOR_GOOD); // Green when shutdown is OFF (normal) - } - - // Fan status color - if (fan == 1) { - _crow_panel_controller->set_label_color(ui_fan, CrowPanelController::COLOR_BLUE); // Blue when fan is ON (cooling) - } else { - _crow_panel_controller->set_label_color(ui_fan, CrowPanelController::COLOR_NORMAL); // White when fan is OFF - } - - // Brake pressure color (assuming brake > 0 means brakes applied) - if (brake > 100) { // Adjust threshold as needed - _crow_panel_controller->set_label_color(ui_auxstatus9, CrowPanelController::COLOR_WARNING); // Yellow for heavy braking - } else if (brake > 0) { - _crow_panel_controller->set_label_color(ui_auxstatus9, CrowPanelController::COLOR_NORMAL); // White for light braking - } else { - _crow_panel_controller->set_label_color(ui_auxstatus9, CrowPanelController::COLOR_GOOD); // Green for no braking - } } - void DataProcessor::send_serial_frame_3(int aux3, int aux4, int aux5, int aux6, int aux7, int aux8, int dig1){ - Serial.println("send_serial_frame_3"); char aux3_str[10]; char aux4_str[10]; @@ -188,42 +83,9 @@ void DataProcessor::send_serial_frame_3(int aux3, int aux4, int aux5, int aux6, } else { strcpy(dig1_str, "OFF"); } - - _crow_panel_controller -> set_string_to_label(ui_auxstatus3, aux3_str); - if(aux3 == 1 && change_screen_requested == false){ - switch(current_display){ - case 0: - _crow_panel_controller->change_screen(ui_Screen1); - break; - case 1: - _crow_panel_controller->change_screen(ui_Screen2); - break; - case 2: - _crow_panel_controller->change_screen(ui_Screen3); - break; - case 3: - _crow_panel_controller->change_screen(ui_Screen4); - break; - } - current_display++; - change_screen_requested = true; - if(current_display > 3){ - current_display = 0; - } - }else if(aux3 == 0 && change_screen_requested == true){ - change_screen_requested = false; - } - - _crow_panel_controller -> set_string_to_label(ui_auxstatus4, aux4_str); - _crow_panel_controller -> set_string_to_label(ui_auxstatus5, aux5_str); - _crow_panel_controller -> set_string_to_label(ui_auxstatus6, aux6_str); - _crow_panel_controller -> set_string_to_label(ui_auxstatus7, aux7_str); - _crow_panel_controller -> set_string_to_label(ui_auxstatus8, aux8_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus1, dig1_str); } void DataProcessor::send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, int dig7, int dig8, int dig9){ - Serial.println("send_serial_frame_4"); char dig3_str[10]; char dig4_str[10]; @@ -275,16 +137,21 @@ void DataProcessor::send_serial_frame_4(int dig3, int dig4, int dig5, int dig6, strcpy(dig9_str, "OFF"); } - _crow_panel_controller -> set_string_to_label(ui_digitalstatus3, dig3_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus4, dig4_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus5, dig5_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus6, dig6_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus7, dig7_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus8, dig8_str); - _crow_panel_controller -> set_string_to_label(ui_digitalstatus9, dig9_str); } -void DataProcessor::send_serial_screen_test(int test) { - _crow_panel_controller->set_value_to_label(ui_rpm, test); - Serial.println(test); +// ESCRITURA EN SD +void DataProcessor::flushToSD() { + // Solo escribe si la tarjeta está lista + if (_sd && _logFile && _sd->card()) { + + // Modo APPEND + if (_logFile->open("G26.csv", O_RDWR | O_CREAT | O_AT_END)) { + + _logFile->print(millis()); + _logFile->print(","); + _logFile->println(ect); + + _logFile->close(); + } + } } \ No newline at end of file