/** * @file can.cpp * * @brief Implementation file for CAN-related functions in the ChainLube application. * * This file contains the implementation of functions related to CAN (Controller Area Network) * communication within the ChainLube application. It includes the initialization of the CAN module, * setup of masks and filters, and processing of CAN messages. Additionally, a debug message function * is included if CAN debugging is enabled. * * @author Your Name * @date Date */ #include "can.h" MCP_CAN CAN0(GPIO_CS_CAN); #ifdef CAN_DEBUG_MESSAGE #define MAX_DEBUG_RETRIES 100 void sendCANDebugMessage(); #endif /** * @brief Initializes the CAN module, sets masks, and filters based on the configured CAN source. * * This function initializes the CAN module, sets masks and filters based on the configured CAN source * in the application settings, and sets the CAN module in normal mode for communication. */ void Init_CAN() { if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK) MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true); CAN0.init_Mask(0, 0, 0x07FF0000); // Init first mask... CAN0.init_Mask(1, 0, 0x07FF0000); // Init second mask... switch (LubeConfig.CANSource) { case KTM_890_ADV_R_2021: CAN0.init_Filt(0, 0, 0x012D0000); // Init first filter... break; case KTM_1290_SD_R_2023: CAN0.init_Filt(0, 0, 0x012D0000); // Init first filter... break; default: break; } CAN0.setMode(MCP_NORMAL); } /** * @brief Processes CAN messages and sends a CAN debug message periodically. * * This function processes CAN messages and sends a CAN debug message periodically based on a time interval. */ void CAN_Process() { static uint32_t previousMillis = 0; if (millis() - previousMillis >= 100) { sendCANDebugMessage(); previousMillis = millis(); } } /** * @brief Processes CAN messages to determine the wheel speed based on the configured CAN source. * * This function reads incoming CAN messages and extracts the rear wheel speed information. * The wheel speed is then converted to millimeters per second based on the configured CAN source. * The function also monitors the CAN signal for potential issues and triggers diagnostic trouble codes (DTCs). * * @return The calculated distance traveled in millimeters since the last call. */ uint32_t Process_CAN_WheelSpeed() { #define FACTOR_RWP_KMH_890ADV 18 // Divider to convert Raw Data to km/h #define FACTOR_RWP_KMH_1290SD 18 // Divider to convert Raw Data to km/h can_frame canMsg; static uint32_t lastRecTimestamp = 0; uint16_t RearWheelSpeed_raw; uint32_t milimeters_to_add = 0; uint32_t RWP_millimeter_per_second = 0; if (CAN0.readMsgBuf(&canMsg.can_id, &canMsg.can_dlc, canMsg.data) == CAN_OK) { switch (LubeConfig.CANSource) { case KTM_890_ADV_R_2021: // raw / FACTOR_RWP_KMH_890ADV -> km/h * 100000 -> cm/h / 3600 -> cm/s // raw * 500 -> cm/s RearWheelSpeed_raw = (uint16_t)canMsg.data[5] << 8 | canMsg.data[6]; RWP_millimeter_per_second = (((uint32_t)RearWheelSpeed_raw * 1000000) / FACTOR_RWP_KMH_890ADV) / 3600; break; case KTM_1290_SD_R_2023: // raw / FACTOR_RWP_KMH_1290SD -> km/h * 100000 -> cm/h / 3600 -> cm/s // raw * 500 -> cm/s RearWheelSpeed_raw = (uint16_t)canMsg.data[5] << 8 | canMsg.data[6]; RWP_millimeter_per_second = (((uint32_t)RearWheelSpeed_raw * 1000000) / FACTOR_RWP_KMH_1290SD) / 3600; break; default: break; } uint32_t timesincelast = millis() - lastRecTimestamp; lastRecTimestamp = millis(); milimeters_to_add = (RWP_millimeter_per_second * timesincelast) / 1000; } if (lastRecTimestamp > 1000) { MaintainDTC(DTC_NO_CAN_SIGNAL, (millis() > lastRecTimestamp + 10000 ? true : false)); } return milimeters_to_add; } #ifdef CAN_DEBUG_MESSAGE /** * @brief Sends periodic CAN debug messages for monitoring and diagnostics. * * This function sends periodic CAN debug messages containing various system information for monitoring and diagnostics. * The information includes system status, timestamps, tank percentage, DTC flags, and other relevant data. * The debug messages are sent with a configurable multiplexer to broadcast different types of information in each cycle. */ void sendCANDebugMessage() { #define MAX_DEBUG_MULTIPLEXER 6 static uint16_t DebugSendFailTimeout = 0; static uint8_t debugMultiplexer = 0; byte data[8] = {debugMultiplexer, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint32_t millisValue = millis(); switch (debugMultiplexer) { case 0: memcpy(&data[1], &millisValue, sizeof(millisValue)); memcpy(&data[5], &globals.purgePulses, sizeof(globals.purgePulses)); break; case 1: data[1] = (uint8_t)globals.systemStatus; data[2] = (uint8_t)globals.resumeStatus; data[3] = (uint8_t)globals.requestEEAction; data[4] = globals.TankPercentage; data[5] = (0x01 & globals.hasDTC) | ((0x01 & globals.measurementActive) << 1); break; case 2: memcpy(&data[1], &globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress)); memcpy(&data[3], &PersistenceData.tankRemain_microL, sizeof(PersistenceData.tankRemain_microL)); break; case 3: memcpy(&data[1], &PersistenceData.writeCycleCounter, sizeof(PersistenceData.writeCycleCounter)); memcpy(&data[3], &PersistenceData.TravelDistance_highRes_mm, sizeof(PersistenceData.TravelDistance_highRes_mm)); break; case 4: memcpy(&data[1], &PersistenceData.odometer_mm, sizeof(PersistenceData.odometer_mm)); break; case 5: memcpy(&data[1], &PersistenceData.odometer, sizeof(PersistenceData.odometer)); break; case 6: memcpy(&data[1], &PersistenceData.checksum, sizeof(PersistenceData.checksum)); break; default: break; } debugMultiplexer++; debugMultiplexer = debugMultiplexer > MAX_DEBUG_MULTIPLEXER ? 0 : debugMultiplexer; if (DebugSendFailTimeout < MAX_DEBUG_RETRIES) { byte sndStat = CAN0.sendMsgBuf(0x7FF, 0, 8, data); if (sndStat != CAN_OK) { Debug_pushMessage("failed sending CAN-DbgMsg: %d, %d\n", sndStat, DebugSendFailTimeout); DebugSendFailTimeout++; } } else if (DebugSendFailTimeout == MAX_DEBUG_RETRIES) { Debug_pushMessage("disable CAN-DbgMsg due to timeout"); DebugSendFailTimeout++; } } #endif