Skip to content

CAN interface

CAN bus should be your primary choice when developing robotic aplication.
Spectral micro uses 5V CAN bus that adheres to the CAN 2.0 standard. Each Spectral micro has 2 CAN bus connectors allowing you to easily daisy chain multiple devices.

drawing

Bits 10 - 7 of CAN ID represent Node ID.
Node IDs can range from 0 - 15 Meaning you can have maximum 16 different devices on one CAN bus.

Bits 6 - 1 of the CAN ID represent Command ID.
Command IDs can range from 0 - 63.

Bit 0 represents error bit. If spectral micro BLDC controller has any active error this bit will be set to 1. Note this bit is send always by the driver and is independent about the command ID and data.

Node with smallest Node ID is strongest in CAN bus arbitration.

If you want to learn more about CAN bus we recommend you read this article!

This page describes can protocol; Go to CAN bus guide for hardware setup and examples
You can use our Python CAN bus API to communicate with your Spectral BLDC controllers!
If you want to se more examples on how to write Python scripts to control your motor over CAN check this guide!

List of commands

Messages prefixed with Send are messages that the host can send to the Spectral BLDC controller. Note that to some of these messages the driver will respond with pre-defined message prefixed with Respond

Messages prefixed with Respond are messages that the Spectral BLDC controller can send to the host.

Messages prefixed with Send_Respond are messages that host can request from BLDC controller and it will respond with the desired data packet with the same Command ID as recived command. Host is sending these msgs with RTR bit and Spectral is responding with RTR 0 and some data packet.

Command ID Name Type Data
9 Respond_Heartbeat Respond None
3 Respond_data_pack_1 Respond Position [Encoder ticks]
Velocity [Encoder ticks/s]
Current [mA]
5 Respond_data_pack_2 Respond Data
7 Respond_data_pack_3 Respond Data
60 Respond_Gripper_data_pack Respond Position
Current
Gripper activation status
Gripper action status
Object detection status
Temperature error
Timeour error
Estop error
Calibration status
Command ID Name Type Data
2 Send_data_pack_1 Send Position [Encoder ticks]
Velocity [Encoder ticks/s]
Current [mA]
6 Send_data_pack_2 Send Data
8 Send_data_pack_3 Send Data
4 Send_data_pack_PD Send Position [Encoder ticks]
Velocity [Encoder ticks/s]
Current [mA]
61 Send_gripper_data_pack Send Position
Velocity
Current [mA]
Gripper activation
Gripper action
Estop status
Release direction
62 Send_gripper_calibrate Send None
16 Send_PD_Gains Send KP
KD
17 Send_Current_Gains Send Kpiq
Kiiq
18 Send_Velocity_Gains Send Kpv
Kiv
19 Send_Position_Gains Send Kpp
20 Send_Limits Send Velocity limit
Current limit
22 Send_Kt Send Kt
11 Send_CAN_ID Send CAN ID
0 Send_ESTOP Send None
12 Send_Idle Send None
13 Send_Save_config Send None
14 Send_Reset Send None
1 Send_Clear_Error Send None
15 Send_Watchdog Send Time
Action
30 Send_Heartbeat_Setup Send Time
29 Send_Cyclic_command Send Data
Command ID Name Type Respond data
23 Send_Respond_Temperature Send/Respond Temperature
24 Send_Respond_Voltage Send/Respond Vbus voltage
25 Send_Respond_Device_Info Send/Respond Serial number
Hardware version
Batch date
software version
26 Send_Respond_State_of_Errors Send/Respond Error
Temperature error
Encoder error
Vbus error
Driver error
Velocity error
Current error
ESTOP error
Calibration status
Activated status
Watchdog error
27 Send_Respond_Iq_data Send/Respond Iq current
28 Send_Respond_Encoder_data Send/Respond Position [Encoder ticks]
Velocity [Encoder ticks/s]
10 Send_Respond_Ping Send/Respond None

Watchdog

By default watchdog is turned off.
Each valid CAN message received by the spectral BLDC resets its watchdog timer.
Watchdog measures time between the commands that spectral BLDC receives.
If it is bigger than time you set it will report Watchdog error and go to error mode. To clear the error you will need to call:

"Send_Clear_Error"

Heartbeat

By default heartbeat will send data at 1Hz or every 1 second.
Hearbeat is function that will Send "Respond_Heartbeat" msg every time interval you set in "Send_Heartbeat_Setup".
This is usefull when your host device needs to see if spectral BLDC is connected/alive.
In case your spectral BLDC sends any other data (as a response to command) it will reset its heartbeat timer.

Heartbeat timer reset

For example if spectral BLDC is sending data every 10ms and heartbeat is setup to send every 1s; hearbeat will never send its data.

Cyclic

TODO

Commands

Respond_Heartbeat

This is the command that driver will send as its heartbeat every X ms. It is an empty data frame.

  • Command ID: 9
  • Direction: BLDC driver -> host
  • Python call: None, this command is sent only by driver
  • Length: 0 byte
  • Type of frame: standard

Respond_data_pack_1

This is the command that driver will send as a response to movement commands like Send_data_pack_1 and Send_data_pack_PD.

  • Command ID: 3
  • Direction: BLDC driver -> host
  • Python call: None, this command is sent only by driver
  • Length: 8 byte
  • Type of frame: standard
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 - 2 position signed 24bit unit is encoder ticks
3 - 5 velocity signed 24bit unit is encoder ticks /s
6 - 7 current signed 16bit unit is mA

Respond_Gripper_data_pack

This is the command that driver will send as a response to Send_gripper_data_pack.

  • Command ID: 60
  • Direction: BLDC driver -> host
  • Python call: None, this command is sent only by driver
  • Length: 4 byte
  • Type of frame: standard
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 gripper_position unsigned 8bit 255 fully closed, 0 fully open
1-2 gripper_current 16 bit signed 0 min current, 1300 max current, unit mA
3(bit 0) gripper_activated bit (0/1) gripper activate (1) / deactivated (0)
3(bit 1) gripper_action_status bit (0/1) 1 is goto, 0 is idle or performing auto release or in calibration
3(bit 2 and 3) gripper_object_detection 2 bit 0 in motion, 1 object detected closing, 2 object detected opening, 3 at positon
3(bit 4) gripper_temperature_error bit (0/1) gripper_temperature_error
3(bit 5) gripper_timeout_error bit (0/1) gripper_timeout_error
3(bit 6) gripper_estop_error bit (0/1) gripper_estop_error
3(bit 7) gripper_calibrated bit (0/1) gripper calibration status; calibrated (1) / not calibrated (0)

Send_data_pack_1

This command will place the driver in position, speed or current control mode depending on the amount of paramters you give it.
Note that if you dont want feedforward just set it to 0.

  • Command ID: 2
  • Direction: Host -> BLDC driver
  • Python call: Send_data_pack_1()
  • Type of frame: standard
  • Lenght: 8 byte - If using positon setpoint with speed and current feedforward
Size (bytes) Variable Type Details
0 - 2 Position setpoint signed 24bit unit is encoder ticks
3 - 5 Velocity feedforward signed 24bit unit is encoder ticks/s
6 - 7 Current feedforward signed 16bit unit is mA
  • Lenght: 5 byte - If using speed setpoint and current feedforward
Size (bytes) Variable Type Details
0 - 2 Velocity setpoint signed 24bit unit is encoder ticks/s
3 - 5 Current feedforward signed 16bit unit is mA
  • Lenght: 2 byte - If using current setpoint
Size (bytes) Variable Type Details
0 - 1 Current setpoint signed 16bit unit is mA

Driver will respons to this command with:
Respond_data_pack_1


Send_data_pack_PD

This command will place the driver in impedance PD control mode.

  • Command ID: 4
  • Direction: Host -> BLDC driver
  • Python call: Send_data_pack_PD()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable Type Details
0 - 2 Position signed 24bit unit is encoder ticks
3 - 5 Velocity signed 24bit unit is encoder ticks/s
6 - 7 Current signed 16bit unit is mA

Driver will respond to this command with:
Respond_data_pack_1


Send_gripper_data_pack

This command will command the motor (SSG48 gripper) to move to specific position with speed/torque.

  • Command ID: 61
  • Direction: Host -> BLDC driver
  • Python API reference: Send_gripper_data_pack()
  • Type of frame: standard
  • Length: 5 byte
Size (bytes) Variable Type Details
0 Position unsigned 8bit 0 fully open, 255 fully closed
1 Velocity unsigned 8bit 0 min speed, 255 max speed
2-3 Current signed 16bit 0 min current, 1300 max current, unit mA
4(bit 0) Gripper activate bit (0/1) 0 deactivate the gripper, 1 activate the gripper
4(bit 1) Gripper action status bit (0/1)
4(bit 2) Gripper estop status bit (0/1)
4(bit 3) Gripper release direction bit (0/1)

Driver will respond to this command with:
Respond_Gripper_data_pack

Alternatively you can send empty Send_gripper_data_pack command.

  • Command ID: 61
  • Direction: Host -> BLDC driver
  • Python API reference: Send_gripper_data_pack()
  • Type of frame: standard
  • Length: 0 byte

Driver will respons to this command with:
Respond_Gripper_data_pack


Send_gripper_calibrate

This command will start gripper calibration. It is an empty data frame.

  • Command ID: 62
  • Direction: Host -> BLDC driver
  • Python API reference: Send_gripper_calibrate()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_PD_Gains

This command will set KP and KD gains for the PD impedance loop.

  • Command ID: 16
  • Direction: Host -> BLDC driver
  • Python API reference: Send_PD_Gains()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable Type
0 - 3 KP float 32
4 - 7 KD float 32

Driver will not respond to this command!


Send_Current_Gains

This command will set Ki and Kp PI parameters for the PI current control loop.

  • Command ID: 17
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Current_Gains()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable Type
0 - 3 Kp_iq float 32
4 - 7 Ki_iq float 32

Driver will not respond to this command!


Send_Velocity_Gains

This command will set Ki and Kp PI parameters for the PI speed/velocity control loop.

  • Command ID: 18
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Velocity_Gains()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable Type
0 - 3 Kpv float 32
4 - 7 Kiv float 32

Driver will not respond to this command!


Send_Position_Gains

This command will set Kp P parameter for the P position control loop.

  • Command ID: 19
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Position_Gains()
  • Type of frame: standard
  • Length: 4 byte
Size (bytes) Variable Type
0 - 3 Kpp float 32

Driver will not respond to this command!


Send_Limits

This command will set velocity/speed and current limits.
This will limit max speed and current that can be reached during motor operation.

  • Command ID: 20
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Limits()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable Type Details
0 - 3 Velocity limit float 32 unit is encoder ticks/s
3 - 7 Current limit float 32 unit is mA

Driver will not respond to this command!


Send_Kt

This command will set Kt of the motor driver.

  • Command ID: 22
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Kt()
  • Type of frame: standard
  • Length: 4 byte
Size (bytes) Variable Type
0 - 3 Kt float 32

Driver will not respond to this command!


Send_CAN_ID

This command will set a new CAN ID for your motor driver.
Note that ID you send is the new motor ID.

  • Command ID: 11
  • Direction: Host -> BLDC driver
  • Python API reference: Send_CAN_ID()
  • Type of frame: standard
  • Length: 1 byte
Size (bytes) Variable Type
0 ID byte

Driver will not respond to this command!


Send_ESTOP

This command will stop the motor and set ESTOP error to 1.
It is an empty data frame.

  • Command ID: 0
  • Direction: Host -> BLDC driver
  • Python API reference: Send_ESTOP()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_Idle

This command will set the motor driver to idle state.
It is an empty data frame.

  • Command ID: 12
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Idle()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_Save_config

This command will save the current motor config to the EEPROM.
It is an empty data frame.

  • Command ID: 13
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Save_config()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_Reset

This command will reset the MCU of the motor driver.
It is an empty data frame.

  • Command ID: 14
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Reset()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_Clear_Error

This command will clear all active errors of the motor driver.
It is an empty data frame.

  • Command ID: 1
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Clear_Error()
  • Type of frame: standard
  • Length: 0 byte

Driver will not respond to this command!


Send_Watchdog

This command will set Watchdog parameters like watchdog time and action.

  • Command ID: 15
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Watchdog()
  • Type of frame: REMOTE
  • Length: 5 byte
Size (bytes) Variable Type Details
0 - 3 watchdog_time_ms int
4 Action int *Not implemented

Send_Heartbeat_Setup

This command will set heartbeat paramters of the motor driver.

  • Command ID: 30
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Heartbeat_Setup()
  • Type of frame: REMOTE
  • Length: 4 byte
Size (bytes) Variable Type
0 - 3 Heartbeat_rate_ms int

Send_Cyclic_command

TODO


Send_Respond_Temperature

This command will request that motor driver responds with its current temperature. (Temperature of the thermistor).
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 23
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Temperature()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 23
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Temperature()
  • Type of frame: standard
  • Length: 2 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 - 1 temperature 16 bit signed unit of degrees

Send_Respond_Voltage

This command will request that motor driver responds with its current supply voltage.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 24
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Voltage()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 24
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Voltage()
  • Type of frame: standard
  • Length: 2 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 - 1 voltage 16 bit unsigned unit of mV

Send_Respond_Device_Info

This command will request that motor driver responds with its version information saved in the EEPROM.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 25
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Device_Info()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 25
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Device_Info()
  • Type of frame: standard
  • Length: 7 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 HARDWARE_VERSION byte harware version of the driver
1 BATCH_DATE byte date when the batch was produced
2 SOFTWARE_VERSION byte version of the software on the driver
3 - 6 SERIAL_NUMBER 32 bit serial number of the driver

Send_Respond_State_of_Errors

This command will request that motor driver responds with state of all possible errors.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 26
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_State_of_Errors()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 26
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_State_of_Errors()
  • Type of frame: standard
  • Length: 2 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0(bit 0) error bit (0/1) General error
0(bit 1) temperature_error bit (0/1)
0(bit 2) encoder_error bit (0/1)
0(bit 3) vbus_error bit (0/1)
0(bit 4) driver_error bit (0/1)
0(bit 5) velocity_error bit (0/1)
0(bit 6) current_error bit (0/1)
0(bit 7) estop_error bit (0/1)
1(bit 0) calibrated bit (0/1)
1(bit 0) activated bit (0/1)
1(bit 0) watchdog_error bit (0/1)

Send_Respond_Iq_data

This command will request that motor driver responds with current Iq current data.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 27
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Iq_data()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 27
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Iq_data()
  • Type of frame: standard
  • Length: 2 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 - 1 current signed 16bit unit is mA

Send_Respond_Encoder_data

This command will request that motor driver responds with current encoder position and speed data.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 28
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Encoder_data()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 28
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Encoder_data()
  • Type of frame: standard
  • Length: 8 byte
Size (bytes) Variable (Spectral_BLDC Lib python attribute) Type Details
0 - 3 position signed 32bit unit is encoder ticks
4 - 7 velocity signed 32bit unit is encoder ticks/s

Send_Respond_Ping

This command will request that motor driver responds with its own ping.
Direction host -> driver is remote frame and direction driver -> host is standard data frame.

  • Command ID: 10
  • Direction: Host -> BLDC driver
  • Python API reference: Send_Respond_Ping()
  • Type of frame: REMOTE
  • Length: 0 byte

Driver respond to this command with:

  • Command ID: 10
  • Direction: BLDC driver -> Host
  • Python API reference: Send_Respond_Ping()
  • Type of frame: standard
  • Length: 0 byte

More about CAN

In CAN (Controller Area Network) communication, each byte of data within a CAN frame is transmitted as a sequence of bits. Each bit is transmitted serially, starting with the least significant bit (LSB) and ending with the most significant bit (MSB).

So, if you send a byte with the value 0b10110000, it will be transmitted over the CAN bus as follows:

  • Start Bit: The start bit is transmitted first (LSB).
  • Data Bits: The data bits are transmitted serially, starting with the LSB (bit[0] = 0) and ending with the MSB (bit[7] = 1).

Therefore, in the case of your byte 0b10110000, it will be transmitted as follows:

Start Bit | Data Bits (LSB first)

0 | 0 0 0 0 1 1 0 1

transmition of bytes is LSB byte first. So if we have data packet of 4 bytes; byte 3,2,1,0; byte 3 will be sent first and byte 0 last.

Data is packed in arrays so that for 16 bit number, 8 MSB bits go to array index 0 and 8 LSB bits go to array index 1.
When transmitting that data If you look here: https://en.wikipedia.org/wiki/CAN_bus LSB are sent first so array element with index 1 is transmitted first.
So if we have number that is 32814 decimal: MSB byte[0] = 1000 0000 , LSB byte[1] = 0101 1010
It will be sent like this 0101 1010 0000 0001

Transmitting floats is following the IEEE 754 floating-point format.

In IEEE 754 format, a single-precision floating-point number (float) is represented using 32 bits, with the following components:

Sign bit: 1 bit, representing the sign of the number.
Exponent bits: 8 bits, representing the exponent of the number.
Fraction bits: 23 bits, representing the fractional part of the number.
The function you provided interprets the input array of 4 bytes as a 32-bit integer and then uses a union to reinterpret those bits as a float. The bit manipulation
performed by shifting the bytes and combining them respects the layout of IEEE 754 floating-point numbers, assuming that the byte order of the system is big-endian.

Therefore, this function can be used to convert an array of 4 bytes representing a IEEE 754 float to its equivalent floating-point value.