Bug Report: DC Motor PPM Position Control Broken
Title
mc_interface_get_control_mode() always returns CONTROL_MODE_NONE for DC and BLDC motors, breaking PPM position control
Description
PPM position control (PPM_CTRL_TYPE_PID_POSITION_180 and PPM_CTRL_TYPE_PID_POSITION_360) is non-functional for DC and BLDC motors. The motor only moves within approximately 10 degrees of the current position because the safe-start activation gate applies on every single PPM loop iteration.
Steps to Reproduce
- Configure VESC with a DC motor and ABI encoder
- Set PPM control type to
PPM_CTRL_TYPE_PID_POSITION_180 or PPM_CTRL_TYPE_PID_POSITION_360
- Move the PPM stick
- Observe that the motor only moves within ~10 degrees of the current position
Expected Behavior
The motor should follow the PPM stick position across the full 0-180 or 0-360 degree range. Once position control is activated (passing the 10-degree gate), the motor should follow freely without the gate re-applying.
Actual Behavior
The motor only moves within ~10 degrees of the current position. The 10-degree activation gate applies on every PPM iteration, preventing full-range position control.
Root Cause
In motor/mc_interface.c, the function mc_interface_get_control_mode() only handles MOTOR_TYPE_FOC: 1
mc_control_mode mc_interface_get_control_mode(void) {
mc_control_mode ret = CONTROL_MODE_NONE;
switch (motor_now()->m_conf.motor_type) {
case MOTOR_TYPE_FOC:
ret = mcpwm_foc_control_mode();
break;
default:
break; // DC and BLDC always return CONTROL_MODE_NONE
}
return ret;
}
For DC and BLDC motors, this falls through to default: break and always returns CONTROL_MODE_NONE. This causes the PPM position control check at line 370 of app_ppm.c to always evaluate to true: 2
if (mc_interface_get_control_mode() != CONTROL_MODE_POS){ // ALWAYS TRUE for DC
if (fabsf(angle - mc_interface_get_pid_pos_now()) < 10) {
mc_interface_set_pid_pos(angle);
}
break; // always breaks, never reaches else
} else {
mc_interface_set_pid_pos(angle); // DC motor NEVER reaches this
}
The else branch that allows free position following is unreachable for DC motors. The 10-degree gate applies on every iteration.
Fix
Add a getter function mcpwm_get_control_mode() to motor/mcpwm.c and motor/mcpwm.h, then update mc_interface_get_control_mode() to handle DC/BLDC motors:
mc_control_mode mc_interface_get_control_mode(void) {
mc_control_mode ret = CONTROL_MODE_NONE;
switch (motor_now()->m_conf.motor_type) {
case MOTOR_TYPE_BLDC:
case MOTOR_TYPE_DC:
ret = mcpwm_get_control_mode(); // need to add this getter
break;
case MOTOR_TYPE_FOC:
ret = mcpwm_foc_control_mode();
break;
default:
break;
}
return ret;
}
Additional Issues Found
1. Wrong-direction behavior in 180 mode
For PPM_CTRL_TYPE_PID_POSITION_180, utils_norm_angle maps negative angles to 270-360 degrees, causing the motor to move in the opposite direction when the stick is moved left: 3 4
2. Inconsistent PID error calculation
The DC motor position PID computes error as utils_angle_difference(pos_now, pos_pid_set_pos) (current minus setpoint), while the FOC version uses utils_angle_difference(angle_set, angle_now) (setpoint minus current). This inconsistency may cause the motor to take the long way around for some angle combinations: 5 6
Notes
- Affects:
MOTOR_TYPE_DC and MOTOR_TYPE_BLDC
- Does not affect:
MOTOR_TYPE_FOC
- Workaround: Use UART
COMM_SET_POS or CAN CAN_PACKET_SET_POS instead of PPM (these bypass the broken code path)
- Related files:
motor/mc_interface.c, motor/mcpwm.c, motor/mcpwm.h, applications/app_ppm.c
Wiki pages you might want to explore:
Citations
File: motor/mc_interface.c (L545-556)
mc_control_mode mc_interface_get_control_mode(void) {
mc_control_mode ret = CONTROL_MODE_NONE;
switch (motor_now()->m_conf.motor_type) {
case MOTOR_TYPE_FOC:
ret = mcpwm_foc_control_mode();
break;
default:
break;
}
return ret;
}
File: applications/app_ppm.c (L361-366)
if (config.ctrl_type == PPM_CTRL_TYPE_PID_POSITION_180) {
angle = (servo_val * 180); // -1 <> +1
} else {
angle = (servo_val * 360); // 0 <> +1
}
utils_norm_angle(&angle);
File: applications/app_ppm.c (L370-378)
if (mc_interface_get_control_mode() != CONTROL_MODE_POS){
if (fabsf(angle - mc_interface_get_pid_pos_now()) < 10) {
// enable position control.
mc_interface_set_pid_pos(angle);
}
break;
} else {
mc_interface_set_pid_pos(angle);
}
Bug Report: DC Motor PPM Position Control Broken
Title
mc_interface_get_control_mode()always returnsCONTROL_MODE_NONEfor DC and BLDC motors, breaking PPM position controlDescription
PPM position control (
PPM_CTRL_TYPE_PID_POSITION_180andPPM_CTRL_TYPE_PID_POSITION_360) is non-functional for DC and BLDC motors. The motor only moves within approximately 10 degrees of the current position because the safe-start activation gate applies on every single PPM loop iteration.Steps to Reproduce
PPM_CTRL_TYPE_PID_POSITION_180orPPM_CTRL_TYPE_PID_POSITION_360Expected Behavior
The motor should follow the PPM stick position across the full 0-180 or 0-360 degree range. Once position control is activated (passing the 10-degree gate), the motor should follow freely without the gate re-applying.
Actual Behavior
The motor only moves within ~10 degrees of the current position. The 10-degree activation gate applies on every PPM iteration, preventing full-range position control.
Root Cause
In
motor/mc_interface.c, the functionmc_interface_get_control_mode()only handlesMOTOR_TYPE_FOC: 1For DC and BLDC motors, this falls through to
default: breakand always returnsCONTROL_MODE_NONE. This causes the PPM position control check at line 370 ofapp_ppm.cto always evaluate to true: 2The
elsebranch that allows free position following is unreachable for DC motors. The 10-degree gate applies on every iteration.Fix
Add a getter function
mcpwm_get_control_mode()tomotor/mcpwm.candmotor/mcpwm.h, then updatemc_interface_get_control_mode()to handle DC/BLDC motors:Additional Issues Found
1. Wrong-direction behavior in 180 mode
For
PPM_CTRL_TYPE_PID_POSITION_180,utils_norm_anglemaps negative angles to 270-360 degrees, causing the motor to move in the opposite direction when the stick is moved left: 3 42. Inconsistent PID error calculation
The DC motor position PID computes error as
utils_angle_difference(pos_now, pos_pid_set_pos)(current minus setpoint), while the FOC version usesutils_angle_difference(angle_set, angle_now)(setpoint minus current). This inconsistency may cause the motor to take the long way around for some angle combinations: 5 6Notes
MOTOR_TYPE_DCandMOTOR_TYPE_BLDCMOTOR_TYPE_FOCCOMM_SET_POSor CANCAN_PACKET_SET_POSinstead of PPM (these bypass the broken code path)motor/mc_interface.c,motor/mcpwm.c,motor/mcpwm.h,applications/app_ppm.cWiki pages you might want to explore:
Citations
File: motor/mc_interface.c (L545-556)
File: applications/app_ppm.c (L361-366)
File: applications/app_ppm.c (L370-378)