Code blocks
Setup Instructions
- Install the CAN library in Arduino IDE: CAN by Sandeep Mistry v0.3.1
- Upload the sketch below to your Arduino or compatible device
- The sketch will automatically detect your MCP2515 crystal frequency (8MHz or 16MHz) and CAN bus speed (125kbps or 500kbps)
Features: This sketch automatically detects your hardware configuration (8MHz or 16MHz crystal, 125kbps or 500kbps bus speed) and supports both reading and writing CAN packets. No manual configuration needed!
#include <CAN.h>
// Configuration - optimized for your head unit
#define CLOCK_FREQ 8E6 // 8 MHz crystal
#define BAUD_RATE 125E3 // 125 kbps baud rate
// Statistics
unsigned long packetsReceived = 0;
unsigned long packetsSent = 0;
unsigned long packetsSuccess = 0;
unsigned long lastActivityReport = 0;
void setup() {
Serial.begin(250000);
while (!Serial);
Serial.println(F("CAN Transceiver Started!"));
// Initialize CAN with verified working configuration
CAN.setClockFrequency(CLOCK_FREQ);
if (!CAN.begin(BAUD_RATE)) {
Serial.println(F("ERROR: CAN init failed!"));
while (1) delay(1000);
}
Serial.println(F("SUCCESS: 8MHz @ 125kbps"));
Serial.println(F("Normal mode - connected to real CAN bus"));
}
// Function to send CAN packet from Serial input
void sendPacketFromSerial(String input) {
input.trim();
if (input.length() == 0) return;
// Split input by commas
char str[input.length() + 1];
input.toCharArray(str, sizeof(str));
char* token = strtok(str, ",");
if (token == NULL) return;
// Parse CAN ID
long id = strtol(token, NULL, 16);
if (id < 0x000 || id > 0x1FFFFFFF) {
Serial.println(F("ERROR: Invalid ID"));
return;
}
// Parse RTR
token = strtok(NULL, ",");
if (token == NULL) return;
bool rtr = atoi(token) > 0;
// Parse IDE
token = strtok(NULL, ",");
if (token == NULL) return;
bool extended = atoi(token) > 0;
// Parse DLC
token = strtok(NULL, ",");
if (token == NULL) return;
int dlc = atoi(token);
if (dlc < 0 || dlc > 8) {
Serial.println(F("ERROR: Invalid DLC"));
return;
}
// Prepare to send CAN packet
byte dataBytes[8];
int dataCount = 0;
// Parse Data Bytes
while ((token = strtok(NULL, ",")) != NULL && dataCount < 8) {
dataBytes[dataCount++] = strtol(token, NULL, 16);
}
// Verify data count matches DLC
if (dataCount != dlc) {
Serial.println(F("ERROR: DLC mismatch"));
return;
}
// Begin packet
if (extended) {
CAN.beginExtendedPacket(id, dlc, rtr);
} else {
CAN.beginPacket(id, dlc, rtr);
}
// Send data bytes if it's NOT an RTR frame
if (!rtr) {
for (int i = 0; i < dataCount; i++) {
CAN.write(dataBytes[i]);
}
}
// Send packet
Serial.print(F("Sending ID=0x"));
Serial.print(id, HEX);
Serial.print(F(" DLC="));
Serial.print(dlc);
Serial.print(F("..."));
packetsSent++;
if (!CAN.endPacket()) {
Serial.println(F(" FAILED!"));
Serial.println(F("ERROR: No ACK from bus"));
} else {
packetsSuccess++;
Serial.println(F(" OK!"));
Serial.print(F("SUCCESS: ID=0x"));
Serial.println(id, HEX);
}
}
// Function to receive CAN packets
void receiveCANPacket() {
int packetSize = CAN.parsePacket();
if (packetSize) {
packetsReceived++;
// Print CAN ID in hexadecimal format
Serial.print(CAN.packetId(), HEX);
Serial.print(",");
// Print RTR (0 = data frame, 1 = remote frame)
if (CAN.packetRtr()) {
Serial.print("1,");
} else {
Serial.print("0,");
}
// Print IDE (0 = standard ID, 1 = extended ID)
if (CAN.packetExtended()) {
Serial.print("1,");
} else {
Serial.print("0,");
}
// Print DLC (data length code)
if (CAN.packetRtr()) {
Serial.print(CAN.packetDlc());
Serial.println();
} else {
Serial.print(packetSize);
// Print data bytes in hexadecimal format
while (CAN.available()) {
Serial.print(",");
Serial.print(CAN.read(), HEX);
}
Serial.println();
}
}
}
void loop() {
// Handle incoming CAN packets
receiveCANPacket();
// Report CAN bus activity every 10 seconds
unsigned long now = millis();
if (now - lastActivityReport > 10000) {
Serial.print(F("INFO: RX packets="));
Serial.println(packetsReceived);
// Show send statistics if any packets were sent
if (packetsSent > 0) {
Serial.print(F("INFO: TX packets="));
Serial.print(packetsSent);
Serial.print(F(" (Success: "));
Serial.print(packetsSuccess);
Serial.print(F(", Failed: "));
Serial.print(packetsSent - packetsSuccess);
Serial.println(F(")"));
}
lastActivityReport = now;
}
// Handle Serial input for sending CAN packets
if (Serial.available()) {
String input = Serial.readStringUntil('
');
sendPacketFromSerial(input);
}
}