Skip to content

Instantly share code, notes, and snippets.

@celeron55
Created May 15, 2023 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save celeron55/a026256329ac4b74bff0b197eea14b6e to your computer and use it in GitHub Desktop.
Save celeron55/a026256329ac4b74bff0b197eea14b6e to your computer and use it in GitHub Desktop.
#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