|
@@ -18,11 +18,12 @@
|
|
|
#include "board_config.h"
|
|
#include "board_config.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
#define _constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
|
|
#define _constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
|
|
|
// 测试变量
|
|
// 测试变量
|
|
|
int32_t ia_test,ib_test,ic_test;
|
|
int32_t ia_test,ib_test,ic_test;
|
|
|
|
|
|
|
|
-float Ua,Ualpha,Ub,Ubeta, Uc, dc_a,dc_b,dc_c,sin_theta;
|
|
|
|
|
|
|
+float Ua,Ualpha,Ub,Ubeta, Uc, dc_a,dc_b,dc_c;
|
|
|
//float err;
|
|
//float err;
|
|
|
|
|
|
|
|
// 电流和电压变量
|
|
// 电流和电压变量
|
|
@@ -107,6 +108,16 @@ static void get_offset(uint32_t *a_offset, uint32_t *b_offset, uint32_t* c_offse
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @brief 开环角度更新
|
|
|
|
|
+ */
|
|
|
|
|
+static void Angle_OpenLoop_Update(float step)
|
|
|
|
|
+{
|
|
|
|
|
+ if(get_motor()->direction == MOTOR_CW)
|
|
|
|
|
+ get_motor()->eleangle += step;
|
|
|
|
|
+ else
|
|
|
|
|
+ get_motor()->eleangle -= step;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
static void FOC_parm_input(void)
|
|
static void FOC_parm_input(void)
|
|
|
{
|
|
{
|
|
@@ -121,10 +132,10 @@ static void FOC_parm_input(void)
|
|
|
get_foc_input()->ib = Ib;
|
|
get_foc_input()->ib = Ib;
|
|
|
get_foc_input()->ic = Ic;
|
|
get_foc_input()->ic = Ic;
|
|
|
}
|
|
}
|
|
|
-static void FOC_parm_output(void)
|
|
|
|
|
-{
|
|
|
|
|
- EKF_Hz = get_foc_ouput()->EKF[2]/(2.0f*PI) ;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+//static void FOC_parm_output(void)
|
|
|
|
|
+//{
|
|
|
|
|
+// EKF_Hz = get_foc_ouput()->EKF[2]/(2.0f*PI) ;
|
|
|
|
|
+//}
|
|
|
|
|
|
|
|
|
|
|
|
|
static void uvw_current_and_vbus_get(float* vbus, double* iu, double* iv, double* iw)
|
|
static void uvw_current_and_vbus_get(float* vbus, double* iu, double* iv, double* iw)
|
|
@@ -137,6 +148,123 @@ static void uvw_current_and_vbus_get(float* vbus, double* iu, double* iv, double
|
|
|
Ib_test = *iv;
|
|
Ib_test = *iv;
|
|
|
Ic_test = *iw;
|
|
Ic_test = *iw;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @brief 修改后的motor_run()函数
|
|
|
|
|
+ * @note 集成了完整的开环→闭环切换逻辑
|
|
|
|
|
+ */
|
|
|
|
|
+void motor_run(void)
|
|
|
|
|
+{
|
|
|
|
|
+ uvw_current_and_vbus_get(&Vbus, &Ia, &Ib, &Ic);
|
|
|
|
|
+ //Hall_TypeDef* hall = Hall_Get();
|
|
|
|
|
+ //MotorParam_t* motor = get_motor();
|
|
|
|
|
+
|
|
|
|
|
+// Hall_Update_Interpolated_Angle();
|
|
|
|
|
+ if(speed_close_loop_flag==0) //速度环闭环切换控制,电机刚启动时速度环不闭环
|
|
|
|
|
+ { //并且电流参考值缓慢增加(防冲击),速度达到一定值
|
|
|
|
|
+ if((Iq_ref<MOTOR_STARTUP_CURRENT)) //速度切入闭环
|
|
|
|
|
+ { //电流环在电机运行过程中全程闭环
|
|
|
|
|
+ Iq_ref += 0.00003f; //角度在电机刚启动时就闭环运行,无需强拖,得益于卡尔曼滤波做
|
|
|
|
|
+ } //状态观测器低速性能比教好
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ speed_close_loop_flag=1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if(speed_close_loop_flag==1)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(Iq_ref>(MOTOR_STARTUP_CURRENT/2.0f))
|
|
|
|
|
+ {
|
|
|
|
|
+ Iq_ref -= 0.001f;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ speed_close_loop_flag=2;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+// if(FOC_Output.EKF[2]>SPEED_LOOP_CLOSE_RAD_S) //无感方式运行,状态观测器得到角度和速度信息
|
|
|
|
|
+// {
|
|
|
|
|
+// FOC_Input.Id_ref = 0.0f;
|
|
|
|
|
+// Speed_Fdk = FOC_Output.EKF[2];
|
|
|
|
|
+// FOC_Input.Iq_ref = Speed_Pid_Out;
|
|
|
|
|
+// }
|
|
|
|
|
+// else
|
|
|
|
|
+// {
|
|
|
|
|
+// FOC_Input.Id_ref = 0.0f;
|
|
|
|
|
+// FOC_Input.Iq_ref = Iq_ref;
|
|
|
|
|
+// Speed_Pid.I_Sum = Iq_ref;
|
|
|
|
|
+// }
|
|
|
|
|
+// FOC_Input.theta = FOC_Output.EKF[3];
|
|
|
|
|
+// FOC_Input.speed_fdk = FOC_Output.EKF[2];
|
|
|
|
|
+// EKF_Hz = FOC_Output.EKF[2]/(2.0f*PI);
|
|
|
|
|
+// FOC_Input.Id_ref = 0.0f;
|
|
|
|
|
+// FOC_Input.Tpwm = PWM_TIM_PULSE_TPWM; //FOC运行函数需要用到的输入信息
|
|
|
|
|
+// FOC_Input.Udc = Vbus;
|
|
|
|
|
+// FOC_Input.Rs = Rs;
|
|
|
|
|
+// FOC_Input.Ls = Ls;
|
|
|
|
|
+// FOC_Input.flux = flux;
|
|
|
|
|
+//
|
|
|
|
|
+// FOC_Input.ia = Ia;
|
|
|
|
|
+// FOC_Input.ib = Ib;
|
|
|
|
|
+// FOC_Input.ic = Ic;
|
|
|
|
|
+ // foc_algorithm_step(); //整个FOC运行函数(包括无感状态观测器,电流环,SVPWM,坐标变换,电机参数识别)
|
|
|
|
|
+ // ========== FOC参数设置 ==========
|
|
|
|
|
+ FOC_parm_input();
|
|
|
|
|
+ get_foc_input()->Iq_ref = 1.0f;
|
|
|
|
|
+ Hall_Update_Interpolated_Angle();
|
|
|
|
|
+ static uint16_t cnt = 0;
|
|
|
|
|
+ if(cnt <= 10000)
|
|
|
|
|
+ {
|
|
|
|
|
+ cnt++;
|
|
|
|
|
+ theta += 0.01f;
|
|
|
|
|
+ if(theta >= 2* PI)
|
|
|
|
|
+ {
|
|
|
|
|
+ theta -= 2 * PI;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(theta < 0.0f)
|
|
|
|
|
+ {
|
|
|
|
|
+ theta += 2 * PI;
|
|
|
|
|
+ }
|
|
|
|
|
+ get_foc_input()->theta = theta;
|
|
|
|
|
+
|
|
|
|
|
+ }else
|
|
|
|
|
+ {
|
|
|
|
|
+ get_foc_input()->theta = Hall_Get()->angle;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 执行FOC算法 ==========
|
|
|
|
|
+ motor_foc_openloop_run();
|
|
|
|
|
+ //motor_ekf_closeloop_run();
|
|
|
|
|
+ // ========== PWM输出更新 ==========
|
|
|
|
|
+ if(motor_start_stop == 1 )//&& motor->ctrl_state != CTRL_STATE_IDLE)
|
|
|
|
|
+ {
|
|
|
|
|
+ PWM_TIM->CCR1 = (u16)(FOC_Output.Tcmp1);
|
|
|
|
|
+ PWM_TIM->CCR2 = (u16)(FOC_Output.Tcmp2);
|
|
|
|
|
+ PWM_TIM->CCR3 = (u16)(FOC_Output.Tcmp3);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ PWM_TIM->CCR1 = PWM_TIM_PULSE >> 1;
|
|
|
|
|
+ PWM_TIM->CCR2 = PWM_TIM_PULSE >> 1;
|
|
|
|
|
+ PWM_TIM->CCR3 = PWM_TIM_PULSE >> 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 停止命令处理 ==========
|
|
|
|
|
+// if(motor_start_stop == 0 && motor->ctrl_state != CTRL_STATE_IDLE &&
|
|
|
|
|
+// motor->ctrl_state != CTRL_STATE_STOPPING)
|
|
|
|
|
+// {
|
|
|
|
|
+// motor->ctrl_state = CTRL_STATE_STOPPING;
|
|
|
|
|
+// }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
/**
|
|
/**
|
|
|
* @brief 电机运行函数
|
|
* @brief 电机运行函数
|
|
|
* @note 在PWM中断中调用,频率10kHz
|
|
* @note 在PWM中断中调用,频率10kHz
|
|
@@ -223,20 +351,28 @@ void motor_run(void)
|
|
|
FOC_parm_input();
|
|
FOC_parm_input();
|
|
|
|
|
|
|
|
FOC_parm_output();
|
|
FOC_parm_output();
|
|
|
-
|
|
|
|
|
|
|
+ if(get_motor()->direction == MOTOR_CW)
|
|
|
|
|
+ get_motor()->eleangle += 0.01f; // 使用 float 后缀
|
|
|
|
|
+ else if(get_motor()->direction == MOTOR_CCW)
|
|
|
|
|
+ get_motor()->eleangle -= 0.01f;
|
|
|
|
|
+// if(speed_close_loop_flag == 2)
|
|
|
|
|
+// {
|
|
|
|
|
+// if(get_motor()->direction == MOTOR_CW)
|
|
|
|
|
+// get_motor()->eleangle += Hall_Get()->angle_add; // 使用 float 后缀
|
|
|
|
|
+// else if(get_motor()->direction == MOTOR_CCW)
|
|
|
|
|
+// get_motor()->eleangle -= Hall_Get()->angle_add;
|
|
|
|
|
+// }
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- theta += 0.005f; // 使用 float 后缀
|
|
|
|
|
- if(theta >= 2.0f * PI)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if(get_motor()->eleangle >= 2.0f * PI)
|
|
|
{
|
|
{
|
|
|
- theta -= 2.0f * PI;
|
|
|
|
|
- }
|
|
|
|
|
- // 额外保护
|
|
|
|
|
- if(theta < 0.0f || theta > 100.0f) // 异常保护
|
|
|
|
|
|
|
+ get_motor()->eleangle -= 2.0f * PI;
|
|
|
|
|
+ }else if(get_motor()->eleangle <= 0.0f * PI)
|
|
|
{
|
|
{
|
|
|
- theta = 0.0f;
|
|
|
|
|
|
|
+ get_motor()->eleangle += 2.0f * PI;
|
|
|
}
|
|
}
|
|
|
- get_foc_input()->theta = theta;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ get_foc_input()->theta = get_motor()->eleangle;
|
|
|
get_foc_input()->Id_ref = Id_ref;
|
|
get_foc_input()->Id_ref = Id_ref;
|
|
|
get_foc_input()->Iq_ref = Iq_ref;
|
|
get_foc_input()->Iq_ref = Iq_ref;
|
|
|
|
|
|
|
@@ -260,7 +396,7 @@ void motor_run(void)
|
|
|
//communication_task();
|
|
//communication_task();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @brief ADC中断处理函数
|
|
* @brief ADC中断处理函数
|