Quellcode durchsuchen

加入hfi

Signed-off-by: kevin <huhui@sharkgulf.com>
kevin vor 2 Jahren
Ursprung
Commit
a83cfc5b70

+ 7 - 0
Applications/app/app.c

@@ -163,15 +163,22 @@ static u32 app_report_task(void *p) {
 }
 int plot_type = 0;
 static void plot_smo_angle(void) {
+	can_plot1((s16)foc()->in.mot_angle);
+	#if 0
 	u32 mask = cpu_enter_critical();
 	float smo_angle = foc_observer_sensorless_angle();
 	float mot_angle = foc()->in.mot_angle;
+	if (mot_contrl()->if_ctl.b_ena) {
+		mot_angle += 90;
+		norm_angle_deg(mot_angle);
+	}
 	cpu_exit_critical(mask);
 	float delta = smo_angle - mot_angle;
 	float s, c;
 	arm_sin_cos(delta, &s, &c);
 	delta = fast_atan2(s, c)/PI*180.0f;
 	can_plot3(mot_angle, smo_angle, delta);
+	#endif
 }
 
 #ifdef CONFIG_USE_ENCODER_HALL

+ 10 - 8
Applications/bsp/at32/adc.c

@@ -17,7 +17,7 @@
 
 #define REG_CHAN_NUM (ADC1_NUM + ADC2_NUM)
 u16 adc_buffer[REG_CHAN_NUM];
-
+static bool adc_inited = false;
 static void analog_gpio_init(gpio_type *gpiox, u32 pin) {
 	gpio_init_type gpio_init_struct = {0};
 	/* gpio configuration */
@@ -126,7 +126,10 @@ static void adc01_init(void){
 
 	adc_reset(ADC1);
 	adc_reset(ADC2);
-	
+
+	/* select adc mster-slave mode */
+	adc_combine_mode_select(ADC_ORDINARY_SMLT_PREEMPT_SMLT_MODE);
+
 	adc_base_struct.sequence_mode = TRUE;
 	adc_base_struct.repeat_mode = TRUE;
 	adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
@@ -139,6 +142,7 @@ static void adc01_init(void){
 	adc_ordinary_channel_set(ADC1, W_VOL_ADC_CHAN, 2, ADC_REGCHAN_SAMPLE_TIME);
 	adc_ordinary_channel_set(ADC1, MOS_TEMP_ADC_CHAN, 3, ADC_REGCHAN_SAMPLE_TIME);
 	adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
+	adc_dma_mode_enable(ADC1, TRUE);
 
 	adc_ordinary_channel_set(ADC2, V_VOL_ADC_CHAN, 1, ADC_REGCHAN_SAMPLE_TIME);
 	adc_ordinary_channel_set(ADC2, VBUS_I_CHAN, 2, ADC_REGCHAN_SAMPLE_TIME);
@@ -160,14 +164,8 @@ static void adc01_init(void){
 	/* adc prempt trigger source */
 	adc_preempt_conversion_trigger_set(ADC2, ADC12_PREEMPT_TRIG_TMR1CH4, TRUE);
 
-	/* select adc mster-slave mode */
-	adc_combine_mode_select(ADC_ORDINARY_SMLT_PREEMPT_SMLT_MODE);
-
 	//adc_tempersensor_vintrv_enable(TRUE);
 
-	adc_dma_mode_enable(ADC1, TRUE);
-	//adc_dma_mode_enable(ADC2, TRUE);
-
 	/* ADC enable and calibration */
 	adc_enable(ADC1, TRUE);
 	adc_calibration_init(ADC1);
@@ -231,9 +229,13 @@ static void adc_gpio_init(void) {
 }
 
 void adc_init(bool mot_ind) {
+	if (adc_inited) {
+		return;
+	}
 	adc_gpio_init();
 	adc01_dma_init();
 	adc01_init();
+	adc_inited = true;
 }
 
 void adc_set_vref_calc(float v) {

+ 5 - 5
Applications/bsp/at32/adc.h

@@ -17,7 +17,7 @@ inserted ADC 由timer0 ch3触发,
 #define IL_OFFSET   20
 
 #define ADC_REGCHAN_SAMPLE_TIME ADC_SAMPLETIME_71_5
-#define ADC_INSERT_SAMPLE_TIME ADC_SAMPLETIME_1_5
+#define ADC_INSERT_SAMPLE_TIME ADC_SAMPLETIME_7_5
 #define ADC_TRIGGER_PHASE ADC12_PREEMPT_TRIG_TMR1CH4
 
 static void __inline adc_phase_current_read(u8 phases, s32 *v1, s32 *v2) {
@@ -40,13 +40,13 @@ static void __inline adc_current_sample_config(u8 phases) {
 }
 
 static void __inline adc_disable_ext_trigger(void) {   
-	ADC1->ctrl2_bit.pcten = FALSE;
-	ADC2->ctrl2_bit.pcten = FALSE;
+	//ADC1->ctrl2_bit.pcten = FALSE;
+	//ADC2->ctrl2_bit.pcten = FALSE;
 }
 
 static void __inline adc_enable_ext_trigger(void) {	
-	ADC1->ctrl2_bit.pcten = TRUE;
-	ADC2->ctrl2_bit.pcten = TRUE;
+	//ADC1->ctrl2_bit.pcten = TRUE;
+	//ADC2->ctrl2_bit.pcten = TRUE;
 }
 
 static __inline__ void adc_clear_irq_flags(void) {

+ 5 - 14
Applications/bsp/at32/board_at32_mc.h

@@ -26,8 +26,8 @@
 #define SCHED_TIMER_IRQ TMR5_GLOBAL_IRQn
 #define SCHED_TIMER_IRQHandler TMR5_GLOBAL_IRQHandler
 
-#define CONFIG_THREE_SHUNT 
-
+//#define CONFIG_THREE_SHUNT 
+#define CONFIG_MAX_MODULATION 0.95F
 #define PWM_DEAD_TIME_NS 300u
 #define PWM_TOFF_DELAY_MAX 240u
 #define PWM_TON_DELAY_MIN 200u
@@ -88,9 +88,6 @@
 
 #define CONFIG_CURRENT_SENSOR_CEOF (ADC_REFERENCE_VOLTAGE/ADC_FULL_MAX/16.5F/0.002F) ///(3.3/4095/16.5/0.002)
 
-/* 高边电流传感器采样 */
-#define HIGH_SIDE_CURRENT_SENSOR
-
 #define U_PHASE_I_CHAN				ADC_CHANNEL_0
 #define V_PHASE_I_CHAN  			ADC_CHANNEL_1
 #define W_PHASE_I_CHAN  			ADC_CHANNEL_2
@@ -112,12 +109,6 @@
 
 #define ADC_TO_CURR_ceof  			(CONFIG_CURRENT_SENSOR_CEOF)
 
-#define CONFIG_PWM_UV_SWAP 		   	1
-
-//#define CONFIG_HW_MUTISAMPLE ADC_OVERSAMPLING_RATIO_MUL8
-//#define CONFIG_HW_MUTISAMPLE_SHIFT ADC_OVERSAMPLING_SHIFT_3B
-//#define CONFIG_SW_MUTISAMPLE 1
-
 /* 母线电压采集 */
 #define VBUS_V_CHAN 				ADC_CHANNEL_7  //adc012
 #define VBUS_V_ADC_GROUP 			GPIOA
@@ -173,9 +164,9 @@
 #define W_VOL_ADC_RCU 				CRM_GPIOA_PERIPH_CLOCK
 #define W_VOL_ADC_MODE 				GPIO_MODE_ANALOG
 #define UVW_VOL_CEOF 				(ADC_REFERENCE_VOLTAGE*((37.4F + 3.9F)/3.9F)/ADC_FULL_MAX)
-#define PHASE_VOL_R (40*1000.0f)
-#define PHASE_VOL_R1 (1*1000.0f)
-#define PHASE_VOL_C1 (470e-9f) //470nF
+#define PHASE_VOL_R (37.4f*1000.0f)
+#define PHASE_VOL_R1 (3.9f*1000.0f)
+#define PHASE_VOL_C1 (10e-9f) //10nF
 #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))

+ 1 - 1
Applications/bsp/at32/bsp.h

@@ -12,7 +12,7 @@
 #define ADC_CLOCK_MHz (30u)
 #define NS_PER_TCLK (5u) /* (1/200000000 * 1000000000) */
 #define NS_2_TCLK(ns) (((ns)/NS_PER_TCLK) + 1u) //ns תΪpwmʹ�õ��Ǹ�TIM��clk count
-#define FOC_PWM_FS (16000u)
+#define FOC_PWM_FS (12000u)
 #define FOC_PWM_period (TIM_CLOCK/FOC_PWM_FS)
 #define FOC_PWM_Half_Period (FOC_PWM_period/2)
 

+ 2 - 2
Applications/bsp/at32/pwm.c

@@ -110,7 +110,7 @@ static void _init_pwm_timer(bool enable_brk) {
 	tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
 	tmr_output_struct.oc_idle_state = FALSE;
 	tmr_output_struct.occ_output_state = TRUE;
-	tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
+	tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_LOW;
 	tmr_output_struct.occ_idle_state = FALSE;
 	
 	/* channel 1, 2, 3 */
@@ -133,7 +133,7 @@ static void _init_pwm_timer(bool enable_brk) {
 	tmr_brkdt_config_struct.auto_output_enable = FALSE;
 	tmr_brkdt_config_struct.deadtime = _dead_time(NS_2_TCLK(PWM_DEAD_TIME_NS));
 	tmr_brkdt_config_struct.fcsodis_state = TRUE;
-	tmr_brkdt_config_struct.fcsoen_state = FALSE;
+	tmr_brkdt_config_struct.fcsoen_state = TRUE;
 	tmr_brkdt_config_struct.brk_polarity = TMR_BRK_INPUT_ACTIVE_LOW;
 	tmr_brkdt_config_struct.wp_level = TMR_WP_OFF;
 	tmr_brkdt_config(MOS_PWM_TIMER, &tmr_brkdt_config_struct);

+ 1 - 1
Applications/bsp/at32/uart.h

@@ -11,7 +11,7 @@
 #define CH_ESC_END						0x06
 #define CH_ESC_ESC						0x07
 
-#define SHARK_UART_TX_MEM_SIZE			(1024)
+#define SHARK_UART_TX_MEM_SIZE			(512)
 #define SHARK_UART_RX_MEM_SIZE			(256+128)
 #define RX_FRAME_MAX_LEN 260
 

+ 163 - 6
Applications/foc/core/controller.c

@@ -55,6 +55,7 @@ bool mot_contrl_enable(mot_contrl_t *ctrl, bool start) {
 		mot_contrl_ulimit(ctrl);
 		mot_contrl_rtlimit(ctrl);
 	}
+	mot_contrl_enable_hfi(ctrl, start);
 	ctrl->b_ebrk_running = false;
 	ctrl->b_AutoHold = false;
 	ctrl->b_cruiseEna = false;
@@ -117,9 +118,150 @@ float mot_contrl_IF_update(mot_contrl_t *ctrl) {
 	i_f->curr_angle += i_f->curr_vel * ctrl->foc.ts; //速度积分获取电角度
 	norm_angle_rad(i_f->curr_angle);
 	ctrl->if_ctl.angle_deg = pi_2_degree(ctrl->if_ctl.curr_angle);
+	i_f->curr_vel_rpm = i_f->curr_vel/M_PI*30.0f/mc_conf()->m.poles;
 	return ctrl->if_ctl.angle_deg;
 }
 
+#define HFI_DEBUG_ON 0
+
+#if 0
+void mot_contrl_enable_hfi(mot_contrl_t *ctrl, bool enable) {
+	hfi_t *hfi = &ctrl->hfi;
+	if (enable) {
+		hfi->inv_ld_lq = 1.0f/mc_conf()->m.lq - 1.0f/mc_conf()->m.ld;
+		hfi->int_gain2 = 3.0f;
+		hfi->int_gain = 1200.0f;
+		hfi->max_vel = 2000;
+		hfi->vel_integrator = -ctrl->foc.in.mot_velocity;
+		hfi->angle_deg = ctrl->foc.in.mot_angle;
+		hfi->angle_rad = degree_2_pi(hfi->angle_deg);
+		hfi->v_inj = 20.0f;
+	}
+	ctrl->b_hfi = enable;
+}
+
+static void mot_contrl_hfi_alpha_beta(mot_contrl_t *ctrl) {
+	hfi_t *hfi = &ctrl->hfi;
+	foc_t *foc = &ctrl->foc;
+	if (hfi->b_sample) {
+		float sample_now = foc->cos * ctrl->foc.in.curr_ab.b - foc->sin * ctrl->foc.in.curr_ab.a;
+		LowPass_Filter(hfi->sample_now, sample_now, 1.0f);
+		float di = hfi->sample_prev - hfi->sample_now;
+		float err = di / ctrl->foc.ts / (hfi->v_inj * hfi->inv_ld_lq);
+		hfi->vel_integrator += err * hfi->int_gain2;
+		hfi->vel_integrator = fclamp(hfi->vel_integrator, -hfi->max_vel, hfi->max_vel);
+		hfi->angle_rad -= 2.0f * ctrl->foc.ts * (err * hfi->int_gain + hfi->vel_integrator);
+		norm_angle_rad(hfi->angle_rad);
+		hfi->angle_deg = pi_2_degree(hfi->angle_rad);
+		foc->in.mot_angle = hfi->angle_deg;
+		arm_sin_cos(foc->in.mot_angle, &foc->sin, &foc->cos);
+		hfi->v_alpha_inj = -hfi->v_inj * foc->cos;
+		hfi->v_beta_inj = -hfi->v_inj * foc->sin;
+	}else {
+		float sample_now = foc->cos * ctrl->foc.in.curr_ab.b - foc->sin * ctrl->foc.in.curr_ab.a;
+		LowPass_Filter(hfi->sample_prev, sample_now, 1.0f);
+		hfi->v_alpha_inj = hfi->v_inj * foc->cos;
+		hfi->v_beta_inj = hfi->v_inj * foc->sin;
+	}
+	hfi->b_sample = !hfi->b_sample;
+}
+
+#else
+#define HFI_PLL_BAND 150.0F
+#define HFI_IPD_V 6.0F
+#define HFI_RUNNING_V 5.0F
+#define HFI_SAMPLE_NUM 8000
+void mot_contrl_enable_hfi(mot_contrl_t *ctrl, bool enable) {
+	hfi_t *hfi = &ctrl->hfi;
+	if (enable) {
+		PI_Controller_Reset(&hfi->pi, 0);
+		hfi->angle_deg = 0;
+		hfi->rad_integrator = degree_2_pi(hfi->angle_deg);
+		hfi->v_inj = 0;
+		hfi->pi.ts = (1.0f/(float)CONFIG_IDQ_CTRL_TS);
+		hfi->pi.kp = 2.0f * HFI_PLL_BAND;
+		hfi->pi.ki = SQ(HFI_PLL_BAND);
+		hfi->pi.kd = 0;
+		hfi->pi.max = 2000.0f/30*M_PI*mc_conf()->m.poles;
+		hfi->pi.min = -hfi->pi.max;
+		hfi->sign = -1;
+		hfi->rpm_vel = 0;
+		hfi->elec_vel = hfi->rpm_vel / 30.0f * PI * mc_conf()->m.poles;
+		hfi->pi.ui = hfi->elec_vel;
+		hfi->ipd = true;
+		hfi->hfi_ready = false;
+	}
+	hfi->n_samples = 0;
+	hfi->b_ena = enable;
+}
+
+static __INLINE void hfi_pll_run(hfi_t *hfi, float alpha, float beta) {
+	float mag = NORM2_f(alpha, beta) + 1e-10f;
+	alpha /= mag;
+	beta  /= mag;
+	float sin, cos;
+	arm_sin_cos(hfi->angle_deg, &sin, &cos);
+	float err = alpha * sin - beta * cos;
+	float vel_elec = PI_Controller_Run(&hfi->pi, err);
+	LowPass_Filter(hfi->elec_vel, vel_elec, 1.0f);
+	hfi->rad_integrator += hfi->elec_vel * hfi->pi.ts;
+	norm_angle_rad(hfi->rad_integrator);
+	hfi->angle_deg = pi_2_degree(hfi->rad_integrator);
+}
+
+static void mot_contrl_hfi_alpha_beta(mot_contrl_t *ctrl) {
+	hfi_t *hfi = &ctrl->hfi;
+	foc_t *foc = &ctrl->foc;
+	float sign = hfi->sign;
+	
+	if (hfi->sign > 0) {
+		hfi->sign = -1;
+	}else {
+		hfi->sign = 1;
+	}
+
+	float hi_alpha = -(ctrl->foc.in.curr_ab.a - hfi->sample_prev.a) * 0.5f * sign;
+	float hi_beta = -(ctrl->foc.in.curr_ab.b - hfi->sample_prev.b) * 0.5f * sign;
+
+	float alpha = (ctrl->foc.in.curr_ab.a + hfi->sample_prev.a) * 0.5f;
+	float beta = (ctrl->foc.in.curr_ab.b + hfi->sample_prev.b) * 0.5f;
+
+	hfi->hi_alpha_beta.a = hi_alpha;
+	hfi->hi_alpha_beta.b = hi_beta;
+
+
+	hfi_pll_run(hfi, hi_alpha, hi_beta);
+	hfi->rpm_vel = LowPass_Filter(hfi->rpm_vel, (hfi->elec_vel/M_PI*30/mc_conf()->m.poles) ,0.1f);
+
+	foc->in.mot_angle = hfi->angle_deg;
+	foc->in.mot_velocity = hfi->rpm_vel;
+	
+	if (!hfi->ipd) {
+		float v_inj = hfi->v_inj;
+		step_towards(&v_inj, HFI_RUNNING_V, 0.1f);
+		hfi->v_inj = v_inj;
+	}else {
+		float v_inj = hfi->v_inj;
+		step_towards(&v_inj, HFI_IPD_V, 0.5f);
+		hfi->v_inj = v_inj;
+		if (hfi->n_samples < HFI_SAMPLE_NUM) {
+			hfi->n_samples++;
+		}
+		if (hfi->n_samples >= HFI_SAMPLE_NUM) {
+			hfi->ipd = false;
+			hfi->hfi_ready = true;
+		}
+	}
+	hfi->v_d_inj = hfi->v_inj * hfi->sign;// + 1.0f;
+	hfi->v_q_inj = 0;
+	hfi->sample_prev.a = ctrl->foc.in.curr_ab.a;
+	hfi->sample_prev.b = ctrl->foc.in.curr_ab.b;
+
+	ctrl->foc.in.curr_ab.a = alpha;
+	ctrl->foc.in.curr_ab.b = beta;
+}
+#endif
+
 bool mot_contrl_request_mode(mot_contrl_t *ctrl, u8 mode) {
 	if (mode > CTRL_MODE_EBRAKE) {
 		mot_contrl_set_error(ctrl, FOC_Param_Err);
@@ -293,6 +435,11 @@ bool mot_contrl_update(mot_contrl_t *ctrl) {
 
 	float enc_angle = motor_encoder_get_angle();
 	float enc_vel = motor_encoder_get_speed();
+	if (ctrl->if_ctl.b_ena) {
+		enc_angle = mot_contrl_IF_update(ctrl);
+		enc_vel = ctrl->if_ctl.curr_vel_rpm;
+		mot_contrl_set_current(ctrl, ctrl->if_ctl.iq_set);
+	}
 	if (!foc_observer_diagnostic(enc_angle, enc_vel)){
 		/* detect encoder angle error, do something here */
 		if (!foc_observer_sensorless_stable()) {
@@ -303,10 +450,7 @@ bool mot_contrl_update(mot_contrl_t *ctrl) {
 		enc_vel = foc_observer_sensorless_speed();
 	}
 
-	if (ctrl->if_ctl.b_ena) {
-		foc->in.mot_angle = mot_contrl_IF_update(ctrl);
-		mot_contrl_set_current(ctrl, ctrl->if_ctl.iq_set);
-	}else if (!ctrl->b_mtpa_calibrate && (ctrl->force_angle != INVALID_ANGLE)) {
+	if (!ctrl->b_mtpa_calibrate && (ctrl->force_angle != INVALID_ANGLE)) {
 		foc->in.mot_angle = ctrl->force_angle;
 	}else {
 		foc->in.mot_angle = enc_angle;
@@ -322,6 +466,14 @@ bool mot_contrl_update(mot_contrl_t *ctrl) {
 		foc->in.target_vol_dq.d = line_ramp_get_interp(&ctrl->ramp_target_vd);
 		foc->in.target_vol_dq.q = line_ramp_get_interp(&ctrl->ramp_target_vq);
 	}
+	if (ctrl->hfi.b_ena) {
+		mot_contrl_hfi_alpha_beta(ctrl);
+		foc->in.v_dq_inj.d = ctrl->hfi.v_d_inj;
+		foc->in.v_dq_inj.q = ctrl->hfi.v_q_inj;
+	}else {
+		foc->in.v_dq_inj.d = 0;
+		foc->in.v_dq_inj.q = 0;
+	}
 
 	foc_update(foc);
 
@@ -577,6 +729,11 @@ float mot_contrl_get_speed(mot_contrl_t *ctrl) {
 	float speed = ctrl->foc.in.mot_velocity;
 	if (!ctrl->b_start || foc_observer_is_encoder()) {
 		speed = motor_encoder_get_speed();
+		if (ctrl->if_ctl.b_ena) {
+			speed = ctrl->if_ctl.curr_vel_rpm;
+		}else if (ctrl->hfi.b_ena) {
+			speed = ctrl->hfi.rpm_vel;
+		}
 	}else {
 		if (foc_observer_sensorless_stable()) {
 			speed = foc_observer_sensorless_speed();
@@ -894,8 +1051,8 @@ void mot_contrl_calc_current(mot_contrl_t *ctrl) {
 		iDC x vDC = 3/2(iq x vq + id x vd);
 	*/
 	float m_pow = (vd * id + vq * iq);
-	float pf_angle = fast_atan2(id, iq) - fast_atan2(vd, vq);
-	m_pow = m_pow * arm_cos_f32(pf_angle);
+	//float pf_angle = fast_atan2(id, iq) - fast_atan2(vd, vq);
+	//m_pow = m_pow * arm_cos_f32(pf_angle);
 	float raw_idc = 0.0f;
 	float v_dc = get_vbus_float();
 	if (v_dc != 0.0f) {

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

@@ -88,6 +88,7 @@ typedef struct {
 	float max_vel; //rpm
 	float iq_set;
 	float curr_vel;
+	float curr_vel_rpm;
 	float curr_angle;
 	float angle_deg;
 	float b_ena;
@@ -125,6 +126,45 @@ typedef struct {
 	float torque;
 }prot_limit;
 
+#if 0
+typedef struct {
+	bool b_ena;
+	bool b_sample;
+	s16  v_inj;
+	float v_alpha_inj;
+	float v_beta_inj;
+	float sample_prev;
+	float sample_now;
+	float vel_integrator;
+	float angle_rad;
+	float angle_deg;
+	float elec_vel;
+	float max_vel;
+	float int_gain2;
+	float int_gain;
+	float inv_ld_lq;
+}hfi_t;
+#else
+typedef struct {
+	bool b_ena;
+	float sign;
+	bool ipd; //初始位置检测
+	bool hfi_ready;
+	float  v_inj;
+	int  n_samples;
+	float v_d_inj;
+	float v_q_inj;
+	albt_t hi_alpha_beta;
+	albt_t sample_prev;
+	float rad_integrator;
+	float angle_deg;
+	float elec_vel;
+	float rpm_vel;
+	PI_Controller pi;
+}hfi_t;
+#endif
+
+
 typedef struct{
 	bool 			b_start;
 	bool			b_ebrk_running;
@@ -179,6 +219,7 @@ typedef struct{
 	float 			phase_c_max;
 	u32 			phase_unbalance_cnt;
 	IF_t			if_ctl;
+	hfi_t           hfi;
 }mot_contrl_t;
 
 void mot_contrl_init(mot_contrl_t *ctrl);
@@ -216,6 +257,7 @@ void mot_contrl_set_torque_limit_rttime(mot_contrl_t *ctrl, u32 time);
 void mot_contrl_set_vel_limit_rttime(mot_contrl_t *ctrl, u32 time);
 bool mot_contrl_set_force_torque(mot_contrl_t *ctrl, float torque);
 void mot_contrl_IF_start(mot_contrl_t *ctrl, bool start, float accl, float max_vel, float iq_set);
+void mot_contrl_enable_hfi(mot_contrl_t *ctrl, bool enable);
 
 static __INLINE bool mot_contrl_start(mot_contrl_t *ctrl, u8 mode) {
 	mot_contrl_enable(ctrl, true);
@@ -317,5 +359,9 @@ static __INLINE void mot_ctrl_set_ind_freq(mot_contrl_t *ctrl, float freq) {
 	ctrl->mot_param_ind_freq = freq;
 }
 
+static __INLINE bool mot_contrl_hfi_is_ipd(mot_contrl_t *ctrl) {
+	return ctrl->hfi.ipd;
+}
+
 #endif /* _CONTROLLER_H__ */
 

+ 5 - 2
Applications/foc/core/foc.c

@@ -88,8 +88,11 @@ void foc_update(foc_t *foc) {
 		foc->in.target_vol_dq.q = fclamp(foc->in.target_vol_dq.q, -max_vq, max_vq);
 	}
 
-	foc->out.vol_dq.d = foc->in.target_vol_dq.d;
-	foc->out.vol_dq.q = foc->in.target_vol_dq.q;
+	foc->out.vol_dq.d = foc->in.target_vol_dq.d + foc->in.v_dq_inj.d;
+	foc->out.vol_dq.q = foc->in.target_vol_dq.q + foc->in.v_dq_inj.q;
+	if (foc->in.v_dq_inj.d != 0 || foc->in.v_dq_inj.q  != 0) {
+		saturate_vector_2d(&foc->out.vol_dq.d, &foc->out.vol_dq.q, max_Vdc * SQRT3_BY_2);
+	}
 #ifdef CONFIG_Volvec_Delay_Comp
 	float sin_old = foc->sin;
 	float cos_old = foc->cos;

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

@@ -17,6 +17,7 @@ typedef struct {
 typedef struct {
 	float 	curr_abc[3];
 	albt_t  curr_ab;
+	dq_t  	v_dq_inj;
 	float   vol_abc[3]; //相对地电压
 	float   mot_velocity;   //from hall or encoder
 	float 	mot_angle; //from hall or encoder

+ 6 - 2
Applications/foc/foc_config.h

@@ -4,7 +4,11 @@
 #include "bsp/bsp.h"
 
 #define CONFIG_ACC_MIN_VOL 30
-#define CONFIG_SVM_MODULATION       1.0f
+#ifdef CONFIG_MAX_MODULATION
+#define CONFIG_SVM_MODULATION     CONFIG_MAX_MODULATION
+#else
+#define CONFIG_SVM_MODULATION     1.0f
+#endif
 #define CONFIG_MIN_CRUISE_RPM 	  1000   /* 能启动定速巡航的最小速度 */
 #define CONFIG_CRUISE_EXIT_RPM    700    /* 自动推出定速巡航的最小速度*/
 #define CONFIG_MIN_RPM_FOR_EBRAKE 800 //进入电流回收的最小转速
@@ -66,7 +70,7 @@
 
 #define CONFIG_ENABLE_IAB_REC 1   // for phase current/voltage debug
 
-#ifdef MC100_HW_V1
+#if defined(MC100_HW_V1) || defined(AT32_MC_DEMO)
 #define CONFIG_MOT_IND_USE_PHASE_SAMPLE 0 //电机参数离线识别使用采集的相电压
 #else
 #define CONFIG_MOT_IND_USE_PHASE_SAMPLE 1

+ 5 - 0
Applications/foc/motor/current_2_3_shut.c

@@ -109,9 +109,14 @@ bool phase_current_offset(void) {
 		}
 	}else {
 		if (cs->c_phases == PHASE_AB) {
+#ifdef CONFIG_THREE_SHUNT
 			cs->c_phases = PHASE_BC;
 			phase_current_init();
 			adc_current_sample_config(cs->c_phases);
+#else
+			cs->adc_offset_c = cs->adc_offset_a;
+			cs->is_calibrating_offset = false;
+#endif
 		}else {
 			cs->is_calibrating_offset = false;
 		}

+ 10 - 3
Applications/foc/motor/motor.c

@@ -1356,11 +1356,11 @@ void ADC_IRQHandler(void) {
 
 #if (CONFIG_ENABLE_IAB_REC==1)
 	if (b_iab_rec && (iab_w_count < CONFIG_IAB_REC_COUNT)) {
-		ia[iab_w_count] = (s16)motor.controller.foc.in.curr_abc[2];
-		ib[iab_w_count] = (s16)motor.controller.foc.in.curr_abc[1];
+		ia[iab_w_count] = (s16)(motor.controller.foc.in.curr_abc[0] * 100.0f);
+		ib[iab_w_count] = (s16)(motor.controller.foc.in.curr_abc[1] * 100.0f);
 		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;
+		ia[iab_w_count] = (s16)(motor.controller.phase_v_ab.a * 100.0f);
 		ib[iab_w_count] = (s16)motor.controller.foc.out.vol_albeta.a*TWO_BY_THREE;
 		iab_w_count ++;
 	}
@@ -1525,6 +1525,10 @@ static void mc_process_epm_move(void) {
 	if (!motor.b_epm || (motor.epm_dir == EPM_Dir_None)){
 		return;
 	}
+	if (mot_contrl_hfi_is_ipd(mot_contrl())) {
+		return;
+	}
+
 	float target_vel = mc_conf()->c.max_epm_rpm;
 	float target_trq = mc_conf()->c.max_epm_torque;
 	if (motor.epm_dir == EPM_Dir_Back) {
@@ -1696,6 +1700,9 @@ static void mc_process_throttle_torque(float vol) {
 	}
 
 	if (motor.controller.mode_running == CTRL_MODE_TRQ) {
+		if (mot_contrl_hfi_is_ipd(mot_contrl())) {
+			return;
+		}
 		throttle_set_torque(&motor.controller, torque);
 	}else if (motor.controller.mode_running == CTRL_MODE_SPD) {
 		if (!mc_is_cruise_enabled()) {

+ 1 - 1
Project/AT32_MC.uvprojx

@@ -312,7 +312,7 @@
           </ArmAdsMisc>
           <Cads>
             <interw>1</interw>
-            <Optim>2</Optim>
+            <Optim>4</Optim>
             <oTime>1</oTime>
             <SplitLS>0</SplitLS>
             <OneElfS>1</OneElfS>