Hello,
I am trying to control RMD X12-150 motor via CAN-BUS using Arduino Nano. I use MCP2515 CAN module for arduino. I wrote the code based on the User manual. I attached my code below. I am trying to do speed control of the motor. When I press ‘x’ it should increase the speed, and inverse when I press ‘s’. However, the motor is just spinning with constant speed, even when I set the speed as 0. Also, when I try to do position control and give 0 degree angle, it is still rotating to a random angle. Also, I receive some response from the motor. Based on this response, I see that I don’t receive any position feedback. Is it possible to reset the motor to factory settings? Or receive any help from someone who worked with this motor? It is not V2 nor V3. Its can message types are of different structure.
#include <SPI.h> // Library for using SPI Communication
#include <mcp2515.h> // Library for using CAN Communication
/*SAMD core*/
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif
struct can_frame canMsg;
MCP2515 mcp2515(10);
char incomingChar; // Store incoming character from Serial
int speedControl = 0; // Speed control value
void setup()
{
Serial.begin(115200);
while (!Serial);
mcp2515.reset();
mcp2515.setBitrate(CAN_1000KBPS, MCP_8MHZ); // Set CAN bus speed to 1000 kbps
mcp2515.setNormalMode();
Serial.println("Setup done");
enable();
// setZero();
sendPositionControlCommand(0, 10000, 10);
delay(5000);
}
void enable(){
canMsg.can_id = 0x7FF; // Use an appropriate ID for speed control
canMsg.can_dlc = 4; // Data length is 4 bytes
// Populate CAN message data according to the datasheet
canMsg.data[0] = (0x01 >> 8) & 0xFF;
canMsg.data[1] = 0x01 & 0xFF;
canMsg.data[2] = 0x00;
canMsg.data[3] = 0x01;
mcp2515.sendMessage(MCP2515::TXB1, &canMsg); // Send CAN message for speed control
Serial.print("Enable: ");
printserial(canMsg.can_id, canMsg.data);
Serial.println();
}
void setZero(){
canMsg.can_id = 0x7FF; // Use an appropriate ID for speed control
canMsg.can_dlc = 4; // Data length is 4 bytes
canMsg.data[0] = (0x01 >> 8) & 0xFF; // Motor id high
canMsg.data[1] = 0x01 & 0xFF; // motor id low
canMsg.data[2] = 0x00;
canMsg.data[3] = 0x03;
mcp2515.sendMessage(MCP2515::TXB1, &canMsg); // Send CAN message for speed control
Serial.print("Zero Setting: ");
printserial(canMsg.can_id, canMsg.data);
Serial.println();
}
void sendSpeedControlCommand(int32_t speedControl) {
canMsg.can_id = 0x1FF; // Use an appropriate ID for speed control
canMsg.can_dlc = 7; // Data length is 7 bytes
// Populate CAN message data according to the datasheet
canMsg.data[0] = 0x03; // Motor mode
canMsg.data[1] = 0x00; // Reserved control status (must be 0)
canMsg.data[2] = 0x00; // Message return status (set to 0)
float expectedSpeed = static_cast<float>(speedControl);
uint32_t speedBytes = *reinterpret_cast<uint32_t*>(&expectedSpeed);
canMsg.data[3] = (speedBytes >> 8) & 0xFF; // High byte of speed
canMsg.data[4] = speedBytes & 0xFF; // Next byte
canMsg.data[5] = 0x00;
canMsg.data[6] = 0x00;
mcp2515.sendMessage(MCP2515::TXB1, &canMsg); // Send CAN message for speed control
Serial.print("Sent: ");
printserial(canMsg.can_id, canMsg.data);
Serial.println();
}
void sendPositionControlCommand(float expectedPosition, uint16_t expectedSpeed, uint16_t currentThreshold) {
canMsg.can_id = 0x1FF; // Use an appropriate ID for position control
canMsg.can_dlc = 8; // Data length is 8 bytes
canMsg.data[0] = 0x01; // Motor mode (Position Control)
// Convert expected position to bytes
uint32_t positionBytes = *reinterpret_cast<uint32_t*>(&expectedPosition);
canMsg.data[1] = (positionBytes >> 24) & 0xFF; // High byte
canMsg.data[2] = (positionBytes >> 16) & 0xFF; // Next byte
canMsg.data[3] = (positionBytes >> 8) & 0xFF; // Next byte
canMsg.data[4] = positionBytes & 0xFF; // Low byte
// Populate expected speed (15 bits)
canMsg.data[5] = (expectedSpeed >> 8) & 0xFF; // High byte of speed
canMsg.data[6] = expectedSpeed & 0xFF; // Low byte of speed
// Populate current threshold (12 bits)
canMsg.data[7] = (currentThreshold & 0x0FFF); // Low byte of current threshold (12 bits)
mcp2515.sendMessage(MCP2515::TXB1, &canMsg); // Send CAN message for position control
Serial.print("Sent Position Control: ");
printserial(canMsg.can_id, canMsg.data);
Serial.println();
}
void printserial(unsigned long ID, unsigned char buf[8]) {
Serial.print(ID, HEX);
Serial.print(": ");
for (int i = 0; i < 8; i++) {
Serial.print(buf[i], HEX);
Serial.print(" ");
}
Serial.println();
}
void loop()
{
if (Serial.available() > 0) {
incomingChar = Serial.read(); // Read a single character
if (incomingChar == 'x') { // Increase speed
speedControl += 100; // Adjust increment as needed
if (speedControl > 10000) speedControl = 10000; // Limit maximum speed
}
else if (incomingChar == 's') { // Decrease speed
speedControl -= 100; // Adjust decrement as needed
if (speedControl < -10000) speedControl = -10000; // Limit minimum speed
}
}
sendSpeedControlCommand(speedControl); // Send updated speed command
// Read incoming CAN message if available
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
// Response received
Serial.print("Recv: ");
printserial(canMsg.can_id, canMsg.data);
Serial.println();
} else {
// No response
Serial.println("Recv: NO ANSWER");
}
delay(100); // Adjust delay as needed
}
Motor Response:
Recv: 205: FE 48 0 1 1 B0 66 0
Sent: 1FF: 3 0 0 0 0 0 0 0
Recv: 205: FE 48 0 1A 2 20 66 0
Sent: 1FF: 3 0 0 0 0 0 0 0
Recv: 205: FE 48 1 29 2 13 66 0
Sent: 1FF: 3 0 0 0 0 0 0 0
Recv: 205: FE 48 C 12 0 31 66 0
Sent: 1FF: 3 0 0 0 0 0 0 0
Recv: 205: FE 48 F 1 0 37 66 0