Help with the RMD X4 v3 from My Actuator using the SparkFun CANBUS Shield

Hello, I am new to this forum, so this is my first post.
I have two My Actuators RMD X4 v3 motors; I intend to use them to control the speed; the idea is to use different or equal speeds in both motors with a PD or PID controller. I am using the code of Skyentific and the same CANBUS Shield. This is the code from the video:

// demo: CAN-BUS Shield, send data
// loovee@seeed.cc

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

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

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

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

//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 = 0.0f;
float kp_in = 20.0f;
float kd_in = 1.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.9b and v1.0 is default D10
const int SPI_CS_PIN = 10;

MCP_CAN CAN(SPI_CS_PIN); // Set CS to pin 

void setup()
{ 
    SERIAL.begin(115200);
    delay(1000);
    while (CAN_OK != CAN.begin(CAN_1000KBPS))  //init can bus : baudrate = 500k
    {
        SERIAL.println("CAN BUS Shield init fail");
        SERIAL.println(" Init CAN Bus Shield again");
        delay(100);
    }
    SERIAL.println("CAN BUS Shield init ok!"); 
    
 //Initialize 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 turn 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 backward
    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)
  {
    //Disable
    ExitMotorMode();
    digitalWrite(LED2, LOW);
  }
  
  //send CAN
  pack_cmd();

  //receive CAN
  if(CAN_MSGAVAIL == CAN.checkReceive()) //check if data coming
  {
    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.print(t_out);
  }

 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] = 0xFC;
  CAN.sendMsgBuf(0x01, 0, 8, buf);
 }

 void ExitMotorMode(){
  //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] = 0xFD;
  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] = 0xFE;
  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 + 30 rad/s
  /// 12 bit kp, between 0 and 500 N-m/rad
  /// 12 bit kd, between 0 and 100 N-m/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); //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), 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);
}

void unpack_reply(){

  /// CAN Reply Packet Structure ///
  /// 16 bit position command, between -4*pi and 4*pi
  /// 12 bit velocity command, 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];
  CAN.readMsgBuf(&len, buf);

  unsigned long canId = CAN.getCanId();

  /// 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);
}

unsigned int float_to_uint(float x, float x_min, float x_max, int bits){
  /// Converts to 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.0 + offset;
  }
  if (bits == 16){
    pgg = ((float)x_int)*span/65535.0 + offset;
  }
  return pgg;
}

// END FILE

My problem is that in Arduino when I am verifying the code, I receive the error "cannot declare the variable 'CAN' to be of abstract type 'MCP_CAN.'" I know that the library is old, and this video is 2-year-olds. Which Arduino version and which library is used for this code? Or, using an updated library, how much does the code change?

Where is the link to its datasheet?

Have You checked and undrstand the code?

The advice is posting the full error report.

What is used in the video?

Try an updated library and try. No helper knows what that library would be and what would follow.

The datasheet of My Actuator RMD X4 v3 is here. I am using the Arduino 1.8.18 version. The library I am using is this one. The full error report is this.

Arduino: 1.8.18 (Windows 10), Board: "Arduino Uno"

MyactuatoV2:52:9: error: cannot declare variable 'CAN' to be of abstract type 'MCP_CAN'

 MCP_CAN CAN(SPI_CS_PIN); // Set CS to pin

         ^~~

In file included from C:\Users\...\Documents\Arduino\MyactuatoV2\MyactuatoV2.ino:4:0:

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:55:7: note:   because the following virtual functions are pure within 'MCP_CAN':

 class MCP_CAN

       ^~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:58:18: note: 	virtual void MCP_CAN::enableTxInterrupt(bool)

     virtual void enableTxInterrupt(bool enable = true) = 0;                             // enable transmit interrupt

                  ^~~~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:59:18: note: 	virtual void MCP_CAN::reserveTxBuffers(byte)

     virtual void reserveTxBuffers(byte nTxBuf = 0) = 0;

                  ^~~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:60:18: note: 	virtual byte MCP_CAN::getLastTxBuffer()

     virtual byte getLastTxBuffer() = 0;

                  ^~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:65:18: note: 	virtual byte MCP_CAN::begin(uint32_t, byte)

     virtual byte begin(uint32_t speedset, const byte clockset) = 0;                     // init can

                  ^~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:66:18: note: 	virtual byte MCP_CAN::init_Mask(byte, byte, long unsigned int)

     virtual byte init_Mask(byte num, byte ext, unsigned long ulData) = 0;               // init Masks

                  ^~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:67:18: note: 	virtual byte MCP_CAN::init_Filt(byte, byte, long unsigned int)

     virtual byte init_Filt(byte num, byte ext, unsigned long ulData) = 0;               // init filters

                  ^~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:68:18: note: 	virtual void MCP_CAN::setSleepWakeup(byte)

     virtual void setSleepWakeup(byte enable) = 0;                                       // Enable or disable the wake up interrupt

                  ^~~~~~~~~~~~~~

In file included from C:\Users\...\Documents\Arduino\MyactuatoV2\MyactuatoV2.ino:4:0:

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:70:18: note: 	virtual byte MCP_CAN::sleep()

     virtual byte sleep() = 0;                                                           // Put the MCP2515 in sleep mode

                  ^~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:71:18: note: 	virtual byte MCP_CAN::wake()

     virtual byte wake() = 0;                                                            // Wake MCP2515 manually from sleep

                  ^~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:72:18: note: 	virtual byte MCP_CAN::setMode(byte)

     virtual byte setMode(byte opMode) = 0;                                              // Set operational mode

                  ^~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:73:18: note: 	virtual byte MCP_CAN::getMode()

     virtual byte getMode() = 0;                                                         // Get operational mode

                  ^~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:74:18: note: 	virtual byte MCP_CAN::checkError(uint8_t*)

     virtual byte checkError(uint8_t* err_ptr = NULL) = 0;                               // if something error

                  ^~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:77:18: note: 	virtual byte MCP_CAN::checkReceive()

     virtual byte checkReceive(void) = 0;                                                // if something received

                  ^~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:78:18: note: 	virtual byte MCP_CAN::readMsgBufID(byte, volatile long unsigned int*, volatile byte*, volatile byte*, volatile byte*, volatile byte*)

     virtual byte readMsgBufID(byte status,

                  ^~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:82:18: note: 	virtual byte MCP_CAN::readMsgBufID(long unsigned int*, byte*, byte*)

     virtual byte readMsgBufID(unsigned long *ID, byte *len, byte *buf) = 0;

                  ^~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:83:18: note: 	virtual byte MCP_CAN::readMsgBuf(byte*, byte*)

     virtual byte readMsgBuf(byte *len, byte *buf) = 0;

                  ^~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:91:18: note: 	virtual byte MCP_CAN::trySendMsgBuf(long unsigned int, byte, byte, byte, const byte*, byte)

     virtual byte trySendMsgBuf(unsigned long id, byte ext, byte rtr,

                  ^~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:93:18: note: 	virtual byte MCP_CAN::sendMsgBuf(byte, long unsigned int, byte, byte, byte, const volatile byte*)

     virtual byte sendMsgBuf(byte status, unsigned long id, byte ext, byte rtr,

                  ^~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:95:18: note: 	virtual byte MCP_CAN::sendMsgBuf(long unsigned int, byte, byte, byte, const byte*, bool)

     virtual byte sendMsgBuf(unsigned long id, byte ext, byte rtrBit,

                  ^~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:102:18: note: 	virtual void MCP_CAN::clearBufferTransmitIfFlags(byte)

     virtual void clearBufferTransmitIfFlags(byte flags = 0) = 0;                        // Clear transmit flags according to status

                  ^~~~~~~~~~~~~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:103:18: note: 	virtual byte MCP_CAN::readRxTxStatus()

     virtual byte readRxTxStatus(void) = 0;                                              // read has something send or received

                  ^~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:104:18: note: 	virtual byte MCP_CAN::checkClearRxStatus(byte*)

     virtual byte checkClearRxStatus(byte *status) = 0;                                  // read and clear and return first found rx status bit

                  ^~~~~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:105:18: note: 	virtual byte MCP_CAN::checkClearTxStatus(byte*, byte)

     virtual byte checkClearTxStatus(byte *status, byte iTxBuf = 0xff) = 0;              // read and clear and return first found or buffer specified tx status bit

                  ^~~~~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:106:18: note: 	virtual bool MCP_CAN::mcpPinMode(byte, byte)

     virtual bool mcpPinMode(const byte pin, const byte mode) = 0;                       // switch supported pins between HiZ, interrupt, output or input

                  ^~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:107:18: note: 	virtual bool MCP_CAN::mcpDigitalWrite(byte, byte)

     virtual bool mcpDigitalWrite(const byte pin, const byte mode) = 0;                  // write HIGH or LOW to RX0BF/RX1BF

                  ^~~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:108:18: note: 	virtual byte MCP_CAN::mcpDigitalRead(byte)

     virtual byte mcpDigitalRead(const byte pin) = 0;                                    // read HIGH or LOW from supported pins

                  ^~~~~~~~~~~~~~

C:\Users\...\Documents\Arduino\MyactuatoV2\MyactuatoV2.ino: In function 'void setup()':

MyactuatoV2:58:44: error: no matching function for call to 'MCP_CAN::begin(MCP_BITTIME_SETUP)'

     while (CAN_OK != CAN.begin(CAN_1000KBPS))  //init can bus : baudrate = 500k

                                            ^

In file included from C:\Users\...\Documents\Arduino\MyactuatoV2\MyactuatoV2.ino:4:0:

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:65:18: note: candidate: virtual byte MCP_CAN::begin(uint32_t, byte)

     virtual byte begin(uint32_t speedset, const byte clockset) = 0;                     // init can

                  ^~~~~

C:\Users\...\Documents\Arduino\libraries\Seeed_Arduino_CAN-master\src/mcp_can.h:65:18: note:   candidate expects 2 arguments, 1 provided

exit status 1

cannot declare variable 'CAN' to be of abstract type 'MCP_CAN'

I don't know which version of Arduino is used in the video.

Essentially you need to download an older version of the library from Github.

How you do that is a mystery to me. A Google search points to screen shots showing you what to do, but I don't see the same thing on my screen. Perhaps there is someone else out there is more familiar with how to drive Github properly?

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