Archivos iniciales añadidos

This commit is contained in:
adrigongv23 2026-02-10 15:00:39 +01:00
parent 7b2267494e
commit dd67d2afdd
8 changed files with 805 additions and 0 deletions

View file

@ -0,0 +1,223 @@
/**
* @file can.cpp
* @author Raúl Arcos Herrera
* @brief This file contains the implementation of the CAN Controller class for Link G4+ ECU.
*/
#include "../include/can.hpp"
static bool driver_installed = false;
void CAN::start() {
Serial.println("Starting CAN Controller...");
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_125KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
esp_err_t install_status = twai_driver_install(&g_config, &t_config, &f_config);
if (install_status != ESP_OK) {
Serial.println("Failed to install TWAI driver");
driver_installed = false;
return;
} else {
Serial.println("TWAI driver installed");
}
esp_err_t start_status = twai_start();
if (start_status != ESP_OK) {
Serial.println("Failed to start TWAI driver");
driver_installed = false;
return;
} else {
Serial.println("TWAI driver started");
}
uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL;
if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
Serial.println("CAN Alerts reconfigured");
} else {
Serial.println("Failed to reconfigure alerts");
driver_installed = false;
return;
}
// TWAI driver is now successfully installed and started
driver_installed = true;
}
CAN::~CAN() {
stop_listening_task();
if (driver_installed) {
twai_stop();
twai_driver_uninstall();
driver_installed = false;
}
}
void CAN::start_listening_task() {
if (_listen_task_handle == NULL) {
_should_stop_listening = false;
BaseType_t result = xTaskCreate(
listenTask, // Task function
"CAN_Listen_Task", // Task name
4096, // Stack size (words)
this, // Task parameter (this CAN instance)
1, // Priority (lowered from 5 to 1)
&_listen_task_handle // Task handle
);
// BaseType_t result = xTaskCreatePinnedToCore(
// listenTask, // Task function
// "CAN_Listen_Task", // Task name
// 4096, // Stack size (words)
// this, // Task parameter (this CAN instance)
// 1, // Priority
// &_listen_task_handle, // Task handle
// 0 // Core 0 (main loop typically runs on Core 1)
// );
if (result == pdPASS) {
Serial.println("CAN listening task created successfully");
} else {
Serial.println("Failed to create CAN listening task");
_listen_task_handle = NULL;
}
} else {
Serial.println("CAN listening task already running");
}
}
void CAN::stop_listening_task() {
if (_listen_task_handle != NULL) {
_should_stop_listening = true;
// Wait for task to finish (max 1 second)
for (int i = 0; i < 100; i++) {
if (_listen_task_handle == NULL) {
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
// Force delete if still running
if (_listen_task_handle != NULL) {
vTaskDelete(_listen_task_handle);
_listen_task_handle = NULL;
}
Serial.println("CAN listening task stopped");
}
}
void CAN::send_frame(twai_message_t message) {
while (xSemaphoreTake(_mutex, portMAX_DELAY) != pdTRUE) {
Serial.println("Retrying to take mutex in send_frame");
}
twai_transmit(&message, pdMS_TO_TICKS(TRANSMIT_RATE_MS));
xSemaphoreGive(_mutex);
}
twai_message_t CAN::createBoolMessage(bool b0, bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7) {
twai_message_t message;
memset(&message, 0, sizeof(message));
message.identifier = 0x001;
message.data[0] = (b7 << 7) | (b6 << 6) | (b5 << 5) | (b4 << 4) |
(b3 << 3) | (b2 << 2) | (b1 << 1) | b0;
message.data_length_code = 8;
message.flags = TWAI_MSG_FLAG_NONE;
return message;
}
void CAN::listen() {
Serial.println("CAN listening task started");
// Continuous loop for the thread
while (!_should_stop_listening) {
if (!driver_installed) {
// Driver not installed
vTaskDelay(pdMS_TO_TICKS(1000));
continue;
}
// Check if alert happened
uint32_t alerts_triggered;
twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(1000)); // Reduced timeout for more responsiveness
twai_status_info_t twaistatus;
twai_get_status_info(&twaistatus);
// Handle alerts
if (alerts_triggered & TWAI_ALERT_ERR_PASS) {
Serial.println("Alert: TWAI controller has become error passive.");
}
if (alerts_triggered & TWAI_ALERT_BUS_ERROR) {
Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.");
Serial.printf("Bus error count: %lu\n", twaistatus.bus_error_count);
}
if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) {
Serial.println("Alert: The RX queue is full causing a received frame to be lost.");
Serial.printf("RX buffered: %lu\t", twaistatus.msgs_to_rx);
Serial.printf("RX missed: %lu\t", twaistatus.rx_missed_count);
Serial.printf("RX overrun %lu\n", twaistatus.rx_overrun_count);
}
if (alerts_triggered & TWAI_ALERT_RX_DATA) {
twai_message_t message;
int message_count = 0;
while (twai_receive(&message, 0) == ESP_OK && !_should_stop_listening) {
bool all_zeros = true;
for (int i = 0; i < message.data_length_code; i++) {
if (message.data[i] != 0) {
all_zeros = false;
break;
}
}
if (all_zeros) {
Serial.println("Ignoring message with all zero data");
taskYIELD();
continue;
}
if (message.extd) {
Serial.println("Extended Format");
} else {
Serial.println("Standard Format");
}
Serial.printf("ID: %lx\nByte:", message.identifier);
if (!(message.rtr)) {
for (int i = 0; i < message.data_length_code; i++) {
Serial.printf(" %d = %02x,", i, message.data[i]);
}
Serial.println("");
// Send to data processor based on first byte (maintaining original logic)
switch (message.data[0]) {
case 0:
_data_processor->send_serial_frame_0(message.data[1], message.data[2], message.data[3], message.data[4], message.data[5], message.data[6], message.data[7]);
break;
case 1:
//_data_processor->send_serial_frame_1(message.data[1], message.data[2], message.data[3], message.data[4], message.data[5], message.data[6], message.data[7]);
break;
case 2:
//_data_processor->send_serial_frame_2(message.data[1], message.data[2], message.data[3], message.data[4], message.data[5], message.data[6], message.data[7]);
break;
case 3:
//_data_processor->send_serial_frame_3(message.data[1], message.data[2], message.data[3], message.data[4], message.data[5], message.data[6], message.data[7]);
default:
break;
}
}
taskYIELD();
}
}
taskYIELD();
vTaskDelay(pdMS_TO_TICKS(5));
}
Serial.println("CAN listening task ending");
_listen_task_handle = NULL;
vTaskDelete(NULL); // Delete this task
}

View file

@ -0,0 +1,251 @@
#include "../include/data_processor.hpp"
char* DataProcessor::process(std::vector<float> data) {
// Implementación del procesamiento de datos si es necesario
return nullptr; // Placeholder
}
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");
this -> current_ect_value = ect; //Actualizamos el valor de ECT para que pueda ser usado por otras clases
//Serial.printf("CAN RX -> ECT: %d \n", ect);
}
/*
//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);
}
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];
char aux5_str[10];
char aux6_str[10];
char aux7_str[10];
char aux8_str[10];
char dig1_str[10];
if (aux3 == 1){
strcpy(aux3_str, "ON");
} else {
strcpy(aux3_str, "OFF");
}
if (aux4 == 1){
strcpy(aux4_str, "ON");
} else {
strcpy(aux4_str, "OFF");
}
if (aux5 == 1){
strcpy(aux5_str, "ON");
} else {
strcpy(aux5_str, "OFF");
}
if (aux6 == 1){
strcpy(aux6_str, "ON");
} else {
strcpy(aux6_str, "OFF");
}
if (aux7 == 1){
strcpy(aux7_str, "ON");
} else {
strcpy(aux7_str, "OFF");
}
if (aux8 == 1){
strcpy(aux8_str, "ON");
} else {
strcpy(aux8_str, "OFF");
}
if (dig1 == 1){
strcpy(dig1_str, "ON");
} 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];
char dig5_str[10];
char dig6_str[10];
char dig7_str[10];
char dig8_str[10];
char dig9_str[10];
if (dig3 == 1){
strcpy(dig3_str, "ON");
} else {
strcpy(dig3_str, "OFF");
}
if (dig4 == 1){
strcpy(dig4_str, "ON");
} else {
strcpy(dig4_str, "OFF");
}
if (dig5 == 1){
strcpy(dig5_str, "ON");
} else {
strcpy(dig5_str, "OFF");
}
if (dig6 == 1){
strcpy(dig6_str, "ON");
} else {
strcpy(dig6_str, "OFF");
}
if (dig7 == 1){
strcpy(dig7_str, "ON");
} else {
strcpy(dig7_str, "OFF");
}
if (dig8 == 1){
strcpy(dig8_str, "ON");
} else {
strcpy(dig8_str, "OFF");
}
if (dig9 == 1){
strcpy(dig9_str, "ON");
} else {
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);
}
*/