Hello! I am trying to work with the CAN Bus protocol for a formula student team. We are using Arduino UNO as the slave attached to MCP2515 and the BAMOCAR d3 controller as the master. More specifically we are trying to receive the Motor Temperature, the IGBT temperature and the RPM which are on the registers 0x49, 0x4A and 0x30 respectively. I tried receiving them with a teensy 4.1 successfully (upon first sending 3 requests for each value I wanted to read, on the register 0x3D, which is the request register). The COB ID of BAMOCAR d3 is 0x201 for receiving and 0x181 for transmitting. With Arduino UNO seems like there is a message available to be read but it does not read anything in the end. Below I have attached first the Arduino UNO code (which has the issue) and second the successful code with Teensy 4.1. I will appreciate your help and excuse me for any profound mistakes!
Arduino UNO
#include <mcp_can.h>
#include <SPI.h>
const int CAN_CS_PIN = 10; // CS pin for the CAN module
// Create an instance of MCP_CAN
MCP_CAN CAN(CAN_CS_PIN);
unsigned long lastMessageTime = 0; // Track the last message time
const unsigned long TIMEOUT_PERIOD = 8000; // Timeout period 8 seconds
// DASHBOARD VALUES
float IGBTtemperature = 0;
float Mtemperature = 0;
float rpm = 0;
// Function prototypes
void sendRequest(uint8_t Register); // 0x4A --> IGBT Temp // 0x49 --> Motor Temp // 0xC8 --> RPM
void readMsg();
void handleError();
void ReadBamocarValues();
void setup(void) {
pinMode(pwmPin, OUTPUT); // Initialize the PWM pin as an output
pinMode(vent, OUTPUT); // Initialize the vent pin as an output
digitalWrite(vent, LOW); // Set the vent pin to LOW initially
Serial.begin(9600);
// Initialize CAN bus
if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) {
Serial.println("CAN Bus Set!");
} else {
Serial.println("CAN Bus Failed to Initialize");
while (1);
}
delay(3000);
// Send requests for various parameters
sendRequest(0x4A); // Request for IGBT Temperature
sendRequest(0x49); // Request for Motor Temperature
sendRequest(0x30); // Request for RPM
lastMessageTime = millis();
}
void loop() {
ReadBamocarValues();
delay(1000);
}
void ReadBamocarValues() {
// Read and process incoming CAN messages
readMsg();
// Check for timeout
if (millis() - lastMessageTime >= TIMEOUT_PERIOD) {
handleError(); // Handles the timeout error
lastMessageTime = millis();
}
}
/**
* Sends a CAN request for a specific register.
*
* @param Register The register ID to request data from.
*/
void sendRequest(uint8_t Register) {
// Set up the CAN message
unsigned char msg[3] = {0x3D, Register, 0x0A}; // Parameter transmission request
// Send the CAN message
CAN.sendMsgBuf(0x201, 0, 3, msg);
lastMessageTime = millis();
}
/**
* Handles CAN timeout errors.
*/
void handleError() {
Serial.println("CAN timeout error occurred!");
}
/**
* Reads incoming CAN messages and processes them.
*/
void readMsg() {
unsigned char len = 0;
unsigned char buf[8];
unsigned long id = 0x181; // Variable to hold the CAN ID
unsigned char ext = 0;
// Check if there are any messages available on the CAN bus
if (CAN_MSGAVAIL == CAN.checkReceive()) {
CAN.readMsgBuf(&id, &ext, &len, buf);
Serial.print("CAN1 ");
Serial.print(" ID: 0x");
Serial.print(id, HEX);
Serial.print(" LEN: ");
Serial.print(len);
Serial.print(" DATA: ");
for (uint8_t i = 0; i < len; i++) {
Serial.print(buf[i], HEX);
Serial.print(" ");
}
Serial.print(" TS: ");
Serial.println(millis());
// Process message if it has the expected ID
if (id == 0x181) {
uint32_t value = (buf[2] << 8) | buf[1];
// Process IGBT Temperature
if (buf[0] == 0x4A) {
Serial.print("IGBT Temperature");
}
// Process Motor Temperature
else if (buf[0] == 0x49) {
Serial.print("Motor Temperature");
}
// Process RPM
else if (buf[0] == 0x30) {
rpm = ((float)value / 32767) * 5000;
Serial.print("RPM: ");
Serial.println(rpm);
}
lastMessageTime = millis();
}
}
}
Teensy 4.1
#include <FlexCAN_T4.h>
// Create an instance of FlexCAN_T4 with specified buffer sizes
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
CAN_message_t msg;
unsigned long lastMessageTime = 0; // Track the last message time
const unsigned long TIMEOUT_PERIOD = 8000; // Timeout period in milliseconds (8 seconds)
// DASHBOARD VALUES
float IGBTtemperature = 0;
float Mtemperature = 0;
float rpm = 0;
// Function prototypes
void sendRequest(uint8_t Register); // 0xE2 --> BTB // 0x4A --> IGBT Temp // 0x49 --> Motor Temp // 0xC8 --> RPM
void readMsg();
void handleError();
void ReadBamocarValues();
void setup(void) {
pinMode(pwmPin, OUTPUT); // Initialize the PWM pin as an output
pinMode(vent, OUTPUT); // Initialize the vent pin as an output
digitalWrite(vent, LOW); // Set the vent pin to LOW initially
// Initialize serial communication for debugging
Serial.begin(9600);
// Initialize CAN bus
can1.begin();
can1.setBaudRate(500000);
Serial.println("CAN Bus Set!");
// Wait for the system to stabilize
delay(3000);
// Send requests for various parameters
sendRequest(0x4A); // Request for IGBT Temperature
sendRequest(0x49); // Request for Motor Temperature
sendRequest(0x30); // Request for RPM
lastMessageTime = millis();
}
void loop() {
ReadBamocarValues();
delay(1000);
}
void ReadBamocarValues() {
// Read and process incoming CAN messages
readMsg();
// Check for timeout
if (millis() - lastMessageTime >= TIMEOUT_PERIOD) {
handleError(); // Handle the timeout error
lastMessageTime = millis();
}
}
/**
* Sends a CAN request for a specific register.
*
* @param Register The register ID to request data from.
*/
void sendRequest(uint8_t Register) {
// Set up the CAN message
CAN_message_t msg;
msg.id = 0x201;
msg.len = 3;
msg.buf[0] = 0x3D; // Parameter transmission request
msg.buf[1] = Register; // REGID for the desired parameter
msg.buf[2] = 0x0A;
// Send the CAN message
can1.write(msg);
// Record the time when the message was sent
lastMessageTime = millis();
}
/**
* Handles CAN timeout errors.
*/
void handleError() {
Serial.println("CAN timeout error occurred!");
}
/**
* Reads incoming CAN messages and processes them.
*/
void readMsg() {
// Check if there are any messages available on the CAN bus
while (can1.read(msg)) {
// Print CAN message details for debugging
Serial.print("CAN1 ");
Serial.print(" ID: 0x");
Serial.print(msg.id, HEX);
Serial.print(" EXT: ");
Serial.print(msg.flags.extended);
Serial.print(" LEN: ");
Serial.print(msg.len);
Serial.print(" DATA: ");
for (uint8_t i = 0; i < msg.len; i++) {
Serial.print(msg.buf[i], HEX);
Serial.print(" ");
}
Serial.print(" TS: ");
Serial.println(msg.timestamp);
// Process message if it has the expected ID
if (msg.id == 0x181) {
uint32_t value = (msg.buf[2] << 8) | msg.buf[1];
// Process IGBT Temperature
if (msg.buf[0] == 0x4A) {
Serial.print("IGBT Temperature");
}
// Process Motor Temperature
else if (msg.buf[0] == 0x49) {
Serial.print("Motor Temperature");
}
// Process RPM
else if (msg.buf[0] == 0x30) {
rpm = ((float)value / 32767) * 5000;
Serial.print("RPM: ");
Serial.println(rpm); // Print the RPM value
}
}
}
}