MCP2515 stops working, CAN Bus

I am having a weird issue with my CAN bus MCP2515 communicating with my Arduino. I am trying to control 4 motors communicating over CAN and using a keypad with 4 LED indicator lights.

Code 1 attached uses the serial print to execute the bouncemotor function, this was working fine.

Code 2 attached integrates an LED and keypad to turn the motors off and on using the same bouncemotor function, this code compiles but is not working at all, and seems to brick the MCP2515. When I revert to code 1 the code compiles but now does not receive any commands.

Things I have tried and have not worked:

  • swapped out the MCP2515, initially it works with code 1 but when swapping between code 1 to 2 code breaks the MCP2515.
  • changed bitrate and clock speed (saw this in another thread).
  • checked wires (don't see how this could be an issue if initially working with code 1 but why not)

  • removed terminal resistor

  • checked if keypad and LEDS work seperately with same wiring ( they do)

attached are code 1 and code 2, and my schematic. Please give me any ideas you have! Thank You!

Code 1:

#include <SPI.h>          // SPI Library
#include <mcp2515.h>      // CAN Library

struct can_frame canMsg;
MCP2515 mcp2515(10); // MCP2515 CS pin on 10

// Define motor IDs
#define MOTOR_1 0x141  // Motor 141 (-45° to -135°)
#define MOTOR_2 0x142  // Motor 142 (45° to 135°)
#define MOTOR_3 0x143  // Motor 143 (Mirrors Motor 142)
#define MOTOR_4 0x144  // Motor 144 (Mirrors Motor 141)

// Define movement positions (hex values for angles)
const uint8_t motor1_low[8]  = {0xA4, 0x00, 0xF4, 0x01, 0x6C, 0xEE, 0xFF, 0xFF}; // -45°
const uint8_t motor1_high[8] = {0xA4, 0x00, 0xF4, 0x01, 0x44, 0xCB, 0xFF, 0xFF}; // -135°

const uint8_t motor2_low[8]  = {0xA4, 0x00, 0xF4, 0x01, 0x94, 0x11, 0x00, 0x00}; // 45°
const uint8_t motor2_high[8] = {0xA4, 0x00, 0xF4, 0x01, 0xBC, 0x34, 0x00, 0x00}; // 135°

const uint8_t motor_reset[8] = {0xA4, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, 0x00}; // 0°

bool running = false; // Flag to track if motion should run

void setup() {
    Serial.begin(115200);
    
    mcp2515.reset();
    mcp2515.setBitrate(CAN_1000KBPS, MCP_8MHZ);
    mcp2515.setNormalMode();
    
    Serial.println("CAN Bus Initialized");
    Serial.println("Press '1' to start motion. Press '2' to stop and reset.");
}

// Function to send a command to a motor
void sendCommand(uint16_t motorID, const uint8_t* data) {
    canMsg.can_id  = motorID;
    canMsg.can_dlc = 8;
    
    for (int i = 0; i < 8; i++) {
        canMsg.data[i] = data[i];
    }
    
    mcp2515.sendMessage(&canMsg);
    
    Serial.print("Sent to ");
    Serial.print(motorID, HEX);
    Serial.print(": ");
    
    for (int i = 0; i < 8; i++) {
        Serial.print(canMsg.data[i], HEX);
        Serial.print(" ");
    }
    
    Serial.println();
}

// Function to alternate movement
void bounceMotors() {
    // Move Motor 141 & 144 to -45° and Motor 142 & 143 to 135°
    sendCommand(MOTOR_1, motor1_low);
    sendCommand(MOTOR_4, motor1_low); // Motor 144 now mirrors Motor 141
    sendCommand(MOTOR_2, motor2_high);
    sendCommand(MOTOR_3, motor2_high); // Motor 143 now mirrors Motor 142
    delay(300); // Wait for movement

    // Move Motor 141 & 144 to -135° and Motor 142 & 143 to 45°
    sendCommand(MOTOR_1, motor1_high);
    sendCommand(MOTOR_4, motor1_high); // Motor 144 now mirrors Motor 141
    sendCommand(MOTOR_2, motor2_low);
    sendCommand(MOTOR_3, motor2_low); // Motor 143 now mirrors Motor 142
    delay(300); // Wait for movement
}

// Function to reset motors to 0°
void resetMotors() {
    sendCommand(MOTOR_1, motor_reset);
    sendCommand(MOTOR_2, motor_reset);
    sendCommand(MOTOR_3, motor_reset);
    sendCommand(MOTOR_4, motor_reset);
    Serial.println("Motors reset to 0°");
}

void loop() {
    // Check for user input
    if (Serial.available() > 0) {
        char command = Serial.read();
        
        if (command == '1') {
            running = true; // Start the motion
            Serial.println("Starting motion...");
        } 
        else if (command == '2') {
            running = false; // Stop motion
            Serial.println("Stopping motion and resetting motors...");
            resetMotors();
        }
    }

    // If running, execute movement
    if (running) {
        bounceMotors();
    }
}

Code 2:

#include <SPI.h>          // SPI Library
#include <mcp2515.h>      // CAN Library
#include <Keypad.h>       // Keypad Library

// LED Pin
const int GREEN_LED = A0;

struct can_frame canMsg;
MCP2515 mcp2515(10); // MCP2515 CS pin on 10

// Define motor IDs
#define MOTOR_1 0x141  // Motor 141 (-45° to -135°)
#define MOTOR_2 0x142  // Motor 142 (45° to 135°)
#define MOTOR_3 0x143  // Motor 143 (Mirrors Motor 142)
#define MOTOR_4 0x144  // Motor 144 (Mirrors Motor 141)

// Define movement positions (hex values for angles)
const uint8_t motor1_low[8]  = {0xA4, 0x00, 0xF4, 0x01, 0x6C, 0xEE, 0xFF, 0xFF}; // -45°
const uint8_t motor1_high[8] = {0xA4, 0x00, 0xF4, 0x01, 0x44, 0xCB, 0xFF, 0xFF}; // -135°

const uint8_t motor2_low[8]  = {0xA4, 0x00, 0xF4, 0x01, 0x94, 0x11, 0x00, 0x00}; // 45°
const uint8_t motor2_high[8] = {0xA4, 0x00, 0xF4, 0x01, 0xBC, 0x34, 0x00, 0x00}; // 135°

const uint8_t motor_reset[8] = {0xA4, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, 0x00}; // 0°

// Keypad Configuration
const byte ROWS = 1;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  { '1', '2', '3', '4' }
};

// Keypad Pins
byte rowPins[ROWS] = { 5 };        // Common pin
byte colPins[COLS] = { 6, 7, 8, 9 }; // Column pins

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

bool running = false; // Flag to track if motion should run
bool ledState = false; // Flag to track LED state

void setup() {
    Serial.begin(115200);
    
    // Initialize CAN Bus
    mcp2515.reset();
    mcp2515.setBitrate(CAN_1000KBPS, MCP_8MHZ);
    mcp2515.setNormalMode();
    
    // Initialize LED
    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, LOW);
    
    Serial.println("CAN Bus and Keypad Initialized");
    Serial.println("Press Button 1 to start/stop motor motion");
}

// Function to send a command to a motor
void sendCommand(uint16_t motorID, const uint8_t* data) {
    canMsg.can_id  = motorID;
    canMsg.can_dlc = 8;
    
    for (int i = 0; i < 8; i++) {
        canMsg.data[i] = data[i];
    }
    
    mcp2515.sendMessage(&canMsg);
    
    Serial.print("Sent to ");
    Serial.print(motorID, HEX);
    Serial.print(": ");
    
    for (int i = 0; i < 8; i++) {
        Serial.print(canMsg.data[i], HEX);
        Serial.print(" ");
    }
    
    Serial.println();
}

// Function to alternate movement
void bounceMotors() {
    // Move Motor 141 & 144 to -45° and Motor 142 & 143 to 135°
    sendCommand(MOTOR_1, motor1_low);
    sendCommand(MOTOR_4, motor1_low); // Motor 144 now mirrors Motor 141
    sendCommand(MOTOR_2, motor2_high);
    sendCommand(MOTOR_3, motor2_high); // Motor 143 now mirrors Motor 142
    delay(300); // Wait for movement

    // Move Motor 141 & 144 to -135° and Motor 142 & 143 to 45°
    sendCommand(MOTOR_1, motor1_high);
    sendCommand(MOTOR_4, motor1_high); // Motor 144 now mirrors Motor 141
    sendCommand(MOTOR_2, motor2_low);
    sendCommand(MOTOR_3, motor2_low); // Motor 143 now mirrors Motor 142
    delay(300); // Wait for movement
}

// Function to reset motors to 0°
void resetMotors() {
    sendCommand(MOTOR_1, motor_reset);
    sendCommand(MOTOR_2, motor_reset);
    sendCommand(MOTOR_3, motor_reset);
    sendCommand(MOTOR_4, motor_reset);
    Serial.println("Motors reset to 0°");
}

void loop() {
    // Get key press
    char key = keypad.getKey();
    
    // Process the key press
    if (key != NO_KEY) {
        switch(key) {
            case '1':
                // Toggle motor running state
                running = !running;
                
                // Toggle LED state
                ledState = !ledState;
                digitalWrite(GREEN_LED, ledState);
                
                if (running) {
                    Serial.println("Starting motor motion...");
                } else {
                    Serial.println("Stopping motor motion and resetting...");
                    resetMotors();
                }
                break;
        }
    }

    // If running, execute movement
    if (running) {
        bounceMotors();
    }
}

No useful information here.

Hardware failure is suspected. Bad contact in a breadboard, something is destroyd.

Posting schematics is a natural step.

The schematic helps a lot. You need terminating resistor (120 Ohm) on the two physical ends of the bus, no more no less. I also recommend starting at a much slower bit rate until you get it operating. Verify each of the CAN modules has a 8 Mhz crystal, Some have different values.

thanks for your response, hardware failure was a good lead. I'll leave this up in case anyone else has a similar problem.

The solution ended up being that the connections from the keypad were too close to the MISO, SDK and INT pins I am suspecting. Shifting the keypad down to D2-D6 seems to have fixed the problem.

Well done!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.