Hello community.
We are using MAXON 200142 motor.
As an encoder we are using 3 built-in HALL sensors. As the motor has 8 poles we’ve got 48 cpr.
We are using POSITION_CONTROL mode. The motor executes an oscillating movement (go forward for X steps without speed limit then go backwards to the original position again without speed limit, only the current is limited), basically we are using it for doing injections.
The motor calibrates successfully and works fine for X amount of time. If a load (syringe)is attached then it works for about 80 -100 injections, without the syringe it can run into the error after 2 injections. The errors are:
Axis::ERROR_MOTOR_DISARMED;
Motor::ERROR_CONTROL_DEADLINE_MISSED;
The ERROR_CONTROL_DEADLINE_MISSED is set inside the pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) function, and I can assume that it happens because the other_axis.motor_.next_timings_valid_
were not valid in time.
What could be the reason for that? What else can I check in the software?
I have to remind that the error is always triggered when the backwards movement is started, as in the folowing traces:
- image_1 (error detected): https://drive.google.com/file/d/1b7kB1SsObI_6jZrkhSZe7YcEHWp7zfKI/view?usp=sharing
- image_2 normal operation: https://drive.google.com/file/d/1mkUnsCLqfl_i3CxjdGbpMfp9QIE4tEht/view?usp=sharing
Trace were collected using a ST-LINK probe.
Code:
configureMotor()
{
Controller::Config_t &c = axis->controller_.config_;
c.pos_gain = 5;
c.vel_gain = 0.001;
c.vel_integrator_gain = 0.1;
c.vel_limit = 3000;
c.vel_limit_tolerance = 2;
c.vel_ramp_rate = 10000;
c.setpoints_in_cpr = false;
c.control_mode = Controller::CTRL_MODE_VELOCITY_CONTROL;
Motor::Config_t &m = axis->motor_.config_;
m.pre_calibrated = true; // Calibration is not required for gimball typ
m.pole_pairs = 8;
m.calibration_current = 1;
m.resistance_calib_max_voltage = 2;
m.phase_inductance = 0;
m.phase_resistance = 0;
m.direction = 1;
m.motor_type = Motor::MOTOR_TYPE_GIMBAL;
m.current_lim = 6;
m.current_lim_tolerance = 1.25;
m.inverter_temp_limit_lower = 100;
m.inverter_temp_limit_upper = 120;
m.requested_current_range = 25;
m.current_control_bandwidth = 100;
Encoder::Config_t &e = axis->encoder_.config_;
e.mode = Encoder::MODE_HALL;
e.use_index = false;
e.find_idx_on_lockin_only = false;
e.pre_calibrated = false;
e.zero_count_on_find_idx = true;
e.cpr = 48;
e.offset = 72;
e.offset_float = 1.4792187213897705;
e.enable_phase_interpolation = true;
e.bandwidth = 100.0;
e.calib_range = 0.02;
e.calib_scan_distance = 50.26548385620117;
e.calib_scan_omega = 12.566370964050293;
e.idx_search_unidirectional = false;
e.ignore_illegal_hall_state = false;
board_config.dc_bus_undervoltage_trip_level = 4.0f;
osDelay(100);
osDelay(1000);
m.current_lim = 2;
m.requested_current_range = 25;
c.vel_limit = 3000;
m.calibration_current = 1;
m.pole_pairs = 8;
m.motor_type = Motor::MOTOR_TYPE_GIMBAL;
}
//Move backward funtcion
moveSlow(float target)
{
axes[0]->requested_state_ = Axis::AXIS_STATE_CLOSED_LOOP_CONTROL;
axes[0]->controller_.config_.control_mode = Controller::CTRL_MODE_POSITION_CONTROL;
axes[0]->controller_.config_.vel_limit = 3000;
axes[0]->motor_.config_.current_lim = 2;
axes[0]->controller_.config_.pos_gain = 20;
axes[0]->controller_.config_.vel_gain = 0.01;
axes[0]->controller_.config_.vel_integrator_gain = 0.1;
osDelay(100);
axes[0]->controller_.move_to_pos(target);
// Wait for motor to reach position
float error;
int count = 0;
int vel;
do
{
vel = axes[0]->encoder_.vel_estimate_;
bkw_speed = vel;
if(vel < minSpeed)
minSpeed = vel;
osDelay(10);
error = axes[0]->encoder_.pos_estimate_ - target;
bkw_error = error;
fabs(error) > MOVE_SLOW_POS_DELTA_ERR ? count = 0 : count++;
}
while(count < 2);
axes[0]->requested_state_ = Axis::AXIS_STATE_IDLE;
bkw_speed = 0;
bkw_error = 0;
return axes[0]->error_ == Axis::ERROR_NONE;
}
//Move forward function
moveFast(float target)
{
axes[0]->requested_state_ = Axis::AXIS_STATE_CLOSED_LOOP_CONTROL;
axes[0]->controller_.config_.control_mode = Controller::CTRL_MODE_POSITION_CONTROL;
axes[0]->controller_.config_.vel_limit = 3000;
axes[0]->motor_.config_.current_lim = 5;
axes[0]->controller_.config_.pos_gain = 20;
axes[0]->controller_.config_.vel_gain = 0.01;
axes[0]->controller_.config_.vel_integrator_gain = 0.1;
osDelay(100);
axes[0]->controller_.move_to_pos((int)target);
// Wait for motor to reach position
float error;
int count = 0;
int vel;
do
{
vel = axes[0]->encoder_.vel_estimate_;
fw_speed = vel;
if(vel > maxSpeed)
maxSpeed = vel;
osDelay(10);
error = axes[0]->encoder_.pos_estimate_ - (int)target;
fw_error = error;
error = abs(error);
if(error > MOVE_FAST_POS_DELTA_ERR)
count = 0;
else
count++;
}
while(count < 5);
axes[0]->requested_state_ = Axis::AXIS_STATE_IDLE;
fw_speed = 0;
fw_error = 0;
return axes[0]->error_ == Axis::ERROR_NONE;
}