T-motor Cubemars AK 80-64 arduino Spakfun CAN bus communication

Hello Guys,

I have purchased AK 80-64 motor from AK80-64_AK Series Dynamical Modular_Exoskeleton Robot_CubeMars - Professional and Reliable manufacturer for robot actuators and frameless motors

I have tried to actuate it through Arduino Uno + Sparkfun CAN-BUS Shield.

I have tried to use code with similar setup from Gravity compensation and Spherical robot joint with AK60-6 actuator - YouTube

Just the motor is different, however I suppose they use same protocol for CAN BUS.

The code is as follows.

COULD YOU PLEASE HELP IN IDENTIFYING THE MISTAKE, the motor just doesn't want to start?


// demo: CAN -BUS Shield, send data
// loovee@seeed.cc https://www.youtube.com/watch?v=UWc_7-8gXeE

#include <mcp_can.h>
#include <SPI.h>

/* SAMD core*/
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
  #define SERIAL SerialUSB
#else
  #define SERIAL 0x00
#endif

//Define Joystick connection pins
#define UP A1
#define DOWN A3
#define RIGHT A5
#define CLICK A4
#define LEFT A2

//Define LED pins
#define LED2 8
#define LED3 7

//VALUE LIMIS

#define P_MIN -12.5f
#define P_MAX 12.5f
#define V_MIN -5.0f
#define V_MAX 5.0f
#define KP_MIN 0.0f
#define KP_MAX 500.0f
#define KD_MIN 0.0f
#define KD_MAX 5.0f
#define T_MIN 0.0f
#define T_MAX 5.0f

// SET VALUES

float p_in = 0.0f;
float v_in = 3.0f;
float kp_in = 0.0f;
float kd_in = 3.0f;
float t_in = 0.0f;
//measured values

float p_out = 0.0f;
float v_out = 0.0f;
float t_out = 0.0f;

//the cs pin of the version after v1.1 is default to D9
//v0.9 and v1.0 is default D10
const int SPI_CS_PIN = 10;

MCP_CAN CAN (SPI_CS_PIN);   //Set CS pin

void setup() {
  Serial.begin(115200);
  delay(1000);
  while (CAN_OK != CAN.begin(MCP_ANY,CAN_1000KBPS, MCP_16MHZ))
  {
    Serial.println("CAN BUS Shield init fail");
    Serial.println(" Init CAN BUS Shield again");
    delay(100);
  }
Serial.println("CAN BUS Shield is ok!");

//Intialize pins as necessary

pinMode(UP, INPUT);
pinMode(DOWN, INPUT);
pinMode(LEFT, INPUT);
pinMode(RIGHT, INPUT);
pinMode(CLICK, INPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);

//Pull analog pins high to enable reading of joystick movements
digitalWrite(UP, HIGH);
digitalWrite(DOWN, HIGH);
digitalWrite(LEFT, HIGH);
digitalWrite(RIGHT, HIGH);
digitalWrite(CLICK, HIGH);

//Write LED pins low to trun them off by default

digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);

}

long previousMillis = 0;

void loop() {
  //do something

  float p_step=0.001;
  //delay(200);
  if (digitalRead(UP) ==LOW)
  {
    //move motor forward
    p_in = p_in + p_step;
  }
  if (digitalRead(DOWN) ==LOW)
  {
    //move motor forward
    p_in = p_in - p_step;
  }
  p_in = constrain(p_in, P_MIN, P_MAX);
  if (digitalRead(RIGHT) ==LOW)
  {
    //Enable
    EnterMotorMode();
    digitalWrite(LED2, HIGH);
  }
  if (digitalRead(LEFT)==LOW)
  {
    ExitMotorMode();
    digitalWrite(LED2,LOW);
  }
  //send CAN
  pack_cmd();

  //receive CAN
  if(CAN_MSGAVAIL == CAN.checkReceive())
  {
   
    unpack_reply();
  }
  //print data
  Serial.print(millis()-previousMillis);
  previousMillis = millis();
  Serial.print(" ");
  Serial.print(p_in);
  Serial.print(" ");
  Serial.print(p_out);
  Serial.print(" ");
  Serial.print(v_out);
  Serial.print(" ");
  Serial.println(t_out);
}
void unpack_reply() {
/// CAB reply Oacjet structure///
/// 16 bit position, between -4*pi and 4*pi
/// 12 bit velocity, between -30 and +30 rad/s
/// 12 bit current, between -40 and 40;
/// CAN Packet is 5 8-bit words
///Formatted as follows. For each quantity, bit 0 is LSB
/// 0: [position [15-8]]
/// 1: [position[7-0]]
/// 2: [velocity [11-4]]
/// 3: [velocity [3-0], current [11-8]]
/// 4: [current [7-0]]

  byte len = 0;
  byte buf[8];
  unsigned long canId;

  CAN.readMsgBuf(&canId, &len, buf); 
  //read data
  //MCP_CAN::readMsgBuf(*len,  buf[])

  
  /// unpack ints from CAN buffer ///
  unsigned int id = buf[0];
  unsigned int p_int = (buf[1] << 8) | buf[2];
  unsigned int v_int = (buf[3] << 4) | (buf[4] >> 4);
  unsigned int i_int = ((buf[4] & 0xF) << 8) | buf[5];
  /// convert uints to floats ///
  p_out = uint_to_float(p_int, P_MIN, P_MAX, 16);
  v_out = uint_to_float(v_int, V_MIN, V_MAX, 12);
  t_out = uint_to_float(i_int, -T_MAX, T_MAX, 12);
}
void EnterMotorMode(){
  //Enter Motor Mode(enable)
  byte buf[8];
  buf[0] = 0xFF;
  buf[1] = 0xFF;
  buf[2] = 0xFF;
  buf[3] = 0xFF;
  buf[4] = 0xFF;
  buf[5] = 0xFF;
  buf[6] = 0xFF;
  buf[7] = 0xFF;
  CAN.sendMsgBuf(0x01,0, 8, buf);
}
void ExitMotorMode(){
  byte buf[8];
  buf[0] = 0xFF;
  buf[1] = 0xFF;
  buf[2] = 0xFF;
  buf[3] = 0xFF;
  buf[4] = 0xFF;
  buf[5] = 0xFF;
  buf[6] = 0xFF;
  buf[7] = 0xFF;
  CAN.sendMsgBuf(0x01, 0, 8, buf);
}
void Zero(){
  //Enter Motor Mode(enable)
  byte buf[8];
  buf[0] = 0xFF;
  buf[1] = 0xFF;
  buf[2] = 0xFF;
  buf[3] = 0xFF;
  buf[4] = 0xFF;
  buf[5] = 0xFF;
  buf[6] = 0xFF;
  buf[7] = 0xFF;
  CAN.sendMsgBuf(0x01, 0, 8, buf);

}
void pack_cmd(){
  byte buf[8];
  ///CAN Command Packet Structure///
  ///16 bit position command, between -4*pi and 4*pi
  ///12 bit velocity command, between -30 and +30rad/s
  //12 bit kp, between 0 and 500 N-m/rad
  ///12 bit kd, between 0 and 100 N-m*s/rad
  /// 12 bit feed forward toque, between -18 and 18 N-m
  ///CAN packet is 8 8-bit words
  ///Formatted as follows. For each quantity, bit i0 is LSB
  /// 0: [position[15-8[[
  ///1: [position [7-0]]
  ///2: [velocity[11-4]]
  ///3: [velocity[3-0], kp[11-8]]
  ///4: [kp[7-0]]
  ///5: [kd[11-4]]
  ///6:[kd[3-0], torque [11-8]]
  ///7: [torque [7-0]]

  ///limit data to be withing bounds///

  float p_des = constrain(p_in, P_MIN, P_MAX); ///fminf(fmaxf(P_MIN, p_in(, P_MAX);
  float v_des = constrain(v_in, V_MIN, V_MAX); ///fminf(fmaxf(V_MIN, v_in(, V_MAX);
  float kp = constrain(kp_in, KP_MIN, KP_MAX); ///fminf(fmaxf(KP_MIN, kp_in(, KP_MAX);
  float kd = constrain(kd_in, KD_MIN, KD_MAX); ///fminf(fmaxf(KD_MIN, kd_in(, KD_MAX);
  float t_ff = constrain(t_in, T_MIN, T_MAX); ///fminf(fmaxf(T_MIN, t_in(, V_MAX);

 ///convert floats to unsigned ints///
  unsigned int p_int = float_to_uint(p_des, P_MIN, P_MAX, 16);
  unsigned int v_int = float_to_uint(v_des, V_MIN, V_MAX, 12);
  unsigned int kp_int = float_to_uint(kp, KP_MIN, KP_MAX, 12);
  unsigned int kd_int = float_to_uint(kd, KD_MIN, KD_MAX, 12);
  unsigned int t_int = float_to_uint(t_ff, T_MIN, T_MAX, 12);

/// pack ints into the can buffer///

  buf[0] = p_int >> 8;
  buf[1] = p_int & 0xFF;;
  buf[2] = v_int >> 4;
  buf[3] = ((v_int & 0xF) <<4) | (kp_int >>8);
  buf[4] = kp_int & 0xFF;
  buf[5] = kd_int >>4;
  buf[6] = ((kd_int & 0xF) <<4) | (t_int >>8);
  buf[7] = t_int & 0xFF;
  CAN.sendMsgBuf(0x01, 0, 8, buf);
}


unsigned int float_to_uint(float x, float x_min, float x_max, int bits)
{
  ///Converts a  float to an unsigned int, given range and number of bits///
  float span = x_max-x_min;
  float offset = x_min;
  unsigned int pgg = 0;
  if(bits==12){
    pgg = (unsigned int) ((x-offset)*4095.0/span);
  }
  if(bits==16){
    pgg = (unsigned int) ((x-offset)*65535.0/span);
  }
  return pgg;
}

float uint_to_float(unsigned int x_int, float x_min, float x_max, int bits)
{
  ///converts unsigned int to float, given range and number of bits///
  float span = x_max-x_min;
  float offset = x_min;
  float pgg = 0;
  if (bits==12){
    pgg = ((float) x_int)*span/4095 + offset;
  }
  if (bits==16){
    pgg = ((float) x_int)*span/65535.0 + offset;
  }
  return pgg;

}

My setup is as follows

@blh64 @TomGeorge

Hello guys, I think you are experts in this, would you please take a look?

It has been a while I am stuck with this motor, can't make it rotate,
it uses MIT mini cheetah driver board

What do you get on the Serial monitor? You have lots of print() statements in your code, please show the output.

You report information every time through loop, even if you have not received a message. It seems like all those print() statements should be inside the if() statement, after unpack_reply()

Do you have all your grounds tied together? The ground from the power supply should also be connected to the arduino/shield ground

Hi, thanks for your reply.

I am getting the following output at serial monitor.

I have tried to connect groud of power supply with Arduino, that also did not work.

In general, with the R-Link (CAN-bus, UART to usb) setup and manufacturer software (upper computer) I could actuate the motor as shown below.

But it doesn't want to move with Arduino

I have put the print statements after unplack_reply() and I get the following output

Pictures of text are never useful. Copy/paste the output using code tags, just like your code.

You should try putting some print() statements in your code when the joystick moves. As is stands right now, you don't know if your system is detecting UP/DOWN/LEFT/RIGHT and doing anything.

It is also odd that your EnterMotorMode() and ExitMotorMode() functions send the exact same message on the CAN bus.

You also never send any CAN message with the updated coordinates, which I would guess is necessary to command the motor to move.

1 Like

thanks bro, I figured it out, there were some problems with the CAN protocol code

What did you figure out about the CAN protocol code? I am having an issue with my implementation

Hi do you also have such motor?

hii @akimzhankb yes!, I have same motor AK80-9 and I am facing same problem

I am using Arduino mega and CAN bus 2515 module

connection is :point_down:

INT -- to-- D2
CS --to-- D53
SCK --to-- D52
MOSI--to--D51
MISO --to--D50

VCC to 5v VCC
GND to GND

CAN H of module to CAN H of MOTOR
CAN L of module to CAN L of MOTOR
POWER supply 24V 25A to motor
and also did 120 ohms resistor termination in between CAN H and CAN L.

but not able to actuate the motor

#include <SPI.h>
#include <mcp_can.h>
/*
Author: Mihai Moldovanu
Youtube: https://www.youtube.com/channel/UC1CS67BvP8PaVJRK6wxhbCg
Mail: mihaim@tfm.ro
*/

// Mini cheetah actuator testing code
//
// Hardware needed: Wemos d1 mini + mcp215 can
// Last Tested : 24 ian 2021



// Value Limits
#define P_MIN -12.5f
#define P_MAX 12.5f
#define V_MIN -65.0f
#define V_MAX 65.0f
#define KP_MIN 0.0f
#define KP_MAX 500.0f
#define KD_MIN 0.0f
#define KD_MAX 5.0f
#define T_MIN -18.0f
#define T_MAX 18.0f

// Set values
float p_in = 0.0f;
float v_in = 5.0f;
float kp_in = 10.0f;
float kd_in = 0.20f;
float t_in = 0.0f;
// measured values
float p_out = 0.0f;
float v_out = 0.0f;
float t_out = 0.0f;

long previousMillis = 0;

// Wemos D1 mini CS pin is D8 ( translated to pin 15 )
const int spiCSPin = 53; // 53 for arduino mega

MCP_CAN CAN(spiCSPin);

// Motor Mode on command
byte MotorModeOn[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc};

// Motor Mode off command
byte MotorModeOff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd};


void setup()
{
  Serial.begin(115200);
  Serial.println("CANBUS firmware 1.0");

  while (CAN_OK != CAN.begin(MCP_ANY,CAN_1000KBPS,MCP_16MHZ)) {
    Serial.println("CAN BUS init Failed");
    delay(100);
  }

  Serial.println("CAN BUS Shield Init OK!");

  // Enable motor mode
  while ( CAN_OK != CAN.sendMsgBuf(0x01, 0, 8, MotorModeOn))
    {
      Serial.println("Error enabling motor mode");
      delay(1000);
    }
}


int a = 0;

void loop()
{
// Moving faster to 6.0 and slow back to 0
if ( a == 0 ) 
  p_in = p_in + 0.5;
else 
 p_in = p_in - 0.1;

if ( p_in > 6 ) 
  a = 1;

if ( p_in < 0.2 )
  a = 0;



pack_cmd();

// receive CAN
  if(CAN_MSGAVAIL == CAN.checkReceive()) {
    unpack_reply();
    //print data
    Serial.print(p_in);
    Serial.print(" ");
    Serial.print(p_out);
    Serial.print(" ");
    Serial.print(v_out);
    Serial.print(" ");
    Serial.println(t_out);
  }

// during testing don't issue commands to fast
 delay(200);
}


/*
 Pack command and send it to canbus
*/
void pack_cmd(){
  byte buf[8];

  // CAN Command Packet Structure ///
  // 16 bit position command, between -4*pi and 4*pi
  // 12 bit velocity command, between -30 and + 30 rad/s
  // 12 bit kp, between 0 and 500 N-m/rad
  // 12 bit kd, between 0 and 100 N-m*s/rad
  // 12 bit feed forward torque, between -18 and 18 N-m
  // CAN Packet is 8 8-bit words
  // Formatted as follows.  For each quantity, bit 0 is LSB
  // 0: [position[15-8]]
  // 1: [position[7-0]] 
  // 2: [velocity[11-4]]
  // 3: [velocity[3-0], kp[11-8]]
  // 4: [kp[7-0]]
  // 5: [kd[11-4]]
  // 6: [kd[3-0], torque[11-8]]
  // 7: [torque[7-0]]

  // limit data to be within bounds 
  float p_des = constrain(p_in, P_MIN, P_MAX);
  float v_des = constrain(v_in, V_MIN, V_MAX);
  float kp = constrain(kp_in, KP_MIN, KP_MAX);
  float kd = constrain(kd_in, KD_MIN, KD_MAX);
  float t_ff = constrain(t_in, T_MIN, T_MAX);
  // convert floats to unsigned ints
  unsigned int p_int = float_to_uint(p_des, P_MIN, P_MAX, 16);
  unsigned int v_int = float_to_uint(v_des, V_MIN, V_MAX, 12);
  unsigned int kp_int = float_to_uint(kp, KP_MIN, KP_MAX, 12);
  unsigned int kd_int = float_to_uint(kd, KD_MIN, KD_MAX, 12);
  unsigned int t_int = float_to_uint(t_ff, T_MIN, T_MAX, 12);
  // pack ints into the can buffer

  buf[0] = p_int >> 8;
  buf[1] = p_int & 0xFF;
  buf[2] = v_int >> 4;
  buf[3] = ((v_int & 0xF) << 4) | (kp_int >> 8);
  buf[4] = kp_int & 0xFF;
  buf[5] = kd_int >> 4;
  buf[6] = ((kd_int & 0xF) << 4) | (t_int >> 8);
  buf[7] = t_int & 0xFF;
  CAN.sendMsgBuf(0x01, 0, 8, buf);
}

/*
Unpack message received on canbus
*/
void unpack_reply(){
  // CAN Reply Packet Structure ///
  // 16 bit position, between -4*pi and 4*pi
  // 12 bit velocity, between -30 and + 30 rad/s
  // 12 bit current, between -40 and 40;
  // CAN Packet is 5 8-bit words
  // Formatted as follows.  For each quantity, bit 0 is LSB
  // 0: [position[15-8]]
  // 1: [position[7-0]] 
  // 2: [velocity[11-4]]
  // 3: [velocity[3-0], current[11-8]]
  // 4: [current[7-0]]

  long unsigned int rxId;

  byte len = 0;
  byte buf[8];
  CAN.readMsgBuf(&rxId, &len, buf);

  // unpack ints from can buffer
  unsigned int id = buf[0];
  unsigned int p_int = (buf[1] << 8) | buf[2];
  unsigned int v_int = (buf[3] << 4) | (buf[4] >> 4);
  unsigned int i_int = ((buf[4] & 0xF) << 8) | buf[5];
  // convert uints to floats
  p_out = uint_to_float(p_int, P_MIN, P_MAX, 16);
  v_out = uint_to_float(v_int, V_MIN, V_MAX, 12);
  t_out = uint_to_float(i_int, -T_MAX, T_MAX, 12);
} 

/*
 Converts a float to an unsigned int, given range and number of bits
*/
unsigned int float_to_uint(float x, float x_min, float x_max, int bits){
  float span = x_max - x_min;
  float offset = x_min;
  unsigned int pgg = 0;
  if (bits == 12){
    pgg = (unsigned int) ((x-offset)*4095.0/span);
  }
  if (bits == 16){
    pgg = (unsigned int) ((x-offset)*65535.0/span);
  }
  return pgg;
}

/*
 Converts unsigned int to float, given range and number of bits
*/
float uint_to_float(unsigned int x_int, float x_min, float x_max, int bits){
  float span = x_max - x_min;
  float offset = x_min;
  float pgg = 0;
  if (bits == 12){
    pgg = ((float)x_int)*span/4095.0 + offset;
  }
  if (bits == 16){
    pgg = ((float)x_int)*span/65535.0 + offset;
  }
  return pgg;
}


Hi are you able to send the updated code? I'm also stuck.

Hello , im having the same issue with the AK60 using a seeed can bus shield. Van you help please. Ehat did you have to do to solve the issue?
Thanks

I had issue with the exit motor mode and entermotormode buf[7] = 0xFF part, both written in my code same, however one of them should be FC and another FD, void zero should be FE

1 Like

lets have a zoom call all, if you have same motor.

Send me message on akimzhan.kb@gmail.com

1 Like

Could anyone help me write a code that will work with my setup?

Arduino Mega 2560 board
CAN-BUS Shield V2.0 from SEEED
Elegoo joystick
Tmotors AK80-64

Id like to be able to say i can, but i havent been able to get it working yet either.
Theres a yourube channel called skyentific he has helpful videos one these types of actuators.

Im trying to work out why i cant get mine to work; ive now an ak 60 motor, a steadywin motor 2 seeed studio can shields, 2 arduinos, everytging works seperatly but not together. Im wondering if the seeed studio suields are an issue despite being good quality.

When i find a solution and a set up thaf works ill post on here.

I tried getting help from cube mars but that was a waste of time

I'm facing a similar issue. I've a T-motor AK70-10. I'm trying to run it on Arduino Uno with Seeed Can-Bus-Shield. My motor just won't start. I'm able to communicate with CAN but whatever I'm getting from the encoder, I'm not able to unpack that and relay it to the motor. Any help will be greatly appreciated.

This is my code:

#include <mcp_can.h>
#include <mcp_can_dfs.h>
#include <SPI.h>

MCP_CAN CAN0(10);  // Set CS to pin 10

const unsigned long encoderResolution = 4096;  // Encoder resolution (number of counts per revolution)
const unsigned long maxRPM = 6000;            // Maximum RPM of the motor
const unsigned long maxEncoderCount = encoderResolution * 60UL * maxRPM;  // Maximum encoder count for desired RPM

const double gearRatio = 10.0;    // Gear ratio of the motor
const double encoderCountsPerRevolution = encoderResolution * gearRatio;

const double Kp = 0.8;     // Proportional gain
const double Ki = 0.4;     // Integral gain
const double Kd = 0.2;     // Derivative gain

double position_desired = 0.0;   // Desired position in encoder counts
double currentPosition = 0.0;    // Current position in encoder counts
double lastPosition = 0.0;       // Previous position in encoder counts
double integral = 0.0;           // Integral term
double derivative = 0.0;         // Derivative term
double output = 0.0;             // Control signal

struct CANMessage {
  unsigned long id;
  unsigned char ext;
  unsigned char rtr;
  unsigned char len;
  unsigned char buf[8];
};

void enterControlMode() {
  unsigned char buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC};
  CAN0.sendMsgBuf(0x100, 0, 8, buf);
}

void exitControlMode() {
  unsigned char buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD};
  CAN0.sendMsgBuf(0x100, 0, 8, buf);
}

void setZeroPosition() {
  unsigned char buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE};
  CAN0.sendMsgBuf(0x100, 0, 8, buf);
}

void pack_cmd(CANMessage* msg, float p_des, float v_des, float kp, float kd, float t_ff)
{
  const float P_MIN = -95.5;
  const float P_MAX = 95.5;
  const float V_MIN = -30;
  const float V_MAX = 30;
  const float T_MIN = -18;
  const float T_MAX = 18;
  const float Kp_MIN = 0;
  const float Kp_MAX = 500;
  const float Kd_MIN = 0;
  const float Kd_MAX = 5;
  const float Test_Pos = 0.0;

  
  p_des = constrain(p_des, P_MIN, P_MAX);
  v_des = constrain(v_des, V_MIN, V_MAX);
  kp = constrain(kp, Kp_MIN, Kp_MAX);
  kd = constrain(kd, Kd_MIN, Kd_MAX);
  t_ff = constrain(t_ff, T_MIN, T_MAX);

  // Conver floats to unsigned integers //

  int p_int = map(p_des, P_MIN, P_MAX, 0, 65535);
  int v_int = map(v_des, V_MIN, V_MAX, 0, 4095);
  int kp_int = map(kp, Kp_MIN, Kp_MAX, 0, 4095);
  int kd_int = map(kd, Kd_MIN, Kd_MAX, 0, 4095);
  int t_int = map(t_ff, T_MIN, T_MAX, 0, 4095);
  unsigned char buf[8];

  // pack ints into the CAN buffer //

  buf[0] = p_int >> 8;                          // Position 8 higher
  buf[1] = p_int & 0xFF;                        // Position 8 lower
  buf[2] = v_int >> 4;                          // Speed 8 higher
  buf[3] = ((v_int & 0xF) << 4) | (kp_int >> 8); // Speed 4 bit lower KP 4 bit higher
  buf[4] = kp_int & 0xFF;                       // KP 8 bit lower
  buf[5] = kd_int >> 4;                         // Kd 8 bit higher
  buf[6] = ((kd_int & 0xF) << 4) | (kp_int >> 8); // KP 4 bit lower torque 4 bit higher
  buf[7] = t_int & 0xFF;                        // Torque 4 bit lower

  msg->id = 0x100;
  msg->len = 8;
  for(int i=0; i<8; i++)
    msg->buf[i] = buf[i];
}

void unpack_reply(CANMessage* msg) 
{
  unsigned long canId = msg->id;
  unsigned char len = msg->len;
  unsigned char buf[8];
  for(int i=0; i<8; i++)
    buf[i] = msg->buf[i];
  
  int id = buf[0];
  int p_int = (buf[1]<<8)|buf[2];
  int v_int = (buf[3]<<4)|(buf[4]>>4);
  int i_int = ((buf[4]&0xF)<<8)|buf[5];

  // convert ints to floats //

  float p = map(p_int, 0, 65535, -95.5, 95.5);
  float v = map(v_int, 0, 4095, -30, 30);
  float i = map(i_int, 0, 4095, -18, 18);

  // Process encoder data //

  currentPosition = encoder_count; // May have to change this based on the actual data format

  if(id == 1)
  {
    currentPosition = p;
  }
}

// Converts unsigned int to float, given range and number of bits //

float span = x_max - x_min;
float offset = x_min;
return ((float)x_int)*span/((float)(1<<bits)-1)) + offset;
}

void setup() 
{
  Serial.begin(9600);
  while (CAN_OK != CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ)) 
  {
    Serial.println("CAN BUS Shield init fail");
    delay(100);
  }
  Serial.println("CAN BUS Shield init ok!");

  // Enter motor control mode and set position to zero
  enterControlMode();
  setZeroPosition();
}

void loop() {
  float position_desired = 30.0;   // Desired position in degrees
  float velocity_desired = 200.0;  // Desired velocity in degrees per second
  float kp_value = 0.8;            // Proportional gain
  float kd_value = 0.2;            // Derivative gain
  float torque_feedforward = 0.0;  // Torque feedforward value

  CANMessage msg;
  pack_cmd(&msg, position_desired, velocity_desired, kp_value, kd_value, torque_feedforward);

  // Send the command over CAN-Bus
  CAN0.sendMsgBuf(msg.id, 0, msg.len, msg.buf);

  // Read feedback from the motor
  if (CAN0.readMsgBuf(&msg.id, &msg.len, msg.buf) == CAN_OK) 
  {
    unpack_reply(&msg);
  }

  // PID control
  double error = position_desired - currentPosition;
  integral += error;
  derivative = currentPosition - lastPosition;
  output = Kp * error + Ki * integral + Kd * derivative;

  // Apply the control signal to the motor here
  pack_cmd(&msg, output, velocity_desired, kp_value, kd_value, torque_feedforward);
  CAN0.sendMsgBuf(msg.id, 0, msg.len, msg.buf);

  // Update last position
  lastPosition = currentPosition;

  // Add a delay between iterations
  delay(1000);
}

If you look at the docs for map(), it states it uses integer math, not floating point. map() - Arduino Reference

Also, the receiving variable should be unsigned int to match the comment/range

Thank you for pointing that out. I changed it , it's still not working.

This is my serial monitor output:
This is all I'm getting:
Sent command to motor:
Desired position: 30.00
Desired velocity: 200.00
Kp value: 8.00
Kd value: 2.00
Torque feedforward: 1.00
Received feedback from motor:
Current position: -95.00
PID control output: 20000.00
Error: 125.00
Integral: 3750.00
Derivative: 0.00
Sent command to motor:
Desired position: 30.00

The motor is still not running