Made changes reflecting PR comments.

Added torque_ramp_rate to controller config.
Changed INPUT_MODE_CURRENT_RAMP to INPUT_MODE_TORQUE_RAMP for controller input mode enum.
Torque limits and current limits are now observed seperately. Torque limit is in the controller, current limit is in the motor object.
Fixed torque -> current calculation in motor_update to handle ACIM motors.
This commit is contained in:
pjohnson
2020-06-17 13:15:36 -04:00
parent d78119e29f
commit ceabd24582
9 changed files with 35 additions and 32 deletions
+5 -6
View File
@@ -163,8 +163,8 @@ bool Controller::update(float* torque_setpoint_output) {
vel_setpoint_ += step;
torque_setpoint_ = (step / current_meas_period) * config_.inertia;
} break;
case INPUT_MODE_CURRENT_RAMP: {
float max_step_size = std::abs(current_meas_period * config_.current_ramp_rate);
case INPUT_MODE_TORQUE_RAMP: {
float max_step_size = std::abs(current_meas_period * config_.torque_ramp_rate);
float full_step = input_torque_ - torque_setpoint_;
float step = std::clamp(full_step, -max_step_size, max_step_size);
@@ -319,11 +319,10 @@ bool Controller::update(float* torque_setpoint_output) {
torque = limitVel(config_.vel_limit, *vel_estimate_src, vel_gain, torque);
}
// Current limiting
// TODO: Change to controller working in torque units
// and get the torque limits from a function of the motor
// Limit max torque to a user defined torque limit. This functions as an acceleration limit.
// The motor object handles current limiting
bool limited = false;
float Tlim = axis_->motor_.effective_torque_lim();
float Tlim = axis_->motor_.config_.torque_lim;
if (torque > Tlim) {
limited = true;
torque = Tlim;
+1 -1
View File
@@ -28,7 +28,7 @@ public:
float vel_limit = 20000.0f; // [counts/s] Infinity to disable.
float vel_limit_tolerance = 1.2f; // ratio to vel_lim. Infinity to disable.
float vel_ramp_rate = 10000.0f; // [(counts/s) / s]
float current_ramp_rate = 1.0f; // A / sec
float torque_ramp_rate = 0.1f; // Nm / sec
bool setpoints_in_cpr = false;
float inertia = 0.0f; // [A/(count/s^2)]
float input_filter_bandwidth = 2.0f; // [1/s]
+17 -10
View File
@@ -177,19 +177,19 @@ bool Motor::do_checks() {
return true;
}
float Motor::effective_torque_lim() {
float Motor::effective_current_lim() {
// Configured limit
float torque_lim = config_.torque_lim;
float current_lim = config_.current_lim;
// Hardware limit
if (axis_->motor_.config_.motor_type == Motor::MOTOR_TYPE_GIMBAL) {
torque_lim = std::min(torque_lim, 0.98f*one_by_sqrt3*vbus_voltage); //gimbal motor is voltage control, not Nm or A
current_lim = std::min(current_lim, 0.98f*one_by_sqrt3*vbus_voltage); //gimbal motor is voltage control
} else {
torque_lim = std::min(torque_lim, axis_->motor_.current_control_.max_allowed_torque);
current_lim = std::min(current_lim, axis_->motor_.current_control_.max_allowed_current);
}
// Thermal limit
torque_lim = std::min(torque_lim, thermal_torque_lim_);
current_lim = std::min(current_lim, thermal_current_lim_);
return torque_lim;
return current_lim;
}
void Motor::log_timing(TimingLog_t log_idx) {
@@ -359,7 +359,7 @@ bool Motor::FOC_current(float Id_des, float Iq_des, float I_phase, float pwm_pha
ictrl.Id_measured += ictrl.I_measured_report_filter_k * (Id - ictrl.Id_measured);
// Check for violation of current limit
float I_trip = (effective_torque_lim() + config_.torque_lim_margin) / config_.torque_constant;
float I_trip = effective_current_lim() + config_.current_lim_margin;
if (SQ(Id) + SQ(Iq) > SQ(I_trip)) {
set_error(ERROR_CURRENT_LIMIT_VIOLATION);
return false;
@@ -441,13 +441,20 @@ bool Motor::FOC_current(float Id_des, float Iq_des, float I_phase, float pwm_pha
bool Motor::update(float torque_setpoint, float phase, float phase_vel) {
float current_setpoint = torque_setpoint / config_.torque_constant;
current_setpoint *= config_.direction;
float current_setpoint;
phase *= config_.direction;
phase_vel *= config_.direction;
if (config_.motor_type == MOTOR_TYPE_ACIM) {
current_setpoint = torque_setpoint / (config_.torque_constant * fmax(current_control_.acim_rotor_flux, config_.acim_gain_min_flux));
}
else {
current_setpoint = torque_setpoint / config_.torque_constant;
}
current_setpoint *= config_.direction;
// TODO: 2-norm vs independent clamping (current could be sqrt(2) bigger)
float ilim = effective_torque_lim() / config_.torque_constant;
float ilim = effective_current_lim();
float id = std::clamp(current_control_.Id_setpoint, -ilim, ilim);
float iq = std::clamp(current_setpoint, -ilim, ilim);
+1 -3
View File
@@ -29,7 +29,6 @@ public:
float Id_measured; // [A]
float I_measured_report_filter_k;
float max_allowed_current; // [A]
float max_allowed_torque; // [Nm]
float overcurrent_trip_level; // [A]
float acim_rotor_flux; // [A]
float async_phase_vel; // [rad/s electrical]
@@ -96,7 +95,7 @@ public:
bool do_checks();
float get_inverter_temp();
bool update_thermal_limits(float fet_temp);
float effective_torque_lim();
float effective_current_lim();
void log_timing(TimingLog_t log_idx);
float phase_current_from_adcval(uint32_t ADCValue);
bool measure_phase_resistance(float test_current, float max_voltage);
@@ -153,7 +152,6 @@ public:
.Id_measured = 0.0f,
.I_measured_report_filter_k = 1.0f,
.max_allowed_current = 0.0f,
.max_allowed_torque = 0.0f,
.overcurrent_trip_level = 0.0f,
.acim_rotor_flux = 0.0f,
.async_phase_vel = 0.0f,
+3 -4
View File
@@ -376,7 +376,6 @@ interfaces:
Id_measured: float32
I_measured_report_filter_k: float32
max_allowed_current: readonly float32
max_allowed_torque: readonly float32
overcurrent_trip_level: readonly float32
acim_rotor_flux: float32
async_phase_vel: readonly float32
@@ -497,9 +496,9 @@ interfaces:
type: float32
doc: Ratio to `vel_limit`. Infinity to disable.
vel_ramp_rate: float32
current_ramp_rate:
torque_ramp_rate:
type: float32
unit: A / sec
unit: Nm / sec
homing_speed:
type: float32
unit: counts/s
@@ -692,7 +691,7 @@ valuetypes:
PosFilter:
MixChannels:
TrapTraj:
CurrentRamp:
TorqueRamp:
Mirror:
+2 -2
View File
@@ -77,7 +77,7 @@ Possible values are:
* `INPUT_MODE_POS_FILTER`
* `INPUT_MODE_MIX_CHANNELS`
* `INPUT_MODE_TRAP_TRAJ`
* `INPUT_MODE_CURRENT_RAMP`
* `INPUT_MODE_TORQUE_RAMP`
* `INPUT_MODE_MIRROR`
For more information, see [input_modes](input_modes.md).
@@ -97,7 +97,7 @@ Possible values are:
* `INPUT_MODE_POS_FILTER`
* `INPUT_MODE_MIX_CHANNELS`
* `INPUT_MODE_TRAP_TRAJ`
* `INPUT_MODE_CURRENT_RAMP`
* `INPUT_MODE_TORQUE_RAMP`
* `INPUT_MODE_MIRROR`
## System monitoring commands
+1 -1
View File
@@ -348,7 +348,7 @@ You can now control the velocity with `axis.controller.input_vel = 5000` [count/
### Torque control
Set `axis.controller.config.control_mode = CONTROL_MODE_CURRENT_CONTROL`.<br>
You can now control the torque with `axis.controller.input_torque = 3` [Nm].
You can now control the torque with `axis.controller.input_torque = 0.1` [Nm].
Note: If you exceed `vel_limit` in current control mode, the current is reduced. To disable this, set `axis.controller.enable_current_mode_vel_limit = False`.
+4 -4
View File
@@ -13,7 +13,7 @@ The Input Modes currently valid are:
* `INPUT_MODE_POS_FILTER`
* `INPUT_MODE_MIX_CHANNELS`
* `INPUT_MODE_TRAP_TRAJ`
* `INPUT_MODE_CURRENT_RAMP`
* `INPUT_MODE_TORQUE_RAMP`
* `INPUT_MODE_MIRROR`
---
@@ -85,11 +85,11 @@ Implementes an online trapezoidal trajectory planner.
### Valid Control Modes:
* `CONTROL_MODE_POSITION_CONTROL`
## INPUT_MODE_CURRENT_RAMP
Ramp a current command from the current value to the target value.
## INPUT_MODE_TORQUE_RAMP
Ramp a torque command from the current value to the target value.
### Configuration Values:
* `<axis>.controller.config.current_ramp_rate`
* `<axis>.controller.config.torque_ramp_rate`
### Valid Inputs:
* `input_torque`
+1 -1
View File
@@ -9,7 +9,7 @@
"type": "python",
"request": "launch",
"stopOnEntry": true,
"pythonPath": "${config:python.interpreterPath}",
"pythonPath": "${command:python.pythonPath}",
"program": "${file}",
"cwd": "${workspaceRoot}",
"env": {},