Преглед изворни кода

1. 增加相电压示波器显示
2. adc采集尽量让3个端电压一起采集
3. ladrc无感控制,加入一个控制器周期的补偿
4. 电机参数识别使用相电压采集后的数据进行计算

Signed-off-by: kevin <huhui@sharkgulf.com>

kevin пре 2 година
родитељ
комит
2677c8fbe1

+ 4 - 4
Applications/bsp/gd32/adc.c

@@ -33,7 +33,7 @@
 #define THROTTLE_BUFF_IDX 4
 #define VBUS_I_BUFF_IDX 5
 
-#define THROTTLE2_BUFF_IDX 6
+#define THROTTLE2_BUFF_IDX 14
 #define V_VOL_BUFF_IDX 7
 
 //zero chan            8
@@ -45,7 +45,7 @@
 #define THROTTLE2_5V_BUFF_IDX 12
 #define THROTTLE_5V_BUFF_IDX 13
 
-#define U_VOL_BUFF_IDX 14
+#define U_VOL_BUFF_IDX 6
 //zero chan            15
 
 //zero chan            16
@@ -128,11 +128,11 @@ static void adc01_init(void) {
 	adc_regular_channel_config(ADC0, 0, MOS_TEMP_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME);
 	adc_regular_channel_config(ADC0, 1, MOTOR_TEMP_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME);
 	adc_regular_channel_config(ADC0, 2, THROTTLE_CHAN, ADC_REGCHAN_SAMPLE_TIME);
-	adc_regular_channel_config(ADC0, 3, THROTTLE2_CHAN, ADC_REGCHAN_SAMPLE_TIME);
+	adc_regular_channel_config(ADC0, 3, U_VOL_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME);
 	adc_regular_channel_config(ADC0, 4, ZERO_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME); //insert zero vol
 	adc_regular_channel_config(ADC0, 5, ADC_CHANNEL_17, ADC_REGCHAN_SAMPLE_TIME); //mcu内部vref
 	adc_regular_channel_config(ADC0, 6, THROTTLE2_5V_CHAN, ADC_REGCHAN_SAMPLE_TIME);
-	adc_regular_channel_config(ADC0, 7, U_VOL_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME);
+	adc_regular_channel_config(ADC0, 7, THROTTLE2_CHAN, ADC_REGCHAN_SAMPLE_TIME);
 	adc_regular_channel_config(ADC0, 8, ZERO_ADC_CHAN, ADC_REGCHAN_SAMPLE_TIME); //insert zero vol
 
 	adc_tempsensor_vrefint_enable();

+ 1 - 2
Applications/bsp/gd32/board_mc105_v3.h

@@ -225,13 +225,12 @@
 
 #define PHASE_VOL_R (40*1000.0f)
 #define PHASE_VOL_R1 (1*1000.0f)
-#define PHASE_VOL_C1 (100e-9f) //100nF
+#define PHASE_VOL_C1 (470e-9f) //470nF
 #define PHASE_VOL_Gain  ((PHASE_VOL_R + PHASE_VOL_R1)/PHASE_VOL_R1)
 #define Phase_Vol_LPF_R  ((PHASE_VOL_R * PHASE_VOL_R1)/(PHASE_VOL_R + PHASE_VOL_R1))
 #define PHASE_VOL_LPF_BAND  (1/(2*3.14F*Phase_Vol_LPF_R*PHASE_VOL_C1))
 #define UVW_VOL_CEOF (ADC_REFERENCE_VOLTAGE*PHASE_VOL_Gain/ADC_FULL_MAX)
 
-
 /* 模拟5v电压采集 */
 #define DC5V_ADC_CHAN     ADC_CHANNEL_3 //adc012
 #define DC5V_ADC_GROUP 	GPIOA

+ 4 - 2
Applications/foc/commands.c

@@ -474,9 +474,11 @@ static void process_foc_command(foc_cmd_body_t *command) {
 			plot_type = (int)decode_u8((u8 *)command->data);
 		#if (CONFIG_ENABLE_IAB_REC==1)
 			if (plot_type == 6) {
-				mc_start_current_rec(true);
+				mc_start_current_rec(true, true);
+			}else if (plot_type == 11) {
+				mc_start_current_rec(false, true);
 			}else if (plot_type == 0) {
-				mc_start_current_rec(false);
+				mc_start_current_rec(false, false);
 			}
 		#endif
 			sys_debug("plot type %d\n", plot_type);

+ 3 - 0
Applications/foc/core/controller.c

@@ -251,6 +251,7 @@ bool mot_contrl_update(mot_contrl_t *ctrl) {
 	clark(foc->in.curr_abc[0], foc->in.curr_abc[1], foc->in.curr_abc[2], &foc->in.curr_ab);
 
 	foc_observer_update(foc->out.vol_albeta.a * TWO_BY_THREE, foc->out.vol_albeta.b * TWO_BY_THREE, foc->in.curr_ab.a, foc->in.curr_ab.b);
+
 	float enc_angle = motor_encoder_get_angle();
 	float enc_vel = motor_encoder_get_speed();
 	if (!foc_observer_diagnostic(enc_angle, enc_vel)){
@@ -281,6 +282,8 @@ bool mot_contrl_update(mot_contrl_t *ctrl) {
 
 	foc_update(foc);
 
+	park(foc, &ctrl->phase_v_ab, &ctrl->phase_v_dq);
+
 	ctrl->duty_raw = NORM2_f(foc->out.vol_dq.d, foc->out.vol_dq.q)/(foc->in.dc_vol * CONFIG_SVM_MODULATION * SQRT3_BY_2);
 	LowPass_Filter(ctrl->duty_filterd, ctrl->duty_raw, 0.01f);
 	float lowpass = foc->mot_vel_radusPers * FOC_CTRL_US * 2;

+ 1 - 0
Applications/foc/core/controller.h

@@ -130,6 +130,7 @@ typedef struct{
 	dq_t			target_idq;
 	dq_t            out_idq_filterd;
 	albt_t			phase_v_ab; //sampled
+	dq_t			phase_v_dq;
 	float 			out_current_vec;
 	u32				ebrk_ramp_time;
 	u32				torque_acc_time;

+ 6 - 0
Applications/foc/core/foc.c

@@ -91,6 +91,8 @@ void foc_update(foc_t *foc) {
 	foc->out.vol_dq.d = foc->in.target_vol_dq.d;
 	foc->out.vol_dq.q = foc->in.target_vol_dq.q;
 #ifdef CONFIG_Volvec_Delay_Comp
+	float sin_old = foc->sin;
+	float cos_old = foc->cos;
 	if (foc->mot_velocity_filterd >= CONFIG_Volvec_Delay_Comp_Start_Vel) {
 		float vol_dq_angle = foc->in.mot_angle + foc->mot_velocity_filterd / PI * 180.0f * (foc->ts * 0.8f);
 		norm_angle_deg(vol_dq_angle);
@@ -105,5 +107,9 @@ void foc_update(foc_t *foc) {
 	
 	pwm_update_duty(foc->out.duty[0], foc->out.duty[1], foc->out.duty[2]);
 	pwm_update_sample(foc->out.sample1, foc->out.sample2, foc->out.sample_phase);
+#ifdef CONFIG_Volvec_Delay_Comp
+	foc->sin = sin_old;
+	foc->cos = cos_old;
+#endif
 }
 

+ 1 - 1
Applications/foc/core/ladrc_observer.c

@@ -103,7 +103,7 @@ float ladrc_observer_update(float va, float vb, float ia, float ib) {
 	/* 补偿ladrc相位延时,LADRC等效截止频率为Wo/2pi的两个低通滤波器串联 */
 	angle = fast_atan2(observer.Vel_El, Wo) * 2.0f;
 	/* 电压滞后一个控制周期,需要通过当前的电角速度对计算的角度进行补偿 */
-	observer.angle_out = observer.angle_atan + (angle + 0/*observer.Vel_El * observer.ts*/);
+	observer.angle_out = observer.angle_atan + (angle + observer.Vel_El * observer.ts);
 	norm_angle_rad(observer.angle_out);
 
 	LowPass_Filter(observer.Vel_El_filter, observer.Vel_El, 0.01f); //需要再加一级低通滤波,给计算Wo和输出使用

+ 3 - 1
Applications/foc/foc_config.h

@@ -64,7 +64,9 @@
 #define CONFIG_CONTRL_FW_ENABLE 1
 #define CONFIG_CONTRL_FW_START_DUTY 0.9F
 
-#define CONFIG_ENABLE_IAB_REC 0   // for phase current debug
+#define CONFIG_ENABLE_IAB_REC 1   // for phase current/voltage debug
+
+#define CONFIG_MOT_IND_USE_PHASE_SAMPLE 1 //电机参数离线识别使用采集的相电压
 
 #ifdef CONFIG_SPEED_LADRC
 	#define CONFIG_LADRC_Wo  200.0F

+ 6 - 2
Applications/foc/motor/mot_params_ind.c

@@ -95,7 +95,11 @@ static void _rs_ind_timer_handler(shark_timer_t *t) {
 		break;
 	case 3: {
 		float dtc = ((float)CONFIG_HW_DeadTime/(float)FOC_PWM_period) * motor.controller.foc.in.dc_vol * 0.2f;
+#if CONFIG_MOT_IND_USE_PHASE_SAMPLE==0
 		float vd = rs_vd_now * TWO_BY_THREE - dtc;
+#else
+		float vd = motor.controller.phase_v_dq.d;
+#endif
 		float id = motor.controller.foc.out.curr_dq.d;
 		float rs = vd / (id + 0.0001f);
 		rs_est_value = LowPass_Filter(rs_est_value, rs, 0.2f);
@@ -220,10 +224,10 @@ bool mot_params_hj_sample_vi(float vd, float vq, float id, float iq) {
 	}
 	if ((n_samples >= 1) && (n_samples <= hj_samples)) {
 		if (n_ind_ld == L_TYPE_D) {
-			v_samples[n_samples - 1] = vd * TWO_BY_THREE;
+			v_samples[n_samples - 1] = vd;
 			i_samples[n_samples - 1] = id;
 		}else {
-			v_samples[n_samples - 1] = vq * TWO_BY_THREE;
+			v_samples[n_samples - 1] = vq;
 			i_samples[n_samples - 1] = iq;
 		}
 	}

+ 27 - 8
Applications/foc/motor/motor.c

@@ -1253,6 +1253,7 @@ measure_time_t g_meas_foc = {.exec_max_time = 25, .intval_max_time = 62,  .intva
 static s16 ia[CONFIG_IAB_REC_COUNT], ib[CONFIG_IAB_REC_COUNT];
 static int iab_w_count = 0, iab_r_count = 0;
 static bool b_iab_rec = false;
+static bool b_vab_rec = false;
 extern void can_plot2(s16 v1, s16 v2);
 #endif
 /*ADC 电流采集中断,调用FOC的核心处理函数*/
@@ -1272,14 +1273,20 @@ void ADC_IRQHandler(void) {
 		ia[iab_w_count] = (s16)motor.controller.foc.in.curr_abc[0];
 		ib[iab_w_count] = (s16)motor.controller.foc.in.curr_abc[1];
 		iab_w_count ++;
+	}else if (b_vab_rec && (iab_w_count < CONFIG_IAB_REC_COUNT)) {
+		ia[iab_w_count] = (s16)motor.controller.phase_v_ab.a;
+		ib[iab_w_count] = (s16)motor.controller.foc.out.vol_albeta.a*TWO_BY_THREE;
+		iab_w_count ++;
 	}
 #endif
 	motor_vbus_crit_check((s16)sample_vbus_raw()); //need fast detect vbus very low, to stop the motor
 	float vd, vq;
 	if (motor.b_ind_start) {
 		mot_params_high_freq_inject();
-		vd = motor.controller.foc.out.vol_dq.d;
-		vq = motor.controller.foc.out.vol_dq.q;
+#if CONFIG_MOT_IND_USE_PHASE_SAMPLE==0
+		vd = motor.controller.foc.out.vol_dq.d * TWO_BY_THREE;
+		vq = motor.controller.foc.out.vol_dq.q * TWO_BY_THREE;
+#endif
 	}
 	if (!mot_contrl_update(&motor.controller)) {/* FOC 角度错误,立即停机 */
 		if (mot_contrl_is_start(&motor.controller)) {
@@ -1309,6 +1316,10 @@ void ADC_IRQHandler(void) {
 	if (motor.b_ind_start) {
 		float id = motor.controller.foc.out.curr_dq.d;
 		float iq = motor.controller.foc.out.curr_dq.q;
+#if CONFIG_MOT_IND_USE_PHASE_SAMPLE==1
+		vd = motor.controller.phase_v_dq.d;
+		vq = motor.controller.phase_v_dq.q;
+#endif
 		mot_params_hj_sample_vi(vd, vq, id, iq);
 	}
 	TIME_MEATURE_END();
@@ -1316,7 +1327,7 @@ void ADC_IRQHandler(void) {
 
 #if (CONFIG_ENABLE_IAB_REC==1)
 static void _iab_plot_timer_handler(shark_timer_t *t) {
-	if (!b_iab_rec) {
+	if (!b_iab_rec && !b_vab_rec) {
 		return;
 	}
 	if (iab_r_count < iab_w_count) {
@@ -1326,18 +1337,26 @@ static void _iab_plot_timer_handler(shark_timer_t *t) {
 	}
 }
 static shark_timer_t _iab_plot_timer = TIMER_INIT(_iab_plot_timer, _iab_plot_timer_handler);
-void mc_start_current_rec(bool rec) {
-	if (b_iab_rec == rec) {
-		return;
-	}
+void mc_start_current_rec(bool is_i, bool rec) {
+
 	if (!rec) {
 		b_iab_rec = false;
+		b_vab_rec = false;
 		shark_timer_cancel(&_iab_plot_timer);
 		return;
 	}
+
+	if (b_iab_rec == true || b_vab_rec == true) {
+		return;
+	}
+
 	iab_w_count = 0;
 	iab_r_count = 0;
-	b_iab_rec = true;
+	if (is_i) {
+		b_iab_rec = true;
+	}else {
+		b_vab_rec = true;
+	}
 	shark_timer_post(&_iab_plot_timer, 100);
 }
 #endif

+ 1 - 1
Applications/foc/motor/motor.h

@@ -128,7 +128,7 @@ s16 mc_get_ebrk_torque(void);
 u16 mc_get_ebrk_time(void);
 bool mc_critical_err_is_set(u8 err);
 bool mc_hwbrk_can_shutpower(void);
-void mc_start_current_rec(bool rec);
+void mc_start_current_rec(bool is_i, bool rec);
 bool mc_ind_motor_start(bool start);
 void mc_enable_brkshutpower(u8 shut);
 void mc_enable_tcs(bool enable);