Skip to content

Bug Report: DC Motor PPM Position Control Broken #914

Description

@Kenaiwolf

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

  1. Configure VESC with a DC motor and ABI encoder
  2. Set PPM control type to PPM_CTRL_TYPE_PID_POSITION_180 or PPM_CTRL_TYPE_PID_POSITION_360
  3. Move the PPM stick
  4. 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);
				}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions