|
@@ -7,18 +7,22 @@
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
参考 MC_Simulink\modules\off_line_params_ind 仿真模型
|
|
参考 MC_Simulink\modules\off_line_params_ind 仿真模型
|
|
|
|
|
+必须空载测试
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
static void _rs_ind_timer_handler(shark_timer_t *);
|
|
static void _rs_ind_timer_handler(shark_timer_t *);
|
|
|
static shark_timer_t _rs_ind_timer = TIMER_INIT(_rs_ind_timer, _rs_ind_timer_handler);
|
|
static shark_timer_t _rs_ind_timer = TIMER_INIT(_rs_ind_timer, _rs_ind_timer_handler);
|
|
|
static void _ldq_ind_timer_handler(shark_timer_t *);
|
|
static void _ldq_ind_timer_handler(shark_timer_t *);
|
|
|
static shark_timer_t _ldq_ind_timer = TIMER_INIT(_ldq_ind_timer, _ldq_ind_timer_handler);
|
|
static shark_timer_t _ldq_ind_timer = TIMER_INIT(_ldq_ind_timer, _ldq_ind_timer_handler);
|
|
|
|
|
+static void _flux_ind_timer_handler(shark_timer_t *);
|
|
|
|
|
+static shark_timer_t _flux_ind_timer = TIMER_INIT(_flux_ind_timer, _flux_ind_timer_handler);
|
|
|
|
|
|
|
|
static float rs_id_max, rs_vd_max, rs_vd_now, rs_est_value;
|
|
static float rs_id_max, rs_vd_max, rs_vd_now, rs_est_value;
|
|
|
static s32 rs_meas_time;
|
|
static s32 rs_meas_time;
|
|
|
-static bool b_rs_ind = false, b_rs_ested = false, b_ldq_ind = false, b_ld_ested = false, b_lq_ested = false;;
|
|
|
|
|
|
|
+static bool b_rs_ind = false, b_rs_ested = false, b_ldq_ind = false, b_ld_ested = false, b_lq_ested = false, b_flux_ind = false, b_flux_ested = false;
|
|
|
|
|
+static u8 rs_ind_step = 0;
|
|
|
void mot_params_ind_rs(float vd_max, float id_max, s32 time) {
|
|
void mot_params_ind_rs(float vd_max, float id_max, s32 time) {
|
|
|
- if (b_rs_ind || b_ldq_ind) {
|
|
|
|
|
|
|
+ if (b_rs_ind || b_ldq_ind || b_flux_ind) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
b_rs_ind = true;
|
|
b_rs_ind = true;
|
|
@@ -27,18 +31,23 @@ void mot_params_ind_rs(float vd_max, float id_max, s32 time) {
|
|
|
rs_vd_max = vd_max;
|
|
rs_vd_max = vd_max;
|
|
|
rs_vd_now = 2.0f;
|
|
rs_vd_now = 2.0f;
|
|
|
rs_meas_time = time;
|
|
rs_meas_time = time;
|
|
|
|
|
+ PMSM_FOC_Set_MotAngle(0);
|
|
|
PMSM_FOC_SetOpenVdq_Immediate(rs_vd_now, 0);
|
|
PMSM_FOC_SetOpenVdq_Immediate(rs_vd_now, 0);
|
|
|
|
|
|
|
|
|
|
+ rs_ind_step = 1;
|
|
|
shark_timer_post(&_rs_ind_timer, 10);
|
|
shark_timer_post(&_rs_ind_timer, 10);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void mot_params_ind_stop(void) {
|
|
void mot_params_ind_stop(void) {
|
|
|
shark_timer_cancel(&_rs_ind_timer);
|
|
shark_timer_cancel(&_rs_ind_timer);
|
|
|
shark_timer_cancel(&_ldq_ind_timer);
|
|
shark_timer_cancel(&_ldq_ind_timer);
|
|
|
|
|
+ shark_timer_cancel(&_flux_ind_timer);
|
|
|
u32 mask = cpu_enter_critical();
|
|
u32 mask = cpu_enter_critical();
|
|
|
b_rs_ind = false;
|
|
b_rs_ind = false;
|
|
|
b_ldq_ind = false;
|
|
b_ldq_ind = false;
|
|
|
|
|
+ b_flux_ind = false;
|
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
|
|
|
+ PMSM_FOC_Set_Current(0);
|
|
|
cpu_exit_critical(mask);
|
|
cpu_exit_critical(mask);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -49,43 +58,59 @@ static void _rs_ind_timer_handler(shark_timer_t *t) {
|
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (PMSM_FOC_Get()->out.s_RealIdq.d < rs_id_max) {
|
|
|
|
|
- rs_vd_now += 0.1f;
|
|
|
|
|
- wait_iq_0_cnt = 0;
|
|
|
|
|
- if (rs_vd_now >= rs_vd_max) {
|
|
|
|
|
- PMSM_FOC_SetOpenVdq(0, 0);
|
|
|
|
|
- b_rs_ind = false;
|
|
|
|
|
- sys_debug("id not reach max id %f\n", PMSM_FOC_Get()->out.s_RealIdq.d);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- PMSM_FOC_SetOpenVdq_Immediate(rs_vd_now, 0);
|
|
|
|
|
- }else {
|
|
|
|
|
- if (ABS(PMSM_FOC_Get()->out.s_FilterIdq.q) > 1.0f) {
|
|
|
|
|
- wait_iq_0_cnt++;
|
|
|
|
|
- if (wait_iq_0_cnt >= 200) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ switch (rs_ind_step) {
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ if (PMSM_FOC_Get()->out.s_RealIdq.d < rs_id_max) {
|
|
|
|
|
+ rs_vd_now += 0.1f;
|
|
|
|
|
+ wait_iq_0_cnt = 0;
|
|
|
|
|
+ if (rs_vd_now >= rs_vd_max) {
|
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
PMSM_FOC_SetOpenVdq(0, 0);
|
|
|
b_rs_ind = false;
|
|
b_rs_ind = false;
|
|
|
- sys_debug("iq is bigger chan 1, %f\n", PMSM_FOC_Get()->out.s_FilterIdq.q);
|
|
|
|
|
|
|
+ sys_debug("id not reach max id %f\n", PMSM_FOC_Get()->out.s_RealIdq.d);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ PMSM_FOC_SetOpenVdq_Immediate(rs_vd_now, 0);
|
|
|
}else {
|
|
}else {
|
|
|
- float *iabc = PMSM_FOC_Get()->in.s_iABC;
|
|
|
|
|
- float d, q;
|
|
|
|
|
- PMSM_FOC_ABC2Dq(SIGN(iabc[0]), SIGN(iabc[1]), SIGN(iabc[2]), &d, &q);
|
|
|
|
|
- float dtc = ((float)CONFIG_HW_DeadTime/(float)FOC_PWM_Half_Period) * PMSM_FOC_Get()->in.s_vDC * 1.5f;
|
|
|
|
|
- float vd = (rs_vd_now - dtc) * TWO_BY_THREE;
|
|
|
|
|
- float rs = vd / (PMSM_FOC_Get()->out.s_RealIdq.d + 0.00000000001f);
|
|
|
|
|
- rs_est_value = LowPass_Filter(rs_est_value, rs, 0.2f);
|
|
|
|
|
- if (rs_meas_time-- <= 0) {
|
|
|
|
|
- mc_ind_motor_start(false);
|
|
|
|
|
- mot_params_ind_stop();
|
|
|
|
|
- finish = true;
|
|
|
|
|
- b_rs_ested = true;
|
|
|
|
|
- sys_debug("est rs = %f\n", rs_est_value);
|
|
|
|
|
- sys_debug("vd is %f\n", rs_vd_now);
|
|
|
|
|
|
|
+ rs_ind_step = 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 2:
|
|
|
|
|
+ if (PMSM_FOC_Get()->out.s_RealIdq.d < rs_id_max) {
|
|
|
|
|
+ rs_vd_now += 0.1f;
|
|
|
|
|
+ wait_iq_0_cnt = 0;
|
|
|
|
|
+ if (rs_vd_now >= rs_vd_max) {
|
|
|
|
|
+ PMSM_FOC_SetOpenVdq(0, 0);
|
|
|
|
|
+ b_rs_ind = false;
|
|
|
|
|
+ sys_debug("id not reach max id %f\n", PMSM_FOC_Get()->out.s_RealIdq.d);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+ PMSM_FOC_SetOpenVdq_Immediate(rs_vd_now, 0);
|
|
|
|
|
+ }else {
|
|
|
|
|
+ rs_ind_step = 3;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 3: {
|
|
|
|
|
+ float *iabc = PMSM_FOC_Get()->in.s_iABC;
|
|
|
|
|
+ float d, q;
|
|
|
|
|
+ PMSM_FOC_ABC2Dq(SIGN(iabc[0]), SIGN(iabc[1]), SIGN(iabc[2]), &d, &q);
|
|
|
|
|
+ float dtc = ((float)CONFIG_HW_DeadTime/(float)FOC_PWM_Half_Period) * PMSM_FOC_Get()->in.s_vDC * 1.5f;
|
|
|
|
|
+ float vd = (rs_vd_now - dtc) * TWO_BY_THREE;
|
|
|
|
|
+ float rs = vd / (PMSM_FOC_Get()->out.s_RealIdq.d + 0.00000000001f);
|
|
|
|
|
+ rs_est_value = LowPass_Filter(rs_est_value, rs, 0.2f);
|
|
|
|
|
+ if (rs_meas_time-- <= 0) {
|
|
|
|
|
+ mc_ind_motor_start(false);
|
|
|
|
|
+ mot_params_ind_stop();
|
|
|
|
|
+ finish = true;
|
|
|
|
|
+ b_rs_ested = true;
|
|
|
|
|
+ sys_debug("est rs = %f\n", rs_est_value);
|
|
|
|
|
+ sys_debug("vd is %f, wait %d\n", rs_vd_now, wait_iq_0_cnt);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (!finish) {
|
|
if (!finish) {
|
|
|
shark_timer_post(&_rs_ind_timer, 10);
|
|
shark_timer_post(&_rs_ind_timer, 10);
|
|
|
}
|
|
}
|
|
@@ -106,18 +131,20 @@ static u16 n_ind_ld, n_samples;
|
|
|
static float ld_est_value, lq_est_value;
|
|
static float ld_est_value, lq_est_value;
|
|
|
static s32 ldq_est_wait_cnt = 0;
|
|
static s32 ldq_est_wait_cnt = 0;
|
|
|
void mot_params_ind_inductance(float v, float freq, u16 l_type) {
|
|
void mot_params_ind_inductance(float v, float freq, u16 l_type) {
|
|
|
- if (b_ldq_ind || b_rs_ind) {
|
|
|
|
|
|
|
+ if (b_ldq_ind || b_rs_ind || b_flux_ind) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!b_rs_ested) { //必须先识别相电阻
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
hj_v = v;
|
|
hj_v = v;
|
|
|
hj_freq = freq;
|
|
hj_freq = freq;
|
|
|
hj_n = (float)FOC_PWM_FS / hj_freq;
|
|
hj_n = (float)FOC_PWM_FS / hj_freq;
|
|
|
- hj_samples = hj_n * 20;
|
|
|
|
|
|
|
+ hj_samples = hj_n * 50;
|
|
|
K_terms = (s32) (0.5f + hj_samples*hj_freq/(float)FOC_PWM_FS);
|
|
K_terms = (s32) (0.5f + hj_samples*hj_freq/(float)FOC_PWM_FS);
|
|
|
Vdead = PMSM_FOC_Get()->in.s_vDC * 0.5f * (float)CONFIG_HW_DeadTime / (float)FOC_PWM_period;
|
|
Vdead = PMSM_FOC_Get()->in.s_vDC * 0.5f * (float)CONFIG_HW_DeadTime / (float)FOC_PWM_period;
|
|
|
hj_w = 360.0f / hj_n;
|
|
hj_w = 360.0f / hj_n;
|
|
|
-
|
|
|
|
|
|
|
+ sys_debug("hj %f, %f, %f, %f, %f, %f, %f\n", hj_v, hj_freq, hj_n, hj_samples, K_terms, Vdead, hj_w);
|
|
|
float fft_angle = 360.0f / hj_samples * K_terms;
|
|
float fft_angle = 360.0f / hj_samples * K_terms;
|
|
|
SinCos_Lut(fft_angle, &hj_image, &hj_real);
|
|
SinCos_Lut(fft_angle, &hj_image, &hj_real);
|
|
|
hj_real = hj_real * 2.0f;
|
|
hj_real = hj_real * 2.0f;
|
|
@@ -134,7 +161,9 @@ void mot_params_ind_inductance(float v, float freq, u16 l_type) {
|
|
|
i_samples = os_alloc(sizeof(float) * hj_samples);
|
|
i_samples = os_alloc(sizeof(float) * hj_samples);
|
|
|
if (v_samples != NULL && i_samples != NULL) {
|
|
if (v_samples != NULL && i_samples != NULL) {
|
|
|
b_ldq_ind = true;
|
|
b_ldq_ind = true;
|
|
|
- shark_timer_post(&_ldq_ind_timer, 50);
|
|
|
|
|
|
|
+ shark_timer_post(&_ldq_ind_timer, 10);
|
|
|
|
|
+ }else {
|
|
|
|
|
+ sys_debug("alloc error\n");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -150,7 +179,7 @@ static void _ldq_ind_timer_handler(shark_timer_t *t) {
|
|
|
mot_params_ind_stop();
|
|
mot_params_ind_stop();
|
|
|
sys_debug("ldq ind timeout %d\n", ldq_est_wait_cnt);
|
|
sys_debug("ldq ind timeout %d\n", ldq_est_wait_cnt);
|
|
|
}else {
|
|
}else {
|
|
|
- shark_timer_post(&_ldq_ind_timer, 50);
|
|
|
|
|
|
|
+ shark_timer_post(&_ldq_ind_timer, 10);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -175,7 +204,7 @@ void mot_params_high_freq_inject(void) {
|
|
|
float s, c;
|
|
float s, c;
|
|
|
SinCos_Lut(hj_angle, &s, &c);
|
|
SinCos_Lut(hj_angle, &s, &c);
|
|
|
float vd = 0, vq = 0;
|
|
float vd = 0, vq = 0;
|
|
|
- if (n_ind_ld == 1) {
|
|
|
|
|
|
|
+ if (n_ind_ld == L_TYPE_D) {
|
|
|
vd = hj_v * c;
|
|
vd = hj_v * c;
|
|
|
}else {
|
|
}else {
|
|
|
vq = hj_v * c;
|
|
vq = hj_v * c;
|
|
@@ -187,12 +216,12 @@ bool mot_params_hj_sample_vi(float vd, float vq, float id, float iq) {
|
|
|
if (!b_ldq_ind) {
|
|
if (!b_ldq_ind) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
- if (n_samples >= 1 && (n_samples) <= (hj_samples + 1)) {
|
|
|
|
|
|
|
+ if ((n_samples >= 1) && (n_samples <= hj_samples)) {
|
|
|
if (n_ind_ld == L_TYPE_D) {
|
|
if (n_ind_ld == L_TYPE_D) {
|
|
|
- v_samples[n_samples - 1] = vd;
|
|
|
|
|
|
|
+ v_samples[n_samples - 1] = vd * TWO_BY_THREE;
|
|
|
i_samples[n_samples - 1] = id;
|
|
i_samples[n_samples - 1] = id;
|
|
|
}else {
|
|
}else {
|
|
|
- v_samples[n_samples - 1] = vq;
|
|
|
|
|
|
|
+ v_samples[n_samples - 1] = vq * TWO_BY_THREE;
|
|
|
i_samples[n_samples - 1] = iq;
|
|
i_samples[n_samples - 1] = iq;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -220,18 +249,20 @@ void mot_params_calc_inductance(void) {
|
|
|
}
|
|
}
|
|
|
goertzel_dft(v_samples, &v_real, &v_image, &v_mag);
|
|
goertzel_dft(v_samples, &v_real, &v_image, &v_mag);
|
|
|
goertzel_dft(i_samples, &i_real, &i_image, &i_mag);
|
|
goertzel_dft(i_samples, &i_real, &i_image, &i_mag);
|
|
|
-
|
|
|
|
|
|
|
+ sys_debug("v %f, %f, %f\n", v_mag/(hj_samples*0.5f), v_real, v_image);
|
|
|
|
|
+ sys_debug("i %f, %f, %f\n", i_mag/(hj_samples*0.5f), i_real, i_image);
|
|
|
v_mag -= Vdead * hj_samples*0.5f;
|
|
v_mag -= Vdead * hj_samples*0.5f;
|
|
|
|
|
|
|
|
- float z_angle = fast_atan_2(i_real, i_image) - fast_atan_2(v_real, v_image);
|
|
|
|
|
|
|
+ float z_angle = fast_atan_2(i_image, i_real) - fast_atan_2(v_image, v_real);
|
|
|
float s,c;
|
|
float s,c;
|
|
|
- SinCos_Lut(z_angle, &s, &c);
|
|
|
|
|
|
|
+ SinCos_Lut(pi_2_degree(z_angle), &s, &c);
|
|
|
|
|
|
|
|
float z_mag = v_mag / (i_mag + 0.0000001f);
|
|
float z_mag = v_mag / (i_mag + 0.0000001f);
|
|
|
float z_real = z_mag * c;
|
|
float z_real = z_mag * c;
|
|
|
float z_image = z_mag * s;
|
|
float z_image = z_mag * s;
|
|
|
- float Ri = SQ(z_real - b_rs_ested) + SQ(z_image)/(z_real - b_rs_ested + 0.0000001f);
|
|
|
|
|
- float l = Ri * (z_real - rs_est_value)/(hj_freq * 2 * PI * z_image + 0.0000001f);
|
|
|
|
|
|
|
+ float Rs = rs_est_value;
|
|
|
|
|
+ float Ri = (SQ(z_real - Rs) + SQ(z_image))/(z_real - Rs + 0.0000001f);
|
|
|
|
|
+ float l = Ri * (z_real - Rs)/(hj_freq * 2 * PI * z_image + 0.0000001f) * 0.83f; //0.83f just for v3 board
|
|
|
if (n_ind_ld == L_TYPE_D) {
|
|
if (n_ind_ld == L_TYPE_D) {
|
|
|
ld_est_value = l;
|
|
ld_est_value = l;
|
|
|
b_ld_ested = true;
|
|
b_ld_ested = true;
|
|
@@ -243,6 +274,45 @@ void mot_params_calc_inductance(void) {
|
|
|
}
|
|
}
|
|
|
b_ldq_ind = false;
|
|
b_ldq_ind = false;
|
|
|
}
|
|
}
|
|
|
|
|
+static float motVelRadusPers, flux_wait_cnt = 0, flux_do_cnt = 0, flux_est_value = 0;
|
|
|
|
|
+static void _flux_ind_timer_handler(shark_timer_t *t) {
|
|
|
|
|
+ float We = PMSM_FOC_Get()->in.s_motVelRadusPers;
|
|
|
|
|
+ float delta = We - motVelRadusPers;
|
|
|
|
|
+ if (We > 100 && ABS(delta) < 40) {
|
|
|
|
|
+ float dtc = ((float)CONFIG_HW_DeadTime/(float)FOC_PWM_Half_Period) * PMSM_FOC_Get()->in.s_vDC * 1.5f;
|
|
|
|
|
+ float vq = (PMSM_FOC_Get()->out.s_OutVdq.q - dtc) * TWO_BY_THREE;
|
|
|
|
|
+ float flux = vq / We;
|
|
|
|
|
+ flux_est_value = LowPass_Filter(flux_est_value, flux, 0.1f);
|
|
|
|
|
+ flux_do_cnt ++;
|
|
|
|
|
+ }else {
|
|
|
|
|
+ flux_wait_cnt ++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((flux_wait_cnt >= 100) || (flux_do_cnt >= 400)) {
|
|
|
|
|
+ b_flux_ind = false;
|
|
|
|
|
+ if (flux_wait_cnt >= 100) {
|
|
|
|
|
+ sys_debug("ind flux error\n");
|
|
|
|
|
+ }else {
|
|
|
|
|
+ b_flux_ested = true;
|
|
|
|
|
+ sys_debug("ind_flux finish, %f\n", flux_est_value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }else {
|
|
|
|
|
+ shark_timer_post(&_flux_ind_timer, 10);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void mot_params_ind_flux(float id, float iq) {
|
|
|
|
|
+ if (b_rs_ind || b_ldq_ind || b_flux_ind) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ b_flux_ind = true;
|
|
|
|
|
+ flux_wait_cnt = 0;
|
|
|
|
|
+ flux_do_cnt = 0;
|
|
|
|
|
+ flux_est_value = 0;
|
|
|
|
|
+ mc_set_foc_mode(CTRL_MODE_CURRENT);
|
|
|
|
|
+ PMSM_FOC_Set_Current(iq);
|
|
|
|
|
+ shark_timer_post(&_flux_ind_timer, 10);
|
|
|
|
|
+ motVelRadusPers = PMSM_FOC_Get()->in.s_motVelRadusPers;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
float mot_params_get_est_ld(void) {
|
|
float mot_params_get_est_ld(void) {
|
|
|
return ld_est_value;
|
|
return ld_est_value;
|
|
@@ -259,3 +329,11 @@ bool mot_params_lq_ested(void) {
|
|
|
return b_lq_ested;
|
|
return b_lq_ested;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+bool mot_params_flux_ested(void) {
|
|
|
|
|
+ return b_flux_ested;
|
|
|
|
|
+}
|
|
|
|
|
+float mot_params_get_est_flux(void) {
|
|
|
|
|
+ return flux_est_value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|