Created
May 15, 2023 04:35
-
-
Save celeron55/a026256329ac4b74bff0b197eea14b6e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <mcp_can.h> | |
#include <SPI.h> | |
#define CAN0_CS 10 /* Set CS to pin 10 */ | |
MCP_CAN CAN0(CAN0_CS); /* Set CS to pin 10 */ | |
// UDS request for DTCs | |
unsigned char stmp[8] = {0x19, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
// Flow control frame | |
unsigned char flowControlFrame[8] = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
// Buffer for multi-frame messages | |
unsigned char multiFrameBuffer[255]; | |
unsigned char multiFrameIndex = 0; | |
unsigned char multiFrameExpectedIndex = 1; // For checking frame sequence | |
// Rate limiter | |
unsigned long lastRequestTime = 0; | |
const unsigned long requestInterval = 2000; // Send request every 2 seconds | |
void setup() { | |
Serial.begin(115200); | |
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) { | |
Serial.println("MCP2515 Initialized Successfully!"); | |
} else { | |
Serial.println("Error Initializing MCP2515..."); | |
} | |
CAN0.setMode(MCP_NORMAL); | |
} | |
void loop() { | |
unsigned char len = 0; | |
unsigned char buf[8]; | |
unsigned long rxId; | |
if (CAN0.readMsgBuf(&rxId, &len, buf) == CAN_OK) { // If message received | |
if (rxId == 0x78C) { // If message is from target ECU | |
// First frame of a multi-frame message | |
if (buf[0] >> 4 == 0x1) { | |
multiFrameIndex = 0; | |
multiFrameExpectedIndex = 1; | |
int numBytes = ((buf[0] & 0x0F) << 8) | buf[1]; | |
for (int i = 2; i < len; i++) { | |
multiFrameBuffer[multiFrameIndex++] = buf[i]; | |
} | |
CAN0.sendMsgBuf(0x784, 0, 8, flowControlFrame); // Send flow control frame | |
} | |
// Consecutive frame | |
else if (buf[0] >> 4 == 0x2) { | |
if ((buf[0] & 0x0F) != multiFrameExpectedIndex) { | |
Serial.println("Received frame out of order"); | |
return; | |
} | |
multiFrameExpectedIndex = (multiFrameExpectedIndex % 0x0F) + 1; | |
for (int i = 1; i < len; i++) { | |
multiFrameBuffer[multiFrameIndex++] = buf[i]; | |
} | |
if (multiFrameExpectedIndex == 0x0F) { | |
// We have received all frames of the multi-frame message | |
printDTCs(multiFrameBuffer, multiFrameIndex); | |
} | |
} | |
// Single frame | |
else if (buf[0] >> 4 == 0x0) { | |
printDTCs(&buf[1], len - 1); | |
} | |
} | |
} else { // If no message is received | |
unsigned long now = millis(); | |
if (now - lastRequestTime > requestInterval) { // If enough time has passed since last request | |
CAN0.sendMsgBuf(0x784, 0, 8, stmp); // Send request to target ECU | |
lastRequestTime = now; // Update last request time | |
} | |
} | |
} | |
// Helper function to print DTCs | |
void printDTCs(unsigned char* data, unsigned char len) { | |
for (int i = 0; i < len; i += 2) { | |
String dtc; | |
// First character | |
switch (data[i] >> 6) { | |
case 0: dtc += 'P'; break; | |
case 1: dtc += 'C'; break; | |
case 2: dtc += 'B'; break; | |
case 3: dtc += 'U'; break; | |
} | |
// Second character | |
dtc += (data[i] & 0x20) ? '1' : '0'; | |
// Third character | |
dtc += String((data[i] & 0x1C) >> 2); | |
// Fourth and fifth characters | |
dtc += String(((data[i] & 0x03) << 2) | ((data[i+1] & 0xC0) >> 6)); | |
dtc += String(data[i+1] & 0x3F); | |
Serial.print("DTC: "); | |
Serial.println(dtc); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment