OpenRobot Motor CAN Protocol

OpenRobot MC Custom Firmware — CAN Communication Specification   GitHub Repository
Version 14 — 2026-03-26  |  by Dongil Choi

Change Logs

24-11-13

24-11-18

24-12-12 (서울과기대, 국민대 방문, 요구사항 수렴)

25-01-14

변경사항: MOTOR_OFF, MOTOR_STOP, MOTOR_START, TORQUE_CLOSED_LOOP, SPEED_CLOSED_LOOP, POSITION_CLOSED_LOOP, SET_MULTITURN_POSITION 제어 모두 한번 명령을 전달하면 그 값이 유지되는 것으로 바꿈. 기존엔 몇몇 제어는 반복적으로 명령을 보내줘야만 제어가 유지되던 것을 일괄적으로 1회 전달된 명령이 유지되는 것으로 바꾸었음.

25-05-15

26-02-09 (v9)

26-02-11 (v10)

26-02-23 (v11)

26-03-05 (v12)

26-03-18 (v13)

26-03-26 (v14)

General

ItemValue
CAN ID0x140 + Motor_ID
Frame TypeStandard (SID)
DLC8 bytes (fixed)
Byte OrderLittle-Endian

Motor Direction Inversion

MCCONF의 m_invert_direction 설정이 CAN 경계에서 자동 적용된다.

입력 반전 (TX): MIT Control (0xC0)의 p_des/v_des/t_ff, DPS (0xA2), Position (0xA3/0xA4), Servo 명령에 mc_interface_get_motor_dir() 적용.
출력 반전 (RX): 모든 응답의 vel_dps (Motor Speed) 필드에 방향 반전 적용.
비반전: Torque (0xA1), Duty (0xA5), eRPM (0xA2 mode=1)은 mc_interface_* API를 경유하므로 내부에서 자동 반전됨. MIT의 Kp/Kd 게인은 항상 양수이므로 반전 안함.

Motor Status Response Format

공통 응답 포맷 — 0xA1~0xA4, 0x9C, 0xC0 명령에 공통 적용

ByteFieldTypeUnitNote
DATA[0]Command IDuint8Echo
DATA[1]Motor Temperatureint81 °C / LSB
DATA[2-3]Torque Current (Iq)int16−2048~2048 = −33A~33A
DATA[4-5]Motor Speedint161 dps / LSB
DATA[6-7]Encoder Positionuint1614-bit, offset appliedCNT2DEG = 360/16384

TX CAN Protocols Summary

Command Message for controller (Message ID = 0x140 + Motor ID)

DescriptionDATA[0]DATA[1]DATA[2]DATA[3]DATA[4]DATA[5]DATA[6]DATA[7]
Read PID data0x30NULLNULLNULLNULLNULLNULLNULL
Write PID to ROM0x32NULLPosition loop KpPosition loop KiPosition loop Kd
Read encoder data0x90NULLNULLNULLNULLNULLNULLNULL
Write encoder offset0x91NULLNULLNULLNULLNULLEncoder offset
Write current pos as zero0x19NULLNULLNULLNULLNULLNULLNULL
Read multi turns angle0x92NULLNULLNULLNULLNULLNULLNULL
Read Motor Status 20x9CNULLNULLNULLNULLNULLNULLNULL
Read Motor Status 30x9DNULLNULLNULLNULLNULLNULLNULL
Motor off0x80NULLNULLNULLNULLNULLNULLNULL
Motor stop0x81NULLNULLNULLNULLNULLNULLNULL
Motor running0x88NULLNULLNULLNULLNULLNULLNULL
Torque closed-loop0xA1NULLNULLNULLTorque current ctrlDamping Const
Speed closed-loop0xA2speed_modeNULLNULLspeed control (int32)
Position closed-loop 10xA3NULLNULLNULLPosition control (int32)
Set Multiturn position0xA4NULLSpeed limitPosition control (int32)
Duty Closed-Loop0xA5NULLNULLNULLDuty (int16)NULLNULL
Read Fault Code0xB0NULLNULLNULLNULLNULLNULLNULL
Clear Error Flag0x9BNULLNULLNULLNULLNULLNULLNULL
Read Max Current0xB1NULLNULLNULLNULLNULLNULLNULL
Write Max Current to ROM0xB2oc_modeMotor Curr. MaxMotor Curr. Abs MaxBat Curr. Max
MIT Control0xC0p_des (16bit)v_hi (8bit)v_lo4|kp_hi4kp_lo (8bit)Kd (8bit)τ_ff (8bit)
MIT Enter Motor Mode0xC1NULLNULLNULLNULLNULLNULLNULL
MIT Exit Motor Mode0xC2NULLNULLNULLNULLNULLNULLNULL
Clear Error Flag0x9BNULLNULLNULLNULLNULLNULLNULL
MIT Set Zero Position0xC3NULLNULLNULLNULLNULLOffset (int16)
Read MIT Params0xC4NULLNULLNULLNULLNULLNULLNULL
Write MIT Params to ROM0xC5v_maxt_maxKt_input (uint16)GR (uint16)NULL
Read External Sensor0xD0NULLNULLNULLNULLNULLNULLNULL

RX CAN Protocols Summary

DescriptionDATA[0]DATA[1]DATA[2]DATA[3]DATA[4]DATA[5]DATA[6]DATA[7]
Read PID data0x300x00Position loop KpPosition loop KiPosition loop Kd
Write PID to ROM0x320x00Position loop KpPosition loop KiPosition loop Kd
Read encoder data0x90Motor_tempEncoder positionEncoder originalEncoder offset
Write encoder offset0x910x000x000x000x000x00Encoder offset
Write current pos as zero0x190x000x000x000x000x00Encoder offset
Read multi turns angle0x92Multi-turn Angle (7 bytes LE)
Read Motor Status 20x9CMotor_tempTorque CurrentSpeedEncoder Pos
Read Motor Status 30x9DControl ModePhase A CurrPhase B CurrPhase C Curr
Motor off0x800x000x000x000x000x000x000x00
Motor stop0x810x000x000x000x000x000x000x00
Motor running0x880x000x000x000x000x000x000x00
Torque closed-loop0xA1Motor_tempTorque CurrentSpeedEncoder Pos
Speed closed-loop0xA2Motor_tempTorque CurrentSpeedEncoder Pos
Position closed-loop 10xA3Motor_tempTorque CurrentSpeedEncoder Pos
Set Multiturn position0xA4Motor_tempTorque CurrentSpeedEncoder Pos
Duty Closed-Loop0xA5Motor_tempTorque CurrentSpeedEncoder Pos
Read Fault Code0xB0Code1Code2Code3Code4Code5Code6Code7
Read Max Current0xB1oc_modeMotor Curr. MaxMotor Curr. Abs MaxBat Curr. Max
Write Max Current to ROM0xB2oc_modeMotor Curr. MaxMotor Curr. Abs MaxBat Curr. Max
Clear Error Flag0x9BFault Code0x000x000x000x000x000x00
MIT Control0xC0Motor_tempTorque CurrentSpeed (out dps)Position (int16, ±12.56rad)
MIT Enter Motor Mode0xC10x000x000x000x000x000x000x00
MIT Exit Motor Mode0xC20x000x000x000x000x000x000x00
MIT Set Zero Position0xC30x000x000x000x000x00Offset echo
Read MIT Params / Write MIT Params0xC4v_maxt_maxKt_out (uint16)GR (uint16)0x00
Read External Sensor0xD0validTemperaturePressureAtmosphere
0xC4/0xC5 Kt 주의: TX (Write 0xC5)에서는 모터단 Kt_input을 보내고, RX 응답에서는 출력단 Kt_out (= Kt_input × GR)을 반환한다. 상세 내용은 Command Details 참조.

Command Summary

IDCommandTypeReturns Status?
0x30Read PID DataReadNo (PID gains)
0x32Write PID to ROMWriteNo (echo)
0x90Read Encoder DataReadNo (encoder only)
0x91Write Encoder OffsetWriteNo (echo)
0x19Write Current Pos as ZeroWriteNo (offset)
0x92Read Multi-Turn AngleReadNo (angle only)
0x9CRead Motor Status 2ReadYes
0x9DRead Motor Status 3ReadYes (phase currents)
0x80Motor OffControlNo (ACK)
0x81Motor StopControlNo (ACK)
0x88Motor Running (Start)ControlNo (ACK)
0xA1Torque Closed-LoopControlYes
0xA2Speed Closed-LoopControlYes
0xA3Position Closed-Loop 1ControlYes
0xA4Set Multiturn PositionControlYes
0xA5Duty Closed-LoopControlYes
0xB0Read Fault CodeReadNo (fault codes)
0xB1Read Max CurrentReadNo (current limits)
0xB2Write Max Current to ROMWriteNo (echo)
0xC0MIT ControlControlYes
0xC1MIT Enter Motor ModeControlNo (ACK)
0xC2MIT Exit Motor ModeControlNo (ACK)
0x9BClear Error FlagWriteNo (fault_code after clear)
0xC3MIT Set Zero PositionWriteNo (ACK + offset echo)
0xC4Read MIT ParamsReadNo (MIT params)
0xC5Write MIT Params to ROMWriteNo (echo as 0xC4)
0xD0Read External SensorReadNo (sensor data)

Command Details


0x30 Read PID Data

Read position PID gains.

TX: [0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeScale
DATA[0]0x30uint8
DATA[1]0x00
DATA[2-3]Kpint16×1000 (0.001/LSB)
DATA[4-5]Kiint16×100000 (0.00001/LSB)
DATA[6-7]Kdint16×100000 (0.00001/LSB)
부연설명
모터 Position Control 시 사용하는 PID Gain 값으로 RMD x6-s2(36:1) 모터의 Default 값은 아래와 같다.
Kp = 0.02  |  Ki = 0.0002  |  Kd = 0.0002

0x32 Write PID to ROM

Write position PID gains to EEPROM (persistent).

TX: [0x32, 0x00, Kp_lo, Kp_hi, Ki_lo, Ki_hi, Kd_lo, Kd_hi]

RX: Echo of TX

Do NOT send faster than 100Hz (EEPROM write latency).
부연설명
모터 Position Control 시 사용하는 PID Gain 값을 모터제어기 Microprocessor의 EEPROM에 저장한다. 저장된 값은 전원이 꺼진 이후에도 사라지지 않고 유지된다. 다만, Firmware를 VESC-Tool로 업데이트한 경우 EEPROM 값이 초기화된다.
주의: EEPROM의 경우, 저장하는데 소요되는 시간이 있어 본 명령을 100Hz 이상 빠르게 반복해서 보내는 것은 지양해야 한다.

0x90 Read Encoder Data

TX: [0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeNote
DATA[0]0x90uint8
DATA[1]Motor Tempint81 °C / LSB
DATA[2-3]Encoder Positionuint16original − offset
DATA[4-5]Encoder Originaluint16raw (0–360°)
DATA[6-7]Encoder Offsetuint16
부연설명
모터 엔코더 데이터로 Magnetic 엔코더의 결과값에 해당한다. Magnetic 엔코더의 특성상 Encoder original position 값은 0~360도 값이 출력된다. Encoder offset 값은 사용자가 지정한 offset값으로 0~360도 값에 해당한다. Encoder Position 값은 Encoder original position에서 Encoder offset 값을 뺀 값이다.

예시: Encoder offset = 100도이고 Encoder original position이 260도이면 Encoder position은 160도가 출력된다. 이 경우, Encoder original position이 0~360도 범위에서 값을 가지고 Encoder offset = 100도 이기 때문에 Encoder position 값은 -100~260도 범위를 가짐을 유념해야한다.

0x91 Write Encoder Offset

TX: [0x91, 0x00, 0x00, 0x00, 0x00, 0x00, Offset_lo, Offset_hi]

RX: Echo of TX

Do NOT send faster than 100Hz.
부연설명
Encoder offset 값은 사용자가 지정한 offset 값으로 DEG 값으로 0~360 범위에 있고 EEPROM에 저장되며 전원이 나가도 유지된다. VESC-Tool로 펌웨어를 업데이트한 경우 EEPROM이 초기화 된다. 다만, 펌웨어 업데이트를 VESC-Tool이 아닌 ST-Link로 JTAG Port를 통해서 하면 EEPROM 값이 유지된다.
주의: EEPROM의 경우, 저장하는데 소요되는 시간이 있어 본 명령을 100Hz 이상 빠르게 반복해서 보내는 것은 지양해야 한다.

0x19 Write Current Position to ROM as Motor Zero

TX: [0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
RX: [0x19, 0x00, 0x00, 0x00, 0x00, 0x00, Offset_lo, Offset_hi]
Do NOT send faster than 100Hz.
부연설명
Encoder offset 값을 지정하여 EEPROM에 저장시킨다. 로봇을 정해진 원점에 위치시키고 본 명령어를 이용하여 그 위치를 Offset으로 지정시키면 Encoder position과 Multi-turn Angle이 그 위치에서 0도가 된다. 본 값은 전원이 꺼진 이후에도 유지되며 단, VESC-Tool을 이용한 펌웨어 업데이트를 하면 초기화된다.
주의: EEPROM의 경우, 저장하는데 소요되는 시간이 있어 본 명령을 100Hz 이상 빠르게 반복해서 보내는 것은 지양해야 한다.

0x92 Read Multi-Turn Angle

TX: [0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeNote
DATA[0]0x92uint8
DATA[1-7]Motor Angleint64 (7 bytes LE)0.01 deg/LSB, cumulative
부연설명
Encoder 값을 누적시켜 Multi-turn Angle 값을 DEG 값으로 출력한다. 본 값은 Encoder offset 값을 적용하여 계산되며 전원이 꺼진 이후에도 저장된다. 단, VESC-Tool을 이용한 펌웨어 업데이트시 초기화 된다.

0x9C Read Motor Status 2

Read-only status query. Returns same motor status format as 0xA1~0xA4 without commanding any motion. Safe for continuous polling.

TX: [0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX: Standard Motor Status Response format

ByteFieldTypeUnitNote
DATA[0]0x9Cuint8Echo
DATA[1]Motor Temperatureint81 °C / LSB
DATA[2-3]Torque Current (Iq)int16−2048~2048 = −33A~33A
DATA[4-5]Motor Speedint161 dps / LSB
DATA[6-7]Encoder Positionuint1614-bit, offset appliedCNT2DEG = 360/16384
Use case: Real-time monitoring, data logging, graph plotting. Can be sent at high rates (up to 1 kHz) without affecting motor operation.

0x9D Read Motor Status 3

Read-only status query returning control mode and phase currents (A/B/C). Based on RMD protocol 0x9D with control_mode added in DATA[1] (originally NULL).

TX: [0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeUnitNote
DATA[0]0x9Duint8Echo
DATA[1]Control Modeuint8enumSee table below
DATA[2-3]Phase A Currentint161A / 64 LSBiA = i_alpha
DATA[4-5]Phase B Currentint161A / 64 LSBiB = −0.5·i_alpha + √3/2·i_beta
DATA[6-7]Phase C Currentint161A / 64 LSBiC = −(iA + iB)

Control Mode Values:

ValueModeCAN Command Origin
0NONE_CONTROLInitial state
1MOTOR_RELEASE0x80 Motor Off
2CURRENT_BRAKECurrent brake
3DUTY_CONTROL0x88 Motor Start
4CURRENT_CONTROL0xA1 Torque
5DAMPED_CURRENT_CONTROL0xA1 w/ damping_kd
7POSITION_CONTROL_ACCUM0xA3 Direct PID
8DPS_CONTROL_TIMEOUTSpeed timeout
9DPS_CONTROL_DURATION0xA2 Speed (mode=0) / 0x81 Stop
10SERVO_CONTROL0xA4 / or_limit redirect
11TRAJ_CONTROLTrajectory
12MIT_CONTROL_MODE0xC0 MIT Control
Use case: Control mode monitoring (or_limit mode transitions, Direct PID ↔ Servo), phase current analysis. Polled alongside 0x9C for combined status + phase data. or_limit redirect visible as 10→7 (SERVO→Direct PID) transition on control mode graph.

0x80 Motor Off

Turns off motor output, clears operating state and accumulated position.

TX: [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX: Echo (all zeros)

부연설명
모터제어를 위한 모든 명령을 OFF 상태로 만든다. 모터를 Free 한 상태로 Release 한다.

0x81 Motor Stop

Stops motor (speed = 0) but retains operating state. Can be resumed.

TX: [0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX: Echo (all zeros)

부연설명
모터를 SPEED = 0 상태로 제어하여 모터가 멈추도록 한다. 단, 이는 위치제어가 아닌 속도제어를 이용하기 때문에 외력이 크게 가해지면 자기 위치를 유지하지 않고 damping이 큰 상태로 천천히 움직일 수 있다. 그러므로 만약, 모터의 완전한 Position Lock을 하기 원한다면 SET Multiturn POS를 이용해야 한다.

0x88 Motor Running (Start)

Resume from stop state. Sets duty = 0 (brake mode).

TX: [0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX: Echo (all zeros)

부연설명
모터를 Duty = 0 상태로 만든다. Duty = 0 상태는 약간의 Damping 이 들어간 상태로 생각하면 된다. RMD 제어 프로토콜을 따라서 만들기는 했으나, OpenRobot MC 제어기에서는 그다지 쓰임새가 없는 제어상태라고 볼 수 있다. 일종의 Brake 상태라고 볼 수는 있다.

0xA1 Torque Closed-Loop

TX:

ByteFieldTypeNote
DATA[0]0xA1uint8
DATA[1]0x00reserved
DATA[2-3]0x0000reserved
DATA[4-5]iqControlint16−2048~2048 = −33A~33A
DATA[6-7]damping_kdint160~100 (100 = max damping)
Current = iqControl + damping_kd × motor_speed_rps

RX: Motor Status Response Format

부연설명
모터 전류제어 Loop으로 다음 식으로 제어한다.
Current = (Torque current control value) + (Damping Constant value) × (motor_speed_rps)

Damping 토크 기능을 추가하였으며 Damping의 크기는 Damping Constant(0~100의 값)로 지정하며 100이 가장 Damping이 크다. RMD x6-s2 (36:1) 모터의 경우, 10정도가 Default 값으로 적당했다.
주의: Return 데이터중 Encoder position은 offset 값이 적용된 값이다.

0xA2 Speed Closed-Loop

Supports two speed control modes selectable via DATA[1].

TX:

ByteFieldTypeNote
DATA[0]0xA2uint8
DATA[1]speed_modeuint80 = DPS (default), 1 = eRPM
DATA[2-3]0x0000reserved
DATA[4-7]speedControlint32mode 0: 0.01 dps/LSB, mode 1: 1 eRPM/LSB

speed_mode values:

ValueModeControl LoopUnitDescription
0DPSOpenRobot custom0.01 dps/LSB위치제어 기반 사다리꼴 프로파일 속도제어 (기본값)
1eRPMVESC built-in PID1 eRPM/LSBVESC 내장 PID 속도제어 루프 (mc_interface_set_pid_speed)

RX: Motor Status Response Format (동일)

부연설명 — Mode 0: DPS 제어 (기본값)
모터 속도제어 Loop으로 Degree/sec 속도값을 보낸다. 일명 DPS 제어라고 불리는 제어방식을 사용하며 일반적인 속도제어와는 다르게 위치제어를 기반으로 한 속도제어를 수행한다. 이는 위치제어를 하는 과정에서 위치 목표값을 주어진 속도 reference 를 따라갈 수 있도록 사다리꼴 Profile을 이용하여 제어한다.

기본적으로 위치제어 상태에서 속도를 제어하기 때문에 매우 저속에서부터 고속까지 정확한 속도제어가 가능하다. 다만, 고속의 속도제어의 경우, 위치제어의 PID Gain 값에 따라 제어 안정성 (Overshoot 등)에 차이가 있는데 RMD x6-s2 (36:1) 모터의 경우 0~8000 DPS 값에 대해서는 안정적으로 작동한다.
주의: 사다리꼴 Profile에서는 가속도값과 최대 속도값을 지정할 수 있는데 이는 펌웨어 상에 일반적으로 적당한 값으로 세팅되어 있으나 모터에 따라 별도의 튜닝이 필요할 수 있다.
부연설명 — Mode 1: eRPM 제어 (VESC 내장)
VESC에 기본 탑재된 PID 속도제어 루프를 사용한다. eRPM (electrical RPM) 단위로 속도 명령을 보내며, VESC-Tool의 Speed PID 설정(Kp, Ki, Kd 등)에 의해 제어 성능이 결정된다. DPS 모드와 달리 위치제어 기반이 아닌 순수 속도 PID 제어이므로, 고속 영역에서의 응답 특성이 다르다.

VESC timeout 메커니즘이 적용되므로 주기적으로 명령을 보내거나, 1회 전송 후 유지되도록 설정해야 한다.
하위 호환: 기존 DATA[1]=0x00으로 전송하던 코드는 변경 없이 DPS 모드(mode=0)로 동작합니다.

0xA3 Position Closed-Loop 1 (Multi-turn, Direct PID)

Direct position PID control. No velocity limiting — large steps cause full current output immediately.

TX:

ByteFieldTypeNote
DATA[0]0xA3uint8
DATA[1-3]0x000000reserved
DATA[4-7]angleControlint320.01 deg / LSB

RX: Motor Status Response Format

WARNING: No velocity ramping. Large position jumps cause instantaneous max current output, which can damage DRV/FET. Use or_limit safety limiter or prefer 0xA4 for large moves.
부연설명
Encoder offset를 고려한 위치에 대해 Multi-turn 위치제어를 수행한다. DPS_LIMIT 없이 PID제어가 직접적으로 적용되는 방식임.

(v8 변경사항) Set multiturn pos 를 이용한 위치제어가 offset error 가 해결될 수 없는 구조로 되어 있음을 발견, 이를 해결하기위해 Position closed-loop1 을 multiturn 방식으로 바꾸고, dps_limit 없이 직접 PID 제어되도록 수정함. → PID 제어시에는 Position closed-loop1 을 사용하기를 추천함.

0xA4 Set Multiturn Position (DPS-limited)

Position control with velocity limiting via servo controller. Recommended for large position moves.

TX:

ByteFieldTypeNote
DATA[0]0xA4uint8
DATA[1]0x00reserved
DATA[2-3]maxSpeeduint161 dps / LSB (1~25000)
DATA[4-7]angleControlint320.01 deg / LSB

RX: Motor Status Response Format

부연설명
Encoder offset를 고려한 위치에 대해 Multi-turn 위치제어를 수행한다. 모터를 초기위치에 놓고 그 위치를 offset 값으로 지정하면 그 위치는 Multi-turn 0도 위치가 된다.

Multi-turn 위치제어를 하다가 바로 Torque 제어, Speed 제어로 변경이 가능하며 그 반대로 가능하다.
주의: Multi-turn 위치제어는 한번 명령이 들어가면 위치제어가 계속 유지되며 모터를 풀고자 하면 Motor Off 명령어로 Release를 해야 한다.

0xB0 Read Fault Code

TX: [0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldNote
DATA[0]0xB0
DATA[1-7]Fault codes 1~7Oldest to newest
부연설명
모터제어기 전원인가후 발생한 Fault Code를 최대 7개 값까지 읽을 수 있다. Fault Code 1이 가장 오래된 값이며, Fault Code 7이 가장 최신값이다. 7개 초과된 Fault Code 값은 누락된다.

Fault Code Table (10진수값):

CodeFaultCodeFault
0NONE14FLASH_CORRUPTION
1OVER_VOLTAGE15HIGH_OFFSET_CURRENT_SENSOR_1
2UNDER_VOLTAGE16HIGH_OFFSET_CURRENT_SENSOR_2
3DRV17HIGH_OFFSET_CURRENT_SENSOR_3
4ABS_OVER_CURRENT18UNBALANCED_CURRENTS
5OVER_TEMP_FET19BRK
6OVER_TEMP_MOTOR20RESOLVER_LOT
7GATE_DRIVER_OVER_VOLTAGE21RESOLVER_DOS
8GATE_DRIVER_UNDER_VOLTAGE22RESOLVER_LOS
9MCU_UNDER_VOLTAGE23FLASH_CORRUPTION_APP_CFG
10BOOTING_FROM_WATCHDOG_RESET24FLASH_CORRUPTION_MC_CFG
11ENCODER_SPI25ENCODER_NO_MAGNET
12ENCODER_SINCOS_BELOW_MIN_AMPLITUDE26ENCODER_MAGNET_TOO_STRONG
13ENCODER_SINCOS_ABOVE_MAX_AMPLITUDE

0xB1 Read Max Current

TX: [0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeNote
DATA[0]0xB1uint8
DATA[1]OC_Modeuint80=LIMIT, 1=LATCH, 2=REPORT, 3=DISABLED
DATA[2-3]Motor Current Maxint160.01 A / LSB
DATA[4-5]Motor Current Abs Maxint160.01 A / LSB
DATA[6-7]Battery Current Maxint160.01 A / LSB
부연설명
1. OC_Mode: DRV8301칩에서 자체적으로 제공하는 과전류(Over Current) 대처 모드 설정. 기본적으로 이 기능은 전류측정에 부정확하기 때문에 DISABLE(=3)으로 해놓는 것이 좋다.
DRV8301_OC_LIMIT = 0, DRV8301_OC_LATCH_SHUTDOWN = 1, DRV8301_OC_REPORT_ONLY = 2, DRV8301_OC_DISABLED = 3

2. Motor Curr. Max: 모터 전류제어시 제한되는 전류 최대값 (양수로 설정하며 이값의 음수값이 자동으로 Motor Curr. Max Brake 값이 됨), Limit 역할을 하며 Fault Code가 발생하지는 않음

3. Motor Curr. Abs Max: 모터 전류제어시 절대값으로의 최대값으로 이 값이 넘으면 Fault Code 발생

4. Bat Curr. Max: 배터리에서 방전되는 전류의 최대값. PWM Duty가 100%일 때 Batt Curr. = Motor Curr. 인 상황이 되고, 일반적으로 PWM Duty가 낮으면 실제값은 Batt Curr. < Motor Curr. 가 된다.

0xB2 Write Max Current to ROM

Same format as 0xB1 RX (with 0xB2 as DATA[0]).

TX:

ByteFieldTypeNote
DATA[0]0xB2uint8
DATA[1]OC_Modeuint8기본값 3 (DISABLED) 권장
DATA[2-3]Motor Current Maxint160.01 A/LSB (예: 2000 = 20A)
DATA[4-5]Motor Current Abs Maxint160.01 A/LSB (예: 15000 = 150A)
DATA[6-7]Battery Current Maxint160.01 A/LSB (예: 9900 = 99A)

RX: Echo of TX

Do NOT send faster than 100Hz.
부연설명
1. OC_Mode: 기본값으로 이 값을 3으로 해놓는 것이 좋다.
DRV8301_OC_LIMIT = 0, DRV8301_OC_LATCH_SHUTDOWN = 1, DRV8301_OC_REPORT_ONLY = 2, DRV8301_OC_DISABLED = 3

2. Motor Curr. Max: 모터 전류제어시 제한되는 전류 최대값 (양수로 설정하며 이값의 음수값이 자동으로 Motor Curr. Max Brake 값이 됨)

3. Motor Curr. Abs Max: 모터 전류제어시 절대값으로의 최대값으로 이 값이 넘으면 Fault Code 발생

4. Bat Curr. Max: 배터리에서 방전되는 전류의 최대값. PWM Duty가 100%일 때 Batt Curr. = Motor Curr. 인 상황이 되고, 일반적으로 PWM Duty가 낮으면 실제값은 Batt Curr. < Motor Curr. 가 된다.

0xA5 Duty Closed-Loop

PWM Duty를 직접 설정. −1.0 ~ 1.0 범위의 Duty를 int16 (scale ×10000)으로 전송.

TX: [0xA5, 0x00, 0x00, 0x00, Duty_Lo, Duty_Hi, 0x00, 0x00]
ByteFieldTypeNote
DATA[0]0xA5uint8Command
DATA[1-3]Reserved-0x00
DATA[4-5]Dutyint16 LE−10000 ~ 10000 (= −1.0 ~ 1.0)
DATA[6-7]Reserved-0x00

RX: Motor Status Response (공통 포맷 — temp, torque current, speed, encoder pos)

부연설명
Duty 0.1 = 10% PWM. 양수는 정방향, 음수는 역방향. 속도/위치 피드백 없이 직접 PWM을 제어하므로 무부하 시 속도가 공급전압에 비례한다.

Terminal Commands

or_limit — Position Command Safety Limiter

Firmware-level protection against dangerous large position jumps via 0xA3. Without protection, a large position step causes the PID to output maximum current instantaneously, which can trigger DRV/FET overcurrent faults.

$ or_limit                 # Show current settings and hit log
$ or_limit 0               # OFF (no limiting)
$ or_limit 1 [deg] [dps]   # REDIRECT mode (default: 60 deg, 10000 dps)
$ or_limit 2 [ramp_ms]     # RAMP mode (default: 5 ms)

Background: Two Position Control Paths

0xA3 — Direct PID0xA4 — Servo Controller
Control Loop run_pid_control_pos_accum() @10kHz
output = Kp·e + Ki·∫e + Kd·de/dtiq = output × I_max
Trapezoidal velocity profile generator
Speed capped at Vel_maximum (DPS)
Velocity Limit None — full current immediately Yes — maxSpeed parameter
Characteristics Fast response, best for small steps & tracking Smooth accel/decel, safe for large moves

Mode 1: REDIRECT — Control Path Switching

Intercept point: app_openrobot_set_position() (command reception) + control loop (auto-return)

When |target − current_pos| > max_step:

This means both single-shot and repeated 0xA3 commands always end up in Direct PID at steady state:

0xA3 command received (target=360°, current=0°)
    ↓
|360 − 0| = 360° > max_step (60°) ?
  YES → Servo controller (DPS-limited, trapezoidal profile)
        ↓  motor moving toward target...
      |360 − 305| = 55° ≤ max_step ?
        YES → Auto-return to Direct PID
              ↓
              Steady state: Direct PID holding at 360°
ParameterDescriptionDefault
degStep threshold — redirect if |delta| exceeds this. Also used as auto-return threshold.60°
dpsMax speed for servo controller redirect path10000 dps

Mode 2: RAMP — PID Output Slew Rate Limiting

Intercept point: run_pid_control_pos_accum() (inside Direct PID loop @10kHz)

The position controller remains 0xA3 Direct PID, but the PID output increase rate is clamped:

PID computes output (e.g., 0.85)
    ↓
|output| > |prev_output| ?  (magnitude increasing?)
  YES → clamp delta to ±ramp_rate per cycle
  NO  → pass through (free braking)
    ↓
iq = output × motor_current_max
ParameterDescriptionDefault
ramp_msTime for PID output to ramp from 0 to 100%5 ms

Comparison

Mode 1 (REDIRECT)Mode 2 (RAMP)
Intercept pointCommand reception + control loopDirect PID loop (10kHz)
MethodSwitches to servo controllerLimits PID output slew rate
Position controllerServo → auto-return to Direct PIDAlways Direct PID
Steady stateDirect PID (auto-return)Direct PID
Velocity profileTrapezoidal (accel→cruise→decel)None (PID response with ramp)
Current limitingIndirect (via velocity limit)Direct (output rate limit)
Default params60° threshold, 10000 dps5 ms (0→full)
AdvantageSmooth profile, intuitiveSimple, preserves PID characteristics
Settings are auto-saved to EEPROM on mode change. Hit counter and last 10 events are logged (viewable via or_limit).

MIT Control Protocol

CubeMars AK 시리즈 호환 임피던스 제어 프로토콜. 로봇 관절의 컴플라이언트 제어에 사용되며, 매 제어 사이클마다 위치/속도 목표값과 강성/감쇠 게인 및 피드포워드 토크를 전송한다. 모든 파라미터는 출력단(output-side) Nm 기준으로 동작하며, 기어비(GR)와 토크 상수(Kt_out)를 통해 모터단 전류(Iq)로 자동 변환된다.

Control Loop Architecture

MIT 임피던스 제어는 FOC ISR 내부에서 ~10kHz 주기로 실행된다. 출력단 토크(τ_out, Nm)를 계산한 후 Kt_out으로 나누어 전류(Iq) 지령으로 변환한다. FOC 전류 루프의 Iq 기준값으로 작용하므로, 외부 PID를 거치지 않고 최소 지연으로 토크를 생성한다.

τout = Kp × (p_des − p_act/GR) + Kd × (v_des − v_act/GR) + τ_ff   →   iq = τout / Ktout
CAN 0xC0  —  Host (Motor Tool / 상위 제어기)
p_des v_des Kp Kd τ_ff
MIT Impedance Controller
Position (스프링)
Kp × (p_des − p_act/GR)
Velocity (댐퍼)
Kd × (v_des − v_act/GR)
Feedforward
+ τ_ff
τout = Kp·ep + Kd·ev + τ_ff  →  iq = τout / Ktout     Clamp: imin ≤ iq ≤ imax
▼ iq = τout / Ktout
FOC Current Loop
~10kHz ISR — Iq 기준값 직접 입력
Motor
Encoder (multiturn → rad)
p_act / GR
↑ output-side position
FOC Speed (rad/s)
v_act / GR
↑ output-side velocity
CAN Response (0xC0 RX)
temp / iq / speed / pos
↑ to Host
출력단 변환 파라미터 (GR, Kt):
GR (Gear Ratio): 감속비. 모터단 피드백(p_act, v_act)을 GR로 나누어 출력단 좌표로 변환.
Kt_out = Kt_input × GR: 출력단 토크 상수 (Nm/A). τ_out을 Kt_out으로 나누어 iq 전류를 계산.
Kt_input: 모터단 토크 상수 (Nm/A). 0이면 MCCONF의 flux_linkagepole_pairs에서 자동 계산 (Kt = 1.5 × (p/2) × flux).
• GR=1 (직결)이면 모터단 = 출력단. 감속기 부착 시 GR을 설정하면 모든 파라미터가 출력단 기준으로 동작.
0xC4 Read / 0xC5 Write to ROM으로 설정 변경. 부팅 시 EEPROM에서 자동 로드.

Command Variables & Gain Descriptions

변수단위범위역할
p_desrad±12.5 목표 위치 (출력단). 엔코더 multiturn 누적 각도를 GR로 나눈 출력단 좌표계 기준. 0xC3 Set Zero 후 0.0이 현재 위치가 된다. m_invert_direction 설정 시 CAN 경계에서 부호 반전.
v_desrad/s±V_MAX 목표 속도 (출력단). 정지 유지 시 0, 궤적 추종 시 원하는 속도 프로파일 값. Kd와 함께 댐핑 제어에 사용. V_MAX는 EEPROM 설정값 (기본 45 rad/s, 0xC4/0xC5로 변경 가능).
KpNm/rad0–500 위치 강성 (스프링 상수). 출력단 위치 오차 1 rad당 발생시킬 토크(Nm). 값이 클수록 단단하게 위치를 유지하고, 0이면 위치 피드백 없음. 로봇 관절의 가상 스프링 역할.
예: Kp=10이면 1 rad 오차 시 10 Nm의 복원 토크 발생.
KdNm·s/rad0–5 속도 감쇠 (댐퍼 상수). 출력단 속도 오차 1 rad/s당 발생시킬 토크(Nm). Kp와 함께 사용하면 진동을 억제하고, 단독(Kp=0)으로 사용하면 점성 마찰처럼 동작.
예: Kd=0.5이면 1 rad/s 속도 오차 시 0.5 Nm의 감쇠 토크 발생.
τ_ffNm±T_MAX 피드포워드 토크. 임피던스 제어와 무관하게 직접 더해지는 출력단 토크. 중력 보상, 마찰 보상, 또는 역동역학 계산 결과를 주입할 때 사용. Kp=Kd=0이면 순수 토크 제어. T_MAX는 EEPROM 설정값 (기본 33 Nm, 0xC4/0xC5로 변경 가능). m_invert_direction 설정 시 CAN 경계에서 부호 반전.

v_des 동작 원리 — 댐퍼의 기준 속도

댐퍼 항 Kd × (v_des − v_act/GR)에서 v_des는 댐퍼가 허용하는 출력단 기준 속도를 설정한다. 댐퍼는 항상 v_act/GR을 v_des 쪽으로 끌어당긴다.

v_des = +5 rad/s  (정방향으로 이동하려는 궤적)

v_act/GRv_des − v_act/GRKd 항효과
0 (정지)+5+5Kd정방향으로 밀어줌 (가속)
+3 (느림)+2+2Kd더 빠르게 가라고 보조
+5 (정확)00완벽 → 간섭 없음
+8 (빠름)−3−3Kd너무 빠르므로 브레이크

v_des = −5 rad/s  (역방향으로 이동하려는 궤적)

v_act/GRv_des − v_act/GRKd 항효과
0 (정지)−5−5Kd역방향으로 밀어줌 (가속)
−3 (느림)−2−2Kd더 빠르게 역방향 보조
−5 (정확)00완벽 → 간섭 없음
−8 (빠름)+3+3Kd너무 빠르므로 브레이크

v_des = 0  (가장 흔한 사용 — 정지 유지 / 위치 유지)

v_act/GRv_des − v_act/GRKd 항효과
+5 (정방향)−5−5Kd멈춰! (역방향 전류)
−5 (역방향)+5+5Kd멈춰! (정방향 전류)
0 (정지)00정지 유지 → 간섭 없음
요약: v_des의 부호는 댐퍼가 허용하는 운동 방향을 결정한다.
양수 → 정방향 운동을 허용, 편차만 보정
음수 → 역방향 운동을 허용, 편차만 보정
0 → 모든 운동에 저항 (순수 점성 감쇠, 위치 유지 시 Kp와 함께 사용)

궤적 추종 시 매 사이클 p_des(t)와 함께 v_des(t)를 업데이트하면, 댐퍼가 계획된 운동을 방해하지 않고 외란만 제거하므로 추종 정밀도가 크게 향상된다.

Usage Patterns

사용 패턴p_desv_desKpKdτ_ff동작
순수 토크 제어--00원하는 토크 Kp=0, Kd=0이면 τ_ff만 적용. 출력단 Nm 단위의 직접 토크 제어.
위치 유지 (스프링-댐퍼)목표 위치0>0>00 외력에 대해 스프링처럼 복원. Kp↑ = 더 단단, Kd↑ = 진동 감소.
가변 임피던스목표 위치0가변가변0 매 사이클 Kp/Kd를 변경하여 충격 시 유연, 정밀 작업 시 강건 전환.
궤적 추종궤적 p(t)궤적 v(t)>0>0τ(t) 매 사이클 (p, v, τ)를 업데이트. 로봇 동역학 계산 기반 제어.
중력 보상현재 위치000중력 토크 관절의 무게를 상쇄하는 출력단 토크(Nm). 사람이 손으로 자유롭게 움직일 수 있음 (제로-G).
점성 감쇠 (백드라이브)-00>00 Kp=0이면 위치 구속 없이 속도에 비례하는 저항만 발생. 안전한 물리적 상호작용.

Typical Control Sequence

MIT 제어 사용 순서
  1. 0xC3 Set Zero Position — 현재 위치를 MIT 영점으로 설정 (런타임 오프셋, EEPROM 비저장). MIT 제어 중에도 전송 가능 — 20ms hold counter가 잔류 CAN 명령을 무시하여 토크 스파이크를 방지한다.
  2. 0xC1 Enter Motor Mode — 모터 Enable (전류 제어 활성화)
  3. 0xC0 MIT Control — 주기적 전송 (50~500Hz 권장). 매 프레임마다 5개 파라미터 업데이트.
  4. 0xC2 Exit Motor Mode — 제어 종료, 모터 Release (전류 0)
참고: Set Zero (0xC3)는 런타임 오프셋만 설정하며 EEPROM에 저장하지 않는다. 전원 OFF 시 초기화됨. 엔코더 물리적 영점은 0x19 (Write Current Pos as Zero)를 사용할 것.
RMD 제어 모드에서 MIT 모드로 최초 진입 시 현재 위치를 자동 오프셋으로 캡처하므로 p_act=0에서 부드럽게 시작한다.

Feedback Variables (p_act, v_act)

변수소스설명
p_act (mcpwm_foc_get_pos_accum() − offset) × π/180 엔코더 multiturn 누적 각도(deg)를 rad으로 변환. MIT Set Zero (0xC3) 오프셋 적용됨. 제어 법칙에서 p_act/GR로 나누어 출력단 좌표로 변환 후 비교.
v_act mcpwm_foc_get_rps() FOC에서 계산한 모터단 회전 속도 (rad/s). 제어 법칙에서 v_act/GR로 나누어 출력단 속도로 변환 후 비교.
좌표계: p_act는 0xC3 Set Zero 이후 또는 MIT 모드 최초 진입 시 자동 캡처된 오프셋에서 0으로 시작한다. GR=1 (직결)이면 p_act/GR = p_act이므로 모터단과 출력단이 동일하다. GR>1이면 모터 여러 바퀴 회전이 출력단 1바퀴에 해당.
방향 반전: m_invert_direction 설정 시 p_des, v_des, τ_ff는 CAN 수신 시점에 부호가 반전되고, CAN 응답의 vel_dps도 반전된다.

MIT Parameter Encoding (7 bytes)

data8[1]~data8[7]에 56-bit 비트 패킹. CubeMars 표준 인코딩 방식. V_MAX, T_MAX는 0xC4/0xC5로 변경 가능.

FieldBitsRangeResolutionByte Position
p_des (position)16±12.5 rad0.0004 rad (0.02°)DATA[1-2]
v_des (velocity)12±V_MAX rad/s (default 45)V_MAX/2048DATA[3] + DATA[4] hi-nibble
Kp (stiffness)120–500 Nm/rad0.122DATA[4] lo-nibble + DATA[5]
Kd (damping)80–5 Nm·s/rad0.020DATA[6]
τ_ff (feedforward)8±T_MAX Nm (default 33)T_MAX/128DATA[7]
Bit layout: [p_hi(8)] [p_lo(8)] [v_hi(8)] [v_lo(4)|kp_hi(4)] [kp_lo(8)] [kd(8)] [tff(8)]

0xC0 MIT Control

MIT 임피던스 제어. 위치/속도/강성/감쇠/피드포워드 토크 5개 파라미터를 7-byte 패킹으로 전송.

TX: [0xC0, p_hi, p_lo, v_hi, v_lo4|kp_hi4, kp_lo, kd, tff]

RX: Motor Status Response (공통 포맷)

ByteFieldTypeNote
DATA[0]0xC0uint8Echo
DATA[1]Motor Temperatureint81 °C / LSB
DATA[2-3]Torque Current (Iq)int16−2048~2048 = −33A~33A
DATA[4-5]Motor Speedint161 dps / LSB (출력단: ÷GR 적용, m_invert_direction 반영)
DATA[6-7]Encoder Positionuint1614-bit, offset applied
부연설명 — MIT Control 사용법
순수 토크 제어: Kp=0, Kd=0 으로 설정하면 τ_ff만 적용 — 출력단 Nm 단위의 직접 토크 제어.
위치 유지 (스프링-댐퍼): p_des=현재위치, v_des=0, Kp>0, Kd>0, τ_ff=0 — 관절이 외력에 대해 스프링처럼 복원.
궤적 추종: 매 사이클마다 p_des, v_des를 업데이트하면서 Kp, Kd로 임피던스 제어.
GR 적용: p_act, v_act는 모터단 값이며 제어 법칙 내에서 GR로 나누어 출력단 좌표로 변환된다. GR=1이면 모터단과 출력단이 동일하므로 직결 모터에서도 그대로 사용 가능.
자동 오프셋: RMD 제어 모드에서 MIT 모드로 최초 진입 시 현재 위치를 자동 오프셋으로 캡처하므로, 0xC3 없이도 p_act=0에서 부드럽게 시작한다.

0xC1 MIT Enter Motor Mode

모터 Enable. CubeMars 프로토콜의 Enter Motor Mode (0xFC)에 해당.

TX: [0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
RX: [0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

0xC2 MIT Exit Motor Mode

모터 Release. CubeMars 프로토콜의 Exit Motor Mode (0xFD)에 해당. 전류를 0으로 만들고 모터를 해제한다.

TX: [0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
RX: [0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

0x9B Clear Error Flag

현재 fault 상태 및 fault 이력(최근 7개)을 모두 클리어한다. Fault Latch 해제 후 모터는 OFF 상태로 복귀.

TX: [0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
RX: [0x9B, fault_code, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
ByteFieldNote
RX DATA[1]fault_code클리어 후 남은 fault code. 0이면 성공, 0이 아니면 HW fault(DRV) 잔존
Fault Latch: v14부터 fault 발생 시 자동 복귀가 제거됨. 명시적으로 0x9B를 전송해야 fault가 해제되며, 해제 후 모터는 OFF 상태 (제어 명령을 다시 보내야 동작).
Boot Grace Period: 부팅 후 1.5초 동안은 과도 상태 fault (전류 센서 오프셋 등)가 자동 클리어됨.
Watchdog Reset: FAULT_CODE_BOOTING_FROM_WATCHDOG_RESET (10)은 latch 대상 제외 (항상 자동 클리어).
EtherCAT 경로: SDO 0x2030:1에 0을 쓰면 동일하게 fault clear 동작.
VESC EID 경로: CAN_PACKET_FAULT_CLEAR = 100.

0xC3 MIT Set Zero Position

MIT 제어의 현재 위치를 영점(또는 지정 오프셋)으로 설정. CubeMars 프로토콜의 Set Zero Position (0xFE)에 해당.

TX: [0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, offset_lo, offset_hi]
RX: [0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, offset_lo, offset_hi]
ByteFieldTypeNote
DATA[6:7]Offsetint16 LE출력단 기준, 0.01 deg/LSB. 0=현재위치가 0도, 3000=현재위치가 30.00도, −4500=현재위치가 −45.00도. 범위: ±327.67°
런타임 오프셋 방식: m_mit_pos_offset_deg = pos_accum − offset_deg × GR 로 설정. EEPROM에 저장하지 않으므로 전원 OFF 시 초기화된다. 20ms hold counter가 Set Zero 직후 잔류 CAN 명령을 무시하여 토크 스파이크를 방지한다. MIT 제어 중에도 안전하게 전송 가능.

Offset 보존: 0xC3으로 설정한 오프셋은 0xC1 Enter Motor Mode 시 리셋되지 않는다 (m_mit_user_zero_set 플래그). 오프셋을 초기화하려면 offset=0으로 0xC3을 다시 전송.

엔코더 물리적 영점은 별도 0x19 (Write Current Pos as Zero) 명령을 사용할 것.

0xC4 Read MIT Params / 0xC5 Write MIT Params to ROM

MIT 제어 파라미터 (V_MAX, T_MAX, Kt, Gear Ratio) 읽기/쓰기. EEPROM에 영구 저장.

TX (Read):

TX: [0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

TX (Write):

ByteFieldTypeNote
DATA[0]0xC5uint8Command
DATA[1]V_MAXuint8Max velocity range (rad/s), default 45
DATA[2]T_MAXuint8Max torque range (A), default 33
DATA[3-4]Kt_inputuint16 LE×0.001 Nm/A (motor-side). 0 = auto from MCCONF
DATA[5-6]Gear Ratiouint16 LE×0.01 (예: 900 = 9.0)
DATA[7]Reserved-0x00

RX (공통 — 0xC4 Read 및 0xC5 Write 모두):

ByteFieldTypeNote
DATA[0]0xC4uint8항상 0xC4 (Read/Write 모두)
DATA[1]V_MAXuint8현재 V_MAX (rad/s)
DATA[2]T_MAXuint8현재 T_MAX (A)
DATA[3-4]Kt_outuint16 LE×0.001 Nm/A (output-side = Kt_input × GR)
DATA[5-6]Gear Ratiouint16 LE×0.01
DATA[7]Reserved-0x00
부연설명 — Kt_input vs Kt_out
Write (0xC5)에서는 모터단 Kt_input을 보내고, Read (0xC4) 응답에서는 출력단 Kt_out = Kt_input × GR을 반환한다. Kt_input=0으로 보내면 MCCONF의 flux_linkagepole_pairs에서 자동 계산된다 (Kt = 1.5 × (p/2) × flux).

MIT 제어 법칙 (출력단 Nm):
τ_out = Kp × (p_des − p_act/GR) + Kd × (v_des − v_act/GR) + τ_ffiq = τ_out / Kt_out
EEPROM 쓰기 포함. 100Hz 이상 반복 전송 금지.

0xD0 Read External Sensor

외부 센서 데이터 읽기. CAN → RS485 → XIAO RA4M1 → I2C → MS5803 경로로 온도/압력/기압을 읽는다. 응답까지 최대 500ms 소요.

TX: [0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

RX:

ByteFieldTypeUnitNote
DATA[0]0xD0uint8Echo
DATA[1]Validuint80/11 = 유효한 데이터
DATA[2-3]Temperatureint16 LE0.01 °C / LSB예: 2350 = 23.50°C
DATA[4-5]Pressureuint16 LE1 mbar / LSB예: 1013 = 1013 mbar
DATA[6-7]Atmosphereuint16 LE0.0001 atm / LSB예: 10000 = 1.0000 atm
부연설명 — 외부 센서 구조
VESC 제어기의 USART3 (RS485, half-duplex)를 통해 외부 XIAO RA4M1 보드에 센서 데이터를 요청한다. XIAO는 I2C로 연결된 MS5803 수압/기압 센서의 온도/압력을 읽어 텍스트 프로토콜 ($SNS,temp,pres,atm\n)로 응답한다.

주의: RS485 half-duplex 통신 특성상 응답까지 최대 500ms가 소요될 수 있으며, XIAO 보드가 연결되지 않은 경우 Valid=0이 반환된다.

CubeMars 프로토콜 매핑

CubeMars 원본OpenRobot RMD기능
0xFC (CAN ID)0xC1 (DATA[0])Enter Motor Mode
0xFD (CAN ID)0xC2 (DATA[0])Exit Motor Mode
0xFE (CAN ID)0xC3 (DATA[0])Set Zero Position
MIT frame (CAN ID)0xC0 (DATA[0])Impedance Control
CubeMars는 CAN ID 자체로 명령을 구분하지만, OpenRobot은 RMD 프로토콜 구조 (SID = 0x140 + motor_id, DATA[0] = command byte)를 사용하므로 명령 바이트가 다름. 비트 패킹 방식은 CubeMars 표준과 동일하나, 게인 단위가 다르다:
CubeMars: Kp (A/rad), Kd (A·s/rad), τ_ff (A) — 모터단 전류 기준
OpenRobot: Kp (Nm/rad), Kd (Nm·s/rad), τ_ff (Nm) — 출력단 토크 기준, GR/Kt_out으로 자동 변환

부록: 기존 제어 모드와의 비교

MIT 임피던스 제어가 기존 위치/속도 제어보다 구조적으로 단순하고 직접적인 이유를 비교한다.

기존 위치 PID (0xA3 / 0xA4) MIT Control (0xC0)
제어 구조 PID (P+I+D) → 정규화 출력 (-1~1) → × lo_current_max PD + FF → τ_out (Nm) → Iq = τ/Kt_out
I-term (적분항) 있음 (windup 위험) 없음 (τ_ff로 대체)
D-term / 감쇠 오차 미분 + LP 필터 실제 속도(rad/s) 직접 사용
출력 단위 정규화 비율 (-1~1) 물리적 토크 (Nm) → 전류 변환
DPS 속도제어 프로파일 생성 → 위치 PID (이중 루프) 단일 루프
게인 조정 FW에 고정 (MCCONF) 매 프레임 전송 (실시간 변경)

1. PID 출력이 정규화된 비율 — 가장 큰 구조적 차이

기존 run_pid_control_pos_accum()의 출력 경로:

output = P + I + D;                     // PID 합산
clamp(output, -1.0, 1.0);             // -1~1 비율로 클램프
motor→m_iq_set = output × lo_current_max; // 비율 × 최대전류

p_pid_kp의 단위가 “각도오차(deg)당 비율”이므로, lo_current_max가 바뀌면 같은 Kp에서 실제 전류가 달라진다. 모터/설정마다 게인 재튜닝이 필요하며, I-term windup 보호도 이 비율 기준이라 미묘한 동적 문제가 발생할 수 있다.

MIT 제어의 출력 경로:

τ_out = Kp × (p_des − p_act/GR) + Kd × (v_des − v_act/GR) + τ_ff; // 출력단 Nm
iq = τ_out / Kt_out; // 전류 변환
clamp(iq, lo_current_min, lo_current_max);                      // 전류 리밋
motor→m_iq_set = iq;                                           // 직접 입력

정규화 없이 출력단 토크(Nm)를 직접 계산하므로, Kp=10이면 1 rad 오차에 10 Nm의 토크가 발생한다는 것이 직관적이다. GR과 Kt_out을 통해 자동으로 전류(Iq)로 변환되므로, 모터나 감속기 구성이 바뀌어도 물리적 의미가 유지된다.

2. I-term (적분항)의 유무

기존 PID에는 I-term이 있다. 정지 시 오차가 남으면 I-term이 서서히 누적되다가 한계를 넘으면 한꺼번에 방출되어 오버슈트와 진동을 유발할 수 있다. Anti-windup 보호가 있지만 튜닝이 까다롭다.

MIT 제어에는 I-term이 없다 (순수 PD + FF). 로봇 임피던스 제어에서는 I-term 없이 τ_ff (피드포워드 토크)로 정상상태 오차를 보상하는 것이 표준적이며, windup이 원천적으로 발생하지 않는다.

3. D-term: 오차 미분 vs 실제 속도 피드백

기존 PID — 오차 미분
d_term = (error − prev_error) / dt
LP_FILTER(d_term, kd_filter)
  • 엔코더 해상도가 낮으면 error == prev_error 구간 발생 → d_term = 0 → 불연속
  • 목표값 변경 시 미분 킥(derivative kick) 발생
  • LP 필터로 완화하지만 위상 지연 추가
MIT — 실제 속도 피드백
Kd × (v_des − v_act/GR)
v_act = mcpwm_foc_get_rps()
  • FOC에서 계산한 실제 속도(rad/s)를 직접 사용
  • 오차 미분 불필요 → 매끄럽고 노이즈에 강건
  • 목표 속도(v_des)를 별도 설정 가능 → 궤적 추종에 유리

4. DPS 속도제어의 이중 루프

RMD 0xA2 (DPS) 명령은 dps_control_thread에서 사다리꼴 속도 프로파일(genProfile)을 생성한 뒤, 그 출력(deg_ref)을 다시 위치 PID에 넣는 이중 루프 (프로파일 → 위치 PID → 전류) 구조이다. 두 루프의 게인이 서로 간섭할 수 있으며, 프로파일 생성의 이산화 오차도 누적된다.

MIT는 단일 루프. 임피던스 법칙이 출력단 토크를 계산하고 Kt_out으로 나누어 직접 Iq를 생성하므로 중간 단계가 없다.

결론: 기존 제어가 “문제”라기보다, MIT가 구조적으로 더 단순하고 직접적인 것이 핵심이다.
정규화 없이 출력단 토크(Nm) 직접 계산, Kt_out으로 전류 변환 → 직관적 튜닝
I-term 없음 → windup/오버슈트 원천 방지
실제 속도 피드백 → 오차 미분보다 매끄럽고 강건
단일 루프 → 이중 루프 간섭 없음
매 프레임 게인 전송 → 실시간 임피던스 변경

로봇 관절 제어에서는 I-term 없는 PD + FF가 산업 표준이며, CubeMars/MIT Mini Cheetah 등 대부분의 로봇 액추에이터가 이 구조를 채택하고 있다.

VESC EID Protocol

CAN Extended ID (EID)를 사용하는 VESC 내장 통신 프로토콜. SID 프로토콜과 별도로 동작하며, MCCONF/APPCONF 파라미터 설정, 펌웨어 업로드, 리부트 등에 사용된다.

EID Frame Format

ItemValue
Frame TypeExtended (EID, 29-bit)
EID Format(packet_type << 8) | target_id
Byte OrderBig-Endian
PC Sender ID0xFE (254)
VESC EID는 multi-frame 프로토콜을 사용하여 8바이트 CAN 프레임 제한을 넘는 대용량 데이터를 전송한다. FILL_RX_BUFFERPROCESS_RX_BUFFER 순서로 데이터를 분할/재조립한다.

VESC EID Packet Types

TypeValueDirectionDescription
CAN_PACKET_FILL_RX_BUFFER5TX/RXMulti-frame 데이터 버퍼 채우기
CAN_PACKET_FILL_RX_BUFFER_LONG6TX/RXLong index (16-bit offset) 버퍼 채우기
CAN_PACKET_PROCESS_RX_BUFFER7TX/RX버퍼 처리 명령 (CRC 포함)
CAN_PACKET_PROCESS_SHORT_BUFFER8TX/RX짧은 단일 프레임 명령

주요 VESC Commands (CommPacketId)

IDCommandTypeDescription
0COMM_FW_VERSIONRead펌웨어 버전 조회
14COMM_GET_MCCONFReadMotor Configuration 읽기 (~457 bytes)
13COMM_SET_MCCONFWriteMotor Configuration 쓰기
15COMM_GET_MCCONF_DEFAULTReadMotor Configuration 기본값 읽기
17COMM_GET_APPCONFReadApp Configuration 읽기 (~418 bytes)
16COMM_SET_APPCONFWriteApp Configuration 쓰기
18COMM_GET_APPCONF_DEFAULTReadApp Configuration 기본값 읽기
28COMM_REBOOTControlMCU 리부트 (IWDG watchdog 리셋)
31COMM_ERASE_NEW_APPWriteStaging area 삭제 (펌웨어 업로드 1단계)
32COMM_WRITE_NEW_APP_DATAWriteStaging area에 바이너리 쓰기 (2단계)
36COMM_JUMP_TO_BOOTLOADERControl부트로더로 점프 (3단계)
46COMM_ERASE_BOOTLOADERWrite부트로더 섹터 삭제 (부트로더 업로드 시)

MCCONF PID Offsets

MCCONF 바이너리 페이로드 내 PID 파라미터 오프셋 (MCCONF_SIGNATURE: 0x83C3E1AA). 값은 VESC float32_auto 포맷 (4 bytes Big-Endian).

ParameterSpeed PID OffsetPosition PID Offset
Kp329354
Ki333358
Kd337362
Kd Filter341366
Ramp (eRPM/s)350
부연설명 — MCCONF PID 읽기/쓰기
읽기: COMM_GET_MCCONF (14)를 전송하면 전체 MCCONF 바이너리(~457 bytes)가 반환됨. 위 오프셋에서 PID 값을 추출.
쓰기: 읽은 원본 MCCONF를 복사하고, 수정할 PID 값만 해당 오프셋에 패치한 후 COMM_SET_MCCONF (13)로 전송.
주의: 반드시 원본 MCCONF를 먼저 읽은 후(Read Gains), PID 값만 수정하여 전체를 다시 쓰는 방식을 사용해야 함. 그렇지 않으면 다른 설정값이 손상될 수 있음.

Firmware Upload via CAN EID

부연설명 — CAN 펌웨어/부트로더 업로드
Firmware Upload:
1. COMM_ERASE_NEW_APP(size) — Staging area (Flash sectors 8-10) 삭제
2. COMM_WRITE_NEW_APP_DATA(offset, data) — 바이너리 데이터를 400-byte 청크로 분할 전송
3. COMM_JUMP_TO_BOOTLOADER — 부트로더가 staging → app 영역으로 복사

Bootloader Upload:
1~2 단계 동일
3. COMM_ERASE_BOOTLOADER — 부트로더 섹터 (Flash sector 11, 128KB) 삭제
4. COMM_JUMP_TO_BOOTLOADER — staging의 부트로더가 sector 11에 자기 자신을 복사

주의: 부트로더 업로드 실패 시 복구 불가 (JTAG 필요). 반드시 안정적인 전원과 CAN 연결 상태에서 수행할 것.

Encoder Native Resolution

EncoderResolutionCPRNote
AS504714-bit16,384CAN SID 프레임과 동일 해상도
MT683521-bit2,097,152CAN SID에서는 14-bit로 정규화하여 전송
RLS AksIM-220-bit1,048,576BiSS-C 인터페이스. CAN SID에서는 14-bit로 정규화
Overflow 주의: MT6835 21-bit 값 × 16384 연산 시 uint32_t 오버플로 발생 (45° 이상에서). 반드시 uint64_t 캐스트 사용: (uint64_t)val * ENCODER_CPR_AS5047 / cpr

EEPROM Custom Variable Index

conf_general_store_eeprom_var_custom() / conf_general_read_eeprom_var_custom()로 접근하는 사용자 정의 EEPROM 변수 목록. 범위: index 0~63. 터미널에서 or_sev [index]로 개별 값 확인 가능.

EEPROM 값은 전원 OFF 후에도 유지됩니다. 단, VESC-Tool을 통한 펌웨어 업데이트 시 초기화됩니다 (ST-Link/JTAG 업데이트 시에는 유지).
IndexNameDefaultDescription
0EEP_APP_SELECT0Application mode (0=VESCular, 1=VESCAT)
1EEP_CAN_TERMINAL_RESISTOR_MODE0CAN terminal resistor (0=OFF, 1=ON)
2EEP_VMAXDPS_VMAX_DEFAULTDPS control max velocity (dps)
3EEP_AMAXDPS_AMAX_DEFAULTDPS control max acceleration (dps/s)
4EEP_ENC_ZERO_POS0Encoder zero position offset (deg)
5EEP_POS_LIMIT_MODE0Position limit mode (0=OFF, 1=REDIRECT, 2=RAMP)
6EEP_POS_LIMIT_STEPPosition limit max step (deg)
7EEP_POS_LIMIT_RAMPPosition limit ramp rate (/cycle)
8EEP_POS_LIMIT_DPSPosition limit redirect DPS
9EEP_DEMO_MODE0Demo mode (0=duty, 1=erpm, 2=dps)
10EEP_DEMO_VALUEDemo control value
11EEP_DEMO_RAMP_TIMEDemo ramp time (s)
12EEP_DEMO_HOLD_TIMEDemo hold time (s)
13EEP_DEMO_STOP_TIMEDemo stop time (s)
14EEP_MIT_V_MAX45.0MIT max velocity range (rad/s)
15EEP_MIT_T_MAX33.0MIT max torque range (Nm)
16EEP_MIT_KT0 (auto)MIT motor-side Kt (Nm/A), 0=auto from flux
17EEP_MIT_GR9.0MIT gear ratio
18EEP_PDO_TIMEOUT1000EtherCAT PDO timeout (ms). v13
19EEP_BIG_ERROR_THRESHOLD180.0Position big error threshold (output-side deg). v13
터미널 명령
or_sev [index] — 해당 인덱스의 EEPROM 값 읽기 (u32/i32/float 형태로 출력)
or_big — Big Error threshold 현재 값 및 fault 상태 확인
or_big [deg] — Big Error threshold 변경 및 EEPROM 저장

Revision History

VersionDateChanges
v7 2024-11-18 Encoder offset, damping torque, fault code, current limit R/W.
v8 2025-05-15 0xA3 changed to multi-turn direct PID. 0xB0/0xB1/0xB2 added. All control commands changed to single-shot (1회 전달 후 유지).
v9 2026-02-09 0x9C (Read Motor Status 2) added. 0x9D (Read Motor Status 3: control mode + phase currents) added. or_limit safety limiter added. Encoder 14-bit normalization for MT6835. 0xA2 speed_mode (DPS/eRPM) added.
v10 2026-02-11 VESC EID Protocol section added. Encoder native resolution (AS5047 14-bit / MT6835 21-bit) with uint64_t overflow fix. COMM_REBOOT HardFault bug fixed. CAN firmware/bootloader upload. Position/Speed PID via MCCONF EID.
v11 2026-02-23 MIT Control Protocol added (0xC0~0xC3). CubeMars AK compatible impedance control: position/velocity/Kp/Kd/torque_ff packed in 7 bytes. Enter/Exit Motor Mode and Set Zero Position commands. Control loop architecture, parameter descriptions, usage patterns documented. Duty Closed-Loop (0xA5) added.
v12 2026-03-05 MIT Parameter R/W (0xC4/0xC5) added: V_MAX, T_MAX, Kt, GR EEPROM read/write. External Sensor (0xD0) added: MS5803 temperature/pressure via RS485. m_invert_direction support at CAN boundary (all control inputs + vel_dps responses). MIT Set Zero (0xC3) changed to runtime-only offset (no EEPROM, 20ms hold counter). RMD→MIT transition auto-capture offset. RLS AksIM-2 20-bit encoder support added.
v13 2026-03-18 EtherCAT Protocol documentation added (PDO/SDO/DC SYNC0/TwinCAT guide). SDO deferred EEPROM store for motor safety. 0x2020 Motor Parameters changed to RW. ESI XML DC-Synchron support. F405 foc_test_capture removed (RAM overflow fix). TwinCAT 3 verified with DC SYNC0.

EtherCAT Slave Protocol

OpenRobot MC EtherCAT Slave — SOES 3.1.0 + LAN9252 on STM32F405

Hardware: LAN9252 (SPI PDI) + STM32F405  |  Stack: SOES 3.1.0  |  Vendor ID: 0x00524F42 ("ROB")

Overview

ItemValue
ESC ChipLAN9252 (Microchip), SPI PDI (0x80)
MCUSTM32F405RGT6 (168 MHz, Cortex-M4)
EtherCAT StackSOES 3.1.0 (Simple Open EtherCAT Slave)
Mailbox ProtocolCoE (CANopen over EtherCAT)
RxPDO Size17 bytes (Master → Slave)
TxPDO Size20 bytes (Slave → Master)
DC SYNC0Supported (AssignActivate = 0x0300)
Supported MastersTwinCAT 3, pysoem (Python)

RxPDO — Motor Control (Master → Slave)

PDO Index: 0x1600, Object Index: 0x7000, SM2, 17 bytes total

ByteFieldTypeScaleRange (raw)Range (real)Description
0control_modeuint80x80–0xC0Command code (see Control Mode table)
1–4target_positionint32×10000±2,147,483,647±214,748 deg / ±214,748 radPosition target. 0xA3/0xA4: deg, 0xC0(MIT): rad
5–8target_velocityint32×10000±2,147,483,6470xA2: unlimited dps / 0xA4: 0~25,000 dps / 0xC0: rad/s (±V_MAX)Velocity target or speed limit
9–12target_torqueint32×10000±2,147,483,6470xA1: ±200 A (clamp) / 0xA5: ±1.0 duty (clamp) / 0xC0: ±T_MAX NmCurrent, duty, or torque depending on mode
13–14kpuint16×1000–655350xA1: 0~100 (damping) / 0xC0: 0~500 Nm/rad (MIT Kp)Stiffness or damping coefficient
15–16kduint16×10000–655350xC0: 0~5 Nm·s/rad (MIT Kd)Damping — MIT mode only
값 범위 상세 (모드별)
0xA1 (Torque): target_torque는 FW에서 ±200A로 클램핑되지만, 실제 모터 출력은 l_current_max (기본 60A, HW 상한 ±64A)에서 먼저 제한됨.
0xA2 (Speed): target_velocity에 FW 클램핑 없음. DPS 컨트롤러가 내부적으로 Vmax/Amax로 제한.
0xA3 (Position): target_position에 FW 클램핑 없음. Big Error threshold (기본 180°, 출력단) 초과 시 fault.
0xA4 (Multiturn): target_velocity는 0~25,000 dps 범위만 허용 (FW에서 체크).
0xA5 (Duty): target_torque는 FW에서 ±1.0으로 클램핑.
0xC0 (MIT): 각 파라미터는 EEPROM 설정값 (V_MAX, T_MAX, Kp 0~500, Kd 0~5) 범위로 정규화됨. 위치/속도는 rad 단위.
Rate-of-Change Limiting: target_torque는 1 PDO 주기당 최대 ±5.0A, target_velocity는 ±10.0 dps 변화로 제한됩니다 (SPI 데이터 오류 방어). 급격한 값 변화 시 여러 PDO 주기에 걸쳐 램프됩니다.

TxPDO — Motor Status (Slave → Master)

PDO Index: 0x1A00, Object Index: 0x6000, SM3, 20 bytes total

ByteFieldTypeScaleRange (real)Description
0control_modeuint80x80–0xC0Active control mode echo (same codes as RxPDO)
1fault_codeuint80–26mc_fault_code: 0=OK, 1=OV, 2=UV, 3=DRV, 4=OC, 5=FET_OT, 6=MOT_OT, 11=ENC_SPI, 25=NO_MAG, 26=BIG_ERR
2–5actual_positionint32×10000multi-turn deg (MIT: output-side deg ÷GR)Accumulated position. MIT 모드에서는 (pos − enc_offset − mit_offset) / GR
6–9actual_velocityint32×10000dps (degrees per second)Angular velocity from FOC observer
10–13actual_torqueint32×10000A (filtered Iq current)Directional torque current, filtered
14–15bus_voltageuint16×1000~70.0 V (HW dependent)DC bus input voltage
16temp_motorint8−128~127 °CMotor temperature (NTC sensor)
17temp_mosfetint8−128~127 °CMOSFET temperature (DRV8301 internal)
18–19encoder_posuint160–16383 (14-bit)Raw encoder count. 21-bit 엔코더는 >>7 정규화

Control Modes (control_mode field)

Same command codes as CAN RMD protocol. Set via RxPDO control_mode byte.

CodeNameUsed RxPDO FieldsDescription
0x80MOTOR_OFFRelease motor, clear faults. Always start with this.
0x81MOTOR_STOPActive stop (DPS = 0, holds position)
0x88MOTOR_STARTStandby (duty = 0)
0xA1TORQUE_CLOSED_LOOPtarget_torque (A), kp (damping)Current/torque control. kp>0 enables damping.
0xA2SPEED_CLOSED_LOOPtarget_velocity (dps)Speed control via DPS controller
0xA3POSITION_CLOSED_LOOP_1target_position (deg)Direct PID position control (multi-turn, no speed limit). Big Error protection enabled.
0xA4SET_MULTITURN_POSITIONtarget_position (deg), target_velocity (dps)Position + speed limit servo control
0xA5DUTY_CLOSED_LOOPtarget_torque (duty, -1~+1)Direct PWM duty control
0xC0MIT_CONTROLAll 5 fields5-param impedance control (rad units). τ = Kp×(p_des−p_act) + Kd×(v_des−v_act) + τ_ff
Big Error Protection: Modes 0xA3 and 0xC0 have position error threshold check. If |command − actual| exceeds threshold on output-side, motor faults (FAULT_CODE_POSITION_BIG_ERROR). Latched fault — send 0x80 (MOTOR_OFF) to clear. 0xA4는 speed limit이 안전장치 역할을 하므로 Big Error 미적용.

Big Error Threshold 상세

ItemValue
Default180° (출력단 기준)
SDO0x2030:8 (RW, EEPROM-backed)
Terminalor_big (읽기) / or_big [deg] (쓰기+EEPROM 저장)
EEPROM Index19 (EEP_BIG_ERROR_THRESHOLD)
기준출력단 deg — 0xA3, 0xC0 모두 동일 기준
Fault ClearPDO 0x80 (MOTOR_OFF) 전송 시에만 클리어 (latched)

모드별 발동 조건 (예: threshold=180°, GR=9)

Mode입력 단위FW 내부 변환발동 조건
0xA3 Position모터단 degpos_err ÷ GR모터단 |cmd−actual| > 1620° (= 180° × 9, 모터 4.5회전)
0xC0 MIT출력단 rad이미 출력단출력단 |cmd−actual| > 3.14 rad (= π, 출력 반회전)
0xA4 Multiturn모터단 degBig Error 미적용 (speed limit으로 보호)
Big Error 기준 통일 (v13)
0xA3과 0xC0 모두 출력단 기준으로 통일되었습니다.
0xA3: 모터단 에러를 GR로 나눈 값으로 비교 (pos_err / GR > threshold)
0xC0: MIT는 원래부터 출력단 기준 (pos_err_output_deg > threshold)
GR=1 (감속기 없음)이면 두 모드 모두 동일한 threshold가 적용됩니다.
PDO Timeout: If no PDO is received for the configured timeout period (default 1000 ms, writable via SDO 0x2030:7), the motor automatically enters FAULT_STOP. PDO timeout only triggers when control source is EtherCAT.

SDO Object Dictionary (CoE)

49 objects in 12 groups (0x2000–0x2090). Accessible via CoE SDO protocol (TwinCAT CoE-Online, pysoem sdo_read/sdo_write).

Deferred Store: SDO write immediately updates RAM values for real-time effect. Flash/EEPROM storage is deferred until the motor is idle (NONE_CONTROL or MOTOR_RELEASE) to prevent FOC control disruption during flash write operations.

0x2000 — Current Control (RW)

SubNameTypeAccessDescription
1Current_KpREAL32RWFOC current loop proportional gain
2Current_KiREAL32RWFOC current loop integral gain

0x2001 — Speed PID (RW)

SubNameTypeAccessDescription
1Speed_KpREAL32RWSpeed proportional gain
2Speed_KiREAL32RWSpeed integral gain
3Speed_KdREAL32RWSpeed derivative gain
4Speed_Kd_filterREAL32RWSpeed Kd low-pass filter coefficient
5Speed_min_erpmREAL32RWMinimum eRPM for speed control

0x2002 — Position PID (RW)

SubNameTypeAccessDescription
1Pos_KpREAL32RWPosition proportional gain
2Pos_KiREAL32RWPosition integral gain
3Pos_KdREAL32RWPosition derivative gain
4Pos_Kd_filterREAL32RWPosition Kd low-pass filter coefficient

0x2010 — Encoder (Mixed RO/RW)

SubNameTypeAccessDescription
1Enc_offsetREAL32RWEncoder offset (degrees)
2Encoder_CPRUINT32ROCounts per revolution (AS5047: 16384, MT6835: 2097152)

0x2020 — Motor Parameters (RW) v13

SubNameTypeAccessDescription
1Max_currentREAL32RWMotor max current limit (A). Also sets l_current_min = −value. Clamped by HW_LIM_CURRENT (±64A).
2Abs_max_currentREAL32RWAbsolute max current (A). Direction-independent protection limit.
3Torque_constantREAL32RWMotor-side Kt (Nm/A). Write updates MIT Kt parameter. Read returns Kt_out (= Kt × GR).
4Motor_polesUINT8RWNumber of motor pole pairs
5Flux_linkageREAL32RWPM flux linkage (Wb). Used for Kt auto-calculation: Kt = 1.5 × (P/2) × flux
Motor Parameters 변경 시 주의사항
Max_current 변경 시 lo_current_max/min이 자동 재계산됩니다. HW 하드리밋(±64A)을 초과할 수 없습니다. Torque_constant를 write하면 MIT 제어의 Kt (motor-side)가 변경되고, mit_recompute_kt_out()이 호출됩니다. 모든 변경은 deferred store로 모터 idle 시 flash에 저장됩니다.

0x2030 — Fault / Protection (Mixed RO/RW)

SubNameTypeAccessDescription
1Fault_codeUINT8RO0=OK, 1=OV, 2=UV, 3=DRV, 4=OC, 5=FET_OT, 6=MOT_OT, 11=ENC_SPI, 25=NO_MAG, 26=BIG_ERR
2PDO_timeout_flagUINT8RO1 = PDO timeout detected, auto-clears on PDO resume
3VIN_voltageREAL32ROInput voltage (V)
4Temp_MOSFETREAL32ROMOSFET temperature (°C)
5Temp_limit_FETREAL32RWFET over-temperature threshold (°C)
6Temp_limit_motorREAL32RWMotor over-temperature threshold (°C)
7PDO_timeout_msUINT32RWPDO timeout period (ms). Default: 1000. EEPROM-backed.
8Big_error_thresholdREAL32RWPosition big error threshold (output-side deg). Default: 180. EEPROM-backed.

0x2040 — Status (RO)

SubNameTypeAccessDescription
1Position_degREAL32ROMulti-turn accumulated position (degrees)
2Velocity_dpsREAL32ROAngular velocity (degrees per second)
3Torque_currentREAL32ROIq torque current (A)
4Control_modeUINT8ROActive control mode code

0x2050 — MIT Parameters (RW)

SubNameTypeAccessDescription
1MIT_V_maxREAL32RWMax velocity range (rad/s). Default: 45.0. EEPROM-backed.
2MIT_T_maxREAL32RWMax torque range (Nm). Default: 33.0. EEPROM-backed.
3MIT_Kt_motorREAL32RWMotor-side Kt (Nm/A). 0 = auto from flux. EEPROM-backed.
4MIT_Gear_ratioREAL32RWGear ratio. Default: 9.0. EEPROM-backed.
5MIT_Set_zeroUINT8RWWrite 1 to set zero position (runtime offset, auto-clears)

0x2060 — DPS / Servo (RW)

SubNameTypeAccessDescription
1DPS_VmaxREAL32RWMaximum velocity for DPS/servo control (dps). EEPROM-backed.
2DPS_AmaxREAL32RWMaximum acceleration (dps/s). EEPROM-backed.

0x2070 — Version Info (RO)

SubNameTypeAccessDescription
1FW_majorUINT8ROFirmware major version
2FW_minorUINT8ROFirmware minor version
3HW_nameUINT32ROHardware name identifier

0x2080 — External Sensor (RO)

SubNameTypeAccessDescription
1Pressure_mbarREAL32ROMS5803 pressure (mbar). Auto-pushed via CAN from XIAO.
2Temperature_CREAL32ROMS5803 temperature (°C)
3Depth_mREAL32ROCalculated depth (m)

DC Synchronization (Distributed Clocks)

ItemValue
SYNC0 SupportedYes (AssignActivate = 0x0300)
Default Cycle1000 µs (1 kHz, matched to master)
SYNC0 PinLAN9252 → PD2 (EXTI2 ISR)
Free-Run Poll Cycle~700 µs (1428 Hz)
DC SYNC Poll Cycle1000 µs (1000 Hz, synchronized)
DC SYNC0 동작 방식
FREE-RUN 모드에서는 SOES가 ~700µs 주기로 자유 폴링합니다.
DC-Synchron 모드 활성화 시 LAN9252가 SYNC0 펄스를 PD2 핀에 출력하고, EXTI2 ISR에서 세마포어를 통해 SOES 스레드를 깨워 마스터와 정확히 동기화합니다.
or_soes 터미널 명령으로 DC SYNC0 상태 (ACTIVE/OFF, cycle, pulses, mode) 확인 가능합니다.

EtherCAT Master 실시간 성능 비교

pysoem (Motor Tool) vs TwinCAT 3 — 동일 슬레이브(LAN9252 + F405)에서 측정한 실제 성능

항목pysoem (Motor Tool)TwinCAT 3
PDO 주기2 ms (500 Hz)1 ms (1 kHz), 최소 100 µs 가능
FW Poll cycle700 µs (FREE-RUN)1000 µs (DC SYNC 동기)
지터 (Jitter)수백 µs ~ 15 ms (Windows 스레드 스케줄러 의존)< 1 µs (커널 레벨 RT 스케줄러)
DC SYNC0소프트웨어 동기 (불안정)하드웨어 동기 (안정)
동기화 모드FREE-RUNSYNC (DC-Synchron)
실시간성비실시간 (Windows userspace)하드 리얼타임 (RT 커널, CPU 코어 전용)
최악 PDO 지연~20 ms (Windows 스케줄러 최악)< 10 µs
PDO timeout 위험있음 (지터로 인한 누락 가능)거의 없음
권장 용도파라미터 설정, 모니터링, 간단한 테스트정밀 모션 제어, 로봇 운용
실시간 성능 요약
pysoem: 마스터가 time.sleep()으로 주기를 유지하므로 Windows 스레드 스케줄러에 의존합니다. 최악의 경우 PDO 한 주기가 20ms를 넘어 PDO timeout이 발생할 수 있습니다. 파라미터 설정, SDO 접근, 모니터링 등 비실시간 작업에 적합합니다.

TwinCAT: RT 커널이 CPU 코어 하나를 점유하고 하드웨어 타이머 인터럽트로 주기를 보장합니다. 지터가 1µs 미만이므로 MIT 임피던스 제어, 위치 추종 등 정밀 모션 제어에 필수적입니다.

TwinCAT 3 Integration Guide

1. ESI XML Setup

  1. Motor Tool → EtherCAT 탭 → "Gen ESI XML" 버튼 클릭 → XML 파일 저장
  2. 생성된 XML을 C:\TwinCAT\3.1\Config\Io\EtherCAT\ 에 복사
  3. __cache\ 폴더 안의 파일 삭제 (캐시 초기화)
  4. TwinCAT XAE / TcXaeShell 재시작

2. Project Setup

  1. 새 TwinCAT Project 생성
  2. I/O → Devices → Add New Device → EtherCAT Master
  3. 실시간 NIC 선택 (Intel i210/i350 등 TwinCAT RT 호환)
  4. Master 우클릭 → Scan → 슬레이브 자동 감지
  5. 슬레이브 → DC 탭 → "DC-Synchron" 선택 (DC SYNC0 사용 시)

3. PLC Variable Linking

  1. PLC Project 추가 (Standard PLC Project)
  2. MAIN (PRG)에 변수 선언 (AT %Q* for outputs, AT %I* for inputs)
  3. Build Solution (Ctrl+Shift+B)
  4. I/O 트리 → 슬레이브 Outputs/Inputs 에서 각 변수 더블클릭 → Attach Variable → PLC 변수 연결
  5. Activate Configuration → Run Mode → Login (F11) → Start (F5)

4. Example PLC Program (Duty Control)

// VAR declaration
control_mode AT %Q* : BYTE;
target_torque AT %Q* : DINT;
bRun : BOOL;

// Program body
IF bRun THEN
  control_mode := 16#A5;    // DUTY_CLOSED_LOOP
  target_torque := 1000;   // 0.1 duty (x10000)
ELSE
  control_mode := 16#80;    // MOTOR_OFF
  target_torque := 0;
END_IF

5. SDO Access (CoE-Online)

TwinCAT에서 슬레이브 선택 → CoE-Online 탭에서 SDO Object Dictionary가 자동으로 열거됩니다. 각 object를 더블클릭하여 Read/Write 가능합니다.

PLC에서는 FB_EcCoESdoRead / FB_EcCoESdoWrite 펑션블록으로 런타임 SDO 접근이 가능합니다.

Startup 탭에서 SDO write 명령을 등록하면 부팅 시 자동으로 파라미터를 설정할 수 있습니다.

Safety Features

FeatureDescription
PDO TimeoutConfigurable timeout (SDO 0x2030:7, default 1000ms). Motor enters FAULT_STOP if no PDO received. Only active when control source = EtherCAT.
Big Error ProtectionPosition error threshold (SDO 0x2030:8, default 180°, output-side). Applies to 0xA3 and 0xC0 modes. Latched fault — requires 0x80 (MOTOR_OFF) to clear.
Rate-of-Change Limitingtarget_torque and target_velocity changes are rate-limited per PDO cycle to protect against SPI corruption.
Control Source TrackingAutomatic tracking of control source (CAN_VESC, CAN_RMD, ECAT, TERMINAL). PDO timeout only triggers for EtherCAT source.
Deferred EEPROM StoreSDO writes update RAM immediately but defer flash/EEPROM storage until motor is idle, preventing FOC ISR disruption.

Terminal Commands

CommandDescription
or_soesShow SOES status: AL state, poll cycle, PDO count, DC SYNC0 state, control mode, errors
or_sQuick status: control_mode, ctrl_source, ecat_fault, mc_fault