Inquiry for T-Motor AK 60-6 in servo mode by arduino

Hello,

I am a student working on operating the CubeMars AK60-6 motor using an Arduino MKR WiFi 1010 with CAN shield.

Previously, I succeeded in running the motor in MIT mode using the Arduino code provided earlier from CubeMars, along with the MKR CAN shield. However, I am experiencing difficulties in running the motor in Servo mode.

From my understanding, operating the motor in Servo mode requires using an extended CAN packet. Unlike MIT mode, it seems there is no need for an “Enter motor” code to start the motor in Servo mode. Therefore, I believe that the motor should run by simply sending the CAN ID and data in an extended packet. However, the motor does not operate with my attached code.

For debugging purposes, I have printed various results, which are listed below, followed by my code. (For reference, my code operates the motor in Servo velocity mode. It increases the RPM by 1500 whenever ‘u’ is input and decreases it by 1500 whenever ‘d’ is input.)

  1. The motor CAN ID is 0x02, and the numeric value for Velocity mode is 3. Hence, the CAN ID of the extended packet being sent is 0x302. Additionally, the value 3000 is converted to the following byte array via the buffer_append_int32 function from the manual: buf[4] = {0, 0, 11, 184} and this is sent in the packet.

  2. However, in the manual’s example, the data could also be formatted as buf[4] = {184, 11, 0, 0} . I tried sending the data in this format, but the motor still did not operate.

From my understanding, to rotate the motor with an ID of 2 at a speed of 3000, the code should look as follows: (Reference: DEC [0, 0, 11, 184] → HEX [00, 00, 0B B8])

uint8_t buf[4] = {00, 00, 11, 184}; CAN.beginExtendedPacket(0x302); CAN.write(buf, 4);
CAN.endPacket();

Am I possibly missing something?
Or is Servo mode not operated via CAN communication?

If you have an Arduino MKR CAN Shield, you can test the attached program. I would greatly appreciate your assistance.

Sincerely,
Soonho Kwon


Following is my arduino code


#include <CAN.h>

float motor_pos;
float motor_spd;
float motor_cur;
int8_t temp1;
int8_t error;

void comm_can_transmit_eid(uint32_t id, const uint8_t* data, uint8_t len) {
  uint8_t i = 0;

  if (len > 8) {
    len = 8;
  }

  uint8_t buf[len];
  for (i = 0; i < len; i++) {
    buf[i] = data[i];
  }

  // Sending CAN message to MOTOR //
  CAN.beginExtendedPacket(id);
  CAN.write(buf, len);
  CAN.endPacket();

  Serial.print("id: "); Serial.print(id, HEX); 
  for (i = 0; i < len; i++) {
    Serial.print(" / buf"); Serial.print(len-i-1); Serial.print(": "); Serial.print(buf[len-i-1]);
  }
  Serial.println();
}

void buffer_append_int32(uint8_t *buffer, int32_t number, int32_t *index) {
    buffer[(*index)++] = number >> 24;
    buffer[(*index)++] = number >> 16;
    buffer[(*index)++] = number >> 8;
    buffer[(*index)++] = number;

    // buffer[(*index)++] = number;
    // buffer[(*index)++] = number >> 8;
    // buffer[(*index)++] = number >> 16;
    // buffer[(*index)++] = number >> 24;
}

enum {
    CAN_PACKET_SET_DUTY = 0,
    CAN_PACKET_SET_CURRENT,
    CAN_PACKET_SET_CURRENT_BRAKE,
    CAN_PACKET_SET_RPM,
    CAN_PACKET_SET_POS,
    CAN_PACKET_SET_ORIGIN_HERE,
    CAN_PACKET_SET_POS_SPD
} CAN_PACKET_ID;

/*******************Servo*******************/
void comm_can_set_rpm(uint8_t controller_id, float rpm) {
    int32_t send_index = 0;
    uint8_t buffer[4];
    buffer_append_int32(buffer, (int32_t)rpm, &send_index);
    comm_can_transmit_eid((uint32_t)(controller_id | (uint32_t)CAN_PACKET_SET_RPM << 8), buffer, send_index);
}

void motor_receive_servo() {
    // Read data
    uint8_t buf[8]; // CAN data buffer
    int i = 0;
    while (CAN.available() && i < 8) {
      buf[i++] = CAN.read(); // Store data in the array
    }

    long id = CAN.packetId();
    bool isExtended = CAN.packetExtended();

    // if (isExtended) {
    //     Serial.print("Extended ID: ");
    // } else {
    //     Serial.print("Standard ID: ");
    // }
    // Serial.println(id);

    // Parse received data
    int16_t pos_int = (buf[0] << 8) | buf[1];
    int16_t spd_int = (buf[2] << 8) | buf[3];
    int16_t cur_int = (buf[4] << 8) | buf[5];
    motor_pos = (float)(pos_int * 0.1f);   // Motor position
    motor_spd = (float)(spd_int * 10.0f);  // Motor speed
    motor_cur = (float)(cur_int * 0.01f);  // Motor current
    temp1 = buf[6];         // Motor temperature
    error = buf[7];         // Motor error code
}

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("CAN Sender");

  // start the CAN bus at 1000 kbps
  if (!CAN.begin(1000E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
  Serial.println("Start Motor");
}

long previousMillis = 0;
boolean startMotor = true;
float rpm = 0.0;

void loop() {
  char rc;

  if (Serial.available() > 0) {
      rc = Serial.read();
      Serial.println(rc);
  }

  if (startMotor == true) {
    //send CAN
    if(rc=='u')
    {
      rpm = rpm + 1500.0;
      comm_can_set_rpm(0x02, rpm);
      Serial.print("Speed: ");Serial.println(rpm);
    }
    if(rc=='d')
    {
      rpm = rpm - 1500.0;
      comm_can_set_rpm(0x02, rpm);
      Serial.print("Speed: ");Serial.println(rpm);
    }
    
    // receive CANcheckReceive
    int packetSize = CAN.parsePacket();
    if(packetSize || CAN.packetId() != -1) {
      motor_receive_servo();
    
      //print data
      // Serial.print(millis()-previousMillis);
      // previousMillis = millis();
      // Serial.print(" ");
      // Serial.print(motor_pos);
      // Serial.print(" ");
      // Serial.print(motor_spd);
      // Serial.print(" ");
      // Serial.print(motor_cur);
      // Serial.print(" ");
      // Serial.print(temp1);
      // Serial.print(" ");
      // Serial.print(error);
      // Serial.println(" ");
    }
  }
}                                                                                                                                

uint8_t buf[4] = {00, 00 , 11, 184};
CAN.beginExtendedPacket(0x302);
CAN.write(buf, 4);
CAN.endPacket();

This code is correct one.