文章目录
- 1、ST龙伯格算法分析(定点数)
- 1.1 符号说明
- 1.2 最大感应电动势计算
- 1.3 系数计算
- 1.4 龙伯格观测器计算
- 1.5 锁相环计算
- 1.6 观测器增益计算
- 1.7 锁相环PI计算(ST)
- 1.8 平均速度的用意
- 2、启动策略
- 2.1 V/F压频比控制
- 2.2 I/F压频比控制
- 3、算法开发
- 3.1 Luenberger核心算法模块
- 3.1.1 Luenberger.h
- 3.1.2 Luenberger.c
- 3.2 三段式启动状态机模块
- 3.2.1 mc_statemachine.h
- 3.2.2 mc_statemachine.c
- 3.3 初始化及函数调用
- 3.3.1 初始化
- 3.3.2 反馈速度处理
- 3.3.3 FOC模块处理
龙伯格观测+PLL理论篇: https://blog.csdn.net/qq_28149763/article/details/136346434
说明:关键代码已在本文给出(源码不开源,抱歉)
1、ST龙伯格算法分析(定点数)
1.1 符号说明
1.2 最大感应电动势计算
1.3 系数计算
1.4 龙伯格观测器计算
1.5 锁相环计算
1.6 观测器增益计算
1.7 锁相环PI计算(ST)
1.8 平均速度的用意
2、启动策略
2.1 V/F压频比控制
2.2 I/F压频比控制
3、算法开发
3.1 Luenberger核心算法模块
3.1.1 Luenberger.h
/** ****************************************************************************** * @file Luenberger.h * @author hlping * @version V1.0.0 * @date 2023-12-28 * @brief ****************************************************************************** * @attention * ****************************************************************************** */ #ifndef __LUENBERGER_H #define __LUENBERGER_H /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* Includes -----------------------------------------------------------------*/ #include
#include "mc_math.h" #include "foc.h" /* Macros -------------------------------------------------------------------*/ #define BUFFER_SIZE (u16)64 #define BUF_POW2 LOG2(BUFFER_SIZE) #define F1 (s16)(16384) #define F2 (s16)(8192) #define F1LOG LOG2(F1) #define F2LOG LOG2(F2) #define PLL_KP_F (s16)(16384) #define PLL_KI_F (u16)(65535) #define KPLOG LOG2(PLL_KP_F) #define KILOG LOG2(PLL_KI_F) #define PI 3.14159265358979 #define VARIANCE_THRESHOLD 0.0625 typedef struct { s32 K1; s32 K2; s16 hC2; s16 hC4; s16 hF1; s16 hF2; s16 hF3; s16 hC1; s16 hC3; s16 hC5; s16 hC6; s32 wIalfa_est; s32 wIbeta_est; s32 wBemf_alfa_est; s32 wBemf_beta_est; s32 hBemf_alfa_est; s32 hBemf_beta_est; }STO_Observer_t; typedef struct { s16 Rs; u16 Rs_factor; s16 Ls; u32 Ls_factor; u16 Pole; u16 pwm_frequency; u32 max_speed_rpm; s16 max_voltage; s16 max_current; s16 motor_voltage_constant; s16 motor_voltage_constant_factor; float motor_voltage_constant_f; u16 max_bemf_voltage; }STO_Parameter_t; typedef struct { bool_t Max_Speed_Out; bool_t Min_Speed_Out; bool_t Is_Speed_Reliable; s16 hSpeed_Buffer[BUFFER_SIZE]; u16 bSpeed_Buffer_Index; s32 wMotorMaxSpeed_dpp; u16 hPercentageFactor; s16 hRotor_Speed_dpp; s32 wSpeed_PI_integral_sum; s16 hSpeed_P_Gain; s16 hSpeed_I_Gain; s32 speed_sum; }STO_Speed_t; typedef struct { STO_Observer_t STO_Observer; STO_Speed_t STO_Speed; STO_Parameter_t STO_Parameter; s16 hRotor_El_Angle; s16 hRotor_Speed; s16 hLast_Rotor_Speed; s16 hRotor_avSpeed; }STO_luenberger; /* Typedefs -----------------------------------------------------------------*/ /* Function declarations ----------------------------------------------------*/ void STO_InitSpeedBuffer(STO_luenberger *pHandle); void STO_Init(STO_luenberger *pHandle); void STO_Update_Constant(STO_luenberger *pHandle); void STO_Set_k1k2(STO_luenberger *pHandle,s32 pk1,s32 pk2); void STO_PLL_Set_Gains(STO_luenberger *pHandle,s16 pkp,s16 pki); void STO_Gains_Init(STO_luenberger *pHandle); s16 Speed_PI(STO_luenberger *pHandle,s16 hAlfa_Sin, s16 hBeta_Cos); s16 Calc_Rotor_Speed(STO_luenberger *pHandle,s16 hBemf_alfa, s16 hBemf_beta); void Store_Rotor_Speed(STO_luenberger *pHandle,s16 hRotor_Speed); s16 STO_Get_Speed(STO_luenberger *pHandle); s16 STO_Get_Electrical_Angle(STO_luenberger *pHandle); void STO_Set_Electrical_Angle(STO_luenberger *pHandle,s16 eiAngle); void STO_Calc_Speed(STO_luenberger *pHandle); void STO_CalcElAngle(STO_luenberger *pHandle,FOCVars_t *pfoc, s16 hBusVoltage); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* __LUENBERGER_H */ /**** END OF FILE ****/ 3.1.2 Luenberger.c
/** ****************************************************************************** * @file Luenberger.c * @author hlping * @version V1.0.0 * @date 2023-12-28 * @brief ****************************************************************************** * @attention * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "Luenberger.h" /* Private define ------------------------------------------------------------*/ /** * @brief 初始化观测器速度缓冲区 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void STO_InitSpeedBuffer(STO_luenberger *pHandle) {u8 i; /*init speed buffer*/ for (i=0;i
pHandle->STO_Speed.hSpeed_Buffer[i] = 0x00; } pHandle->STO_Speed.bSpeed_Buffer_Index = 0; } /** * @brief 初始化观测器 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void STO_Init(STO_luenberger *pHandle) {pHandle->STO_Observer.wIalfa_est = 0; pHandle->STO_Observer.wIbeta_est = 0; pHandle->STO_Observer.wBemf_alfa_est = 0; pHandle->STO_Observer.wBemf_beta_est = 0; pHandle->STO_Speed.Is_Speed_Reliable = FALSE; pHandle->STO_Speed.wSpeed_PI_integral_sum = 0; pHandle->STO_Speed.Max_Speed_Out = FALSE; pHandle->STO_Speed.Min_Speed_Out = FALSE; pHandle->STO_Speed.hRotor_Speed_dpp = 0; pHandle->STO_Speed.speed_sum = 0; pHandle->hRotor_avSpeed=0; pHandle->hRotor_El_Angle = 0; //could be used for start-up procedure pHandle->hRotor_avSpeed = 0; STO_InitSpeedBuffer(pHandle); // hSpeed_P_Gain = 1638; //0.1*16384 // hSpeed_I_Gain = 0; } /** * @brief 设置观测器增益参数 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param pk1 增益参数1 * @param pk2 增益参数2 * @return 无返回值 */ void STO_Set_k1k2(STO_luenberger *pHandle,s32 pk1,s32 pk2) { pHandle->STO_Observer.K1 = pk1; pHandle->STO_Observer.K2 = pk2; } /** * @brief 设置观测器PLL增益参数 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param pkp PLL比例增益参数 * @param pki PLL积分增益参数 * @return 无返回值 */ void STO_PLL_Set_Gains(STO_luenberger *pHandle,s16 pkp,s16 pki) { pHandle->STO_Speed.hSpeed_P_Gain = pkp; pHandle->STO_Speed.hSpeed_I_Gain = pki; } /** * @brief 更新观测器常数参数 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void STO_Update_Constant(STO_luenberger *pHandle) {float temp_rs; float temp_ls; temp_rs=pHandle->STO_Parameter.Rs/(float)pHandle->STO_Parameter.Rs_factor; temp_ls=pHandle->STO_Parameter.Ls/(float)pHandle->STO_Parameter.Ls_factor; pHandle->STO_Observer.hC1 = (s32)(pHandle->STO_Observer.hF1 * temp_rs/(temp_ls*pHandle->STO_Parameter.pwm_frequency)); //pHandle->STO_Observer.hC2 = (s32)(hF1 * k1/(float)(pHandle->STO_Parameter.pwm_frequency)); pHandle->STO_Observer.hC2 = (s32)(pHandle->STO_Observer.K1);//�����Ǵ������ģ�����Ҫ�ڳ���Ƶ�� pHandle->STO_Observer.hC3 = (s32)(pHandle->STO_Observer.hF1 * pHandle->STO_Parameter.max_bemf_voltage/(temp_ls*pHandle->STO_Parameter.max_current*pHandle->STO_Parameter.pwm_frequency)); //pHandle->STO_Observer.hC4 = (s32)(((k2 * max_current/(max_bemf_voltage))*hF2)/(float)pHandle->STO_Parameter.pwm_frequency); //pHandle->STO_Observer.hC4 = (s32)(hF1 * k2/(float)(pHandle->STO_Parameter.pwm_frequency)); pHandle->STO_Observer.hC4 = (s32)(pHandle->STO_Observer.K2);//�����Ǵ������ģ�����Ҫ�ڳ���Ƶ�� pHandle->STO_Observer.hC5 = (s32)(pHandle->STO_Observer.hF1 * pHandle->STO_Parameter.max_voltage/(temp_ls*pHandle->STO_Parameter.max_current*pHandle->STO_Parameter.pwm_frequency)); // hC1 = pHandle->STO_Observer.hC1; // hC2 = pHandle->STO_Observer.hC2; // hC3 = pHandle->STO_Observer.hC3; // hC4 = pHandle->STO_Observer.hC4; // hC5 = pHandle->STO_Observer.hC5; } /** * @brief 初始化观测器增益参数 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void STO_Gains_Init(STO_luenberger *pHandle) {s16 htempk; pHandle->STO_Observer.hF3 = 1; htempk = (s16)((100*65536)/(F2*2*PI)); //100 rad/s while (htempk != 0) {htempk /= 2; pHandle->STO_Observer.hF3 *= 2; } pHandle->STO_Observer.hC6 = (s16)((F2 * pHandle->STO_Observer.hF3 * 2 * PI)/65536);//10000 pHandle->STO_Observer.hF1 = F1; pHandle->STO_Observer.hF2 = F2; pHandle->STO_Parameter.motor_voltage_constant_f = (float)(pHandle->STO_Parameter.motor_voltage_constant/(float)pHandle->STO_Parameter.motor_voltage_constant_factor); pHandle->STO_Parameter.max_bemf_voltage = (u16)((1.2 * pHandle->STO_Parameter.max_speed_rpm*pHandle->STO_Parameter.motor_voltage_constant_f*SQRT_2)/(1000*SQRT_3)); // pHandle->STO_Parameter.max_current = (u16)(pHandle->STO_Parameter.max_current); // pHandle->STO_Parameter.max_voltage = (s16)(pHandle->STO_Parameter.max_voltage); STO_Update_Constant(pHandle); // hSpeed_P_Gain = PLL_KP_GAIN; // hSpeed_I_Gain = PLL_KI_GAIN; pHandle->STO_Speed.wMotorMaxSpeed_dpp = (s32)((1.2 * pHandle->STO_Parameter.max_speed_rpm*65536*pHandle->STO_Parameter.Pole)/(float)(pHandle->STO_Parameter.pwm_frequency*60)); pHandle->STO_Speed.hPercentageFactor = (u16)(VARIANCE_THRESHOLD*128); } /** * @brief 计算电机旋转速度的PID控制器 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param hAlfa_Sin e_alpha*sin * @param hBeta_Cos e_beta*cos * @return 返回计算得到的电机旋转速度 */ s16 Speed_PI(STO_luenberger *pHandle,s16 hAlfa_Sin, s16 hBeta_Cos) {s32 wSpeed_PI_error, wOutput; s32 wSpeed_PI_proportional_term, wSpeed_PI_integral_term; wSpeed_PI_error = hBeta_Cos - hAlfa_Sin; #if 0 //???? if(wSpeed_PI_error > 50) wSpeed_PI_error = 50; else if(wSpeed_PI_error < -50) wSpeed_PI_error = -50; #endif wSpeed_PI_proportional_term = pHandle->STO_Speed.hSpeed_P_Gain * wSpeed_PI_error; // !!!p wSpeed_PI_integral_term = pHandle->STO_Speed.hSpeed_I_Gain * wSpeed_PI_error; // !!!i if ( (pHandle->STO_Speed.wSpeed_PI_integral_sum >= 0) && (wSpeed_PI_integral_term >= 0) && (pHandle->STO_Speed.Max_Speed_Out == FALSE) ) {if ((s32)(pHandle->STO_Speed.wSpeed_PI_integral_sum + wSpeed_PI_integral_term) < 0) {pHandle->STO_Speed.wSpeed_PI_integral_sum = S32_MAX; } else {pHandle->STO_Speed.wSpeed_PI_integral_sum += wSpeed_PI_integral_term; //integral } } else if ( (pHandle->STO_Speed.wSpeed_PI_integral_sum <= 0) && (wSpeed_PI_integral_term <= 0) && (pHandle->STO_Speed.Min_Speed_Out == FALSE) ) {if((s32)(pHandle->STO_Speed.wSpeed_PI_integral_sum + wSpeed_PI_integral_term) > 0) {pHandle->STO_Speed.wSpeed_PI_integral_sum = -S32_MAX; } else {pHandle->STO_Speed.wSpeed_PI_integral_sum += wSpeed_PI_integral_term; //integral } } else {pHandle->STO_Speed.wSpeed_PI_integral_sum += wSpeed_PI_integral_term; //integral } wOutput = (wSpeed_PI_proportional_term >> KPLOG) + (pHandle->STO_Speed.wSpeed_PI_integral_sum >> KILOG); if (wOutput > pHandle->STO_Speed.wMotorMaxSpeed_dpp) {pHandle->STO_Speed.Max_Speed_Out = TRUE; wOutput = pHandle->STO_Speed.wMotorMaxSpeed_dpp; } else if (wOutput < (-pHandle->STO_Speed.wMotorMaxSpeed_dpp)) {pHandle->STO_Speed.Min_Speed_Out = TRUE; wOutput = -pHandle->STO_Speed.wMotorMaxSpeed_dpp; } else {pHandle->STO_Speed.Max_Speed_Out = FALSE; pHandle->STO_Speed.Min_Speed_Out = FALSE; } return ((s16)wOutput); } /** * @brief 锁相环计算电机控制器旋转速度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param hBemf_alfa BEMF alpha轴反电动势观测值 * @param hBemf_beta BEMF beta轴反电动势观测值 * @return 返回计算得到的电机旋转速度 */ s16 Calc_Rotor_Speed(STO_luenberger *pHandle,s16 hBemf_alfa, s16 hBemf_beta) {s32 wAlfa_Sin_tmp, wBeta_Cos_tmp; s16 hOutput; Trig_Components Local_Components; Local_Components = Trig_Functions(pHandle->hRotor_El_Angle); /* Alfa & Beta BEMF multiplied by hRotor_El_Angle Cos & Sin*/ wAlfa_Sin_tmp = (s32)(hBemf_alfa * Local_Components.hSin); wBeta_Cos_tmp = (s32)(hBemf_beta * Local_Components.hCos); //alfa_sin_test = wAlfa_Sin_tmp >> 15; //beta_cos_test = wBeta_Cos_tmp >> 15; /* Speed PI regulator */ hOutput = Speed_PI(pHandle,(s16)(wAlfa_Sin_tmp >> 15), (s16)(wBeta_Cos_tmp >> 15)); return (hOutput); } /** * @brief 将电机旋转速度存储数组中 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param hRotor_Speed 要存储的电机旋转速度 * @return 无返回值 */ void Store_Rotor_Speed(STO_luenberger *pHandle,s16 hRotor_Speed) {static s32 start_flag; pHandle->STO_Speed.hSpeed_Buffer[pHandle->STO_Speed.bSpeed_Buffer_Index] = hRotor_Speed; pHandle->STO_Speed.speed_sum += pHandle->STO_Speed.hSpeed_Buffer[pHandle->STO_Speed.bSpeed_Buffer_Index]; if(++(pHandle->STO_Speed.bSpeed_Buffer_Index) >= BUFFER_SIZE) //16 {pHandle->STO_Speed.bSpeed_Buffer_Index = 0; start_flag = 1; } if(start_flag == 0) {pHandle->hRotor_avSpeed = pHandle->STO_Speed.speed_sum / pHandle->STO_Speed.bSpeed_Buffer_Index; } else {pHandle->hRotor_avSpeed = pHandle->STO_Speed.speed_sum >> BUF_POW2; pHandle->STO_Speed.speed_sum -= pHandle->STO_Speed.hSpeed_Buffer[pHandle->STO_Speed.bSpeed_Buffer_Index]; } pHandle->STO_Speed.hRotor_Speed_dpp = pHandle->hRotor_avSpeed; /* bSpeed_Buffer_Index++; if (bSpeed_Buffer_Index == BUFFER_SIZE) //64 { bSpeed_Buffer_Index = 0; STO_Calc_Speed(); } hSpeed_Buffer[bSpeed_Buffer_Index] = hRotor_Speed; */ } /** * @brief 获取电机旋转速度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 返回电机旋转速度 */ s16 STO_Get_Speed(STO_luenberger *pHandle) {return (pHandle->hRotor_avSpeed); } /** * @brief 获取电机转子的电角度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 返回电机电角位 */ s16 STO_Get_Electrical_Angle(STO_luenberger *pHandle) {return (pHandle->hRotor_El_Angle); } /** * @brief 设置电机转子的电角度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param eiAngle 设置的电机电角位 * @return 无返回值 */ void STO_Set_Electrical_Angle(STO_luenberger *pHandle,s16 eiAngle) {pHandle->hRotor_El_Angle = eiAngle; } /** * @brief 计算观测速度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void STO_Calc_Speed(STO_luenberger *pHandle) {s32 wAverage_Speed = 0; s32 wError; s32 wAverageQuadraticError = 0; u8 i; for (i = 0; i < BUFFER_SIZE; i++) {wAverage_Speed += pHandle->STO_Speed.hSpeed_Buffer[i]; } wAverage_Speed = wAverage_Speed >> BUF_POW2; pHandle->STO_Speed.hRotor_Speed_dpp = (s16)(wAverage_Speed); for (i = 0; i < BUFFER_SIZE; i++) {wError = pHandle->STO_Speed.hSpeed_Buffer[i] - wAverage_Speed; wError = (wError * wError); wAverageQuadraticError += (u32)(wError); } //It computes the measurement variance wAverageQuadraticError= wAverageQuadraticError >> BUF_POW2; //The maximum variance acceptable is here calculated as ratio of average speed wAverage_Speed = (s32)(wAverage_Speed * wAverage_Speed); wAverage_Speed = (wAverage_Speed >> 7) * pHandle->STO_Speed.hPercentageFactor; #if 0 // for debug only QuadraticError = wAverageQuadraticError; AverageSpeed = wAverage_Speed; #endif if (wAverageQuadraticError > wAverage_Speed) {pHandle->STO_Speed.Is_Speed_Reliable = FALSE; } else {pHandle->STO_Speed.Is_Speed_Reliable = TRUE; } } /** * @brief 观测器观测电角度 * @param pHandle 指向STO_luenberger结构体的指针,用于存储控制器的状态信息 * @param pfoc 指向FOCVars_t结构体的指针,用于存储电压和电流信息 * @param hBusVoltage 输入电压 * @return 无返回值 */ void STO_CalcElAngle(STO_luenberger *pHandle,FOCVars_t *pfoc, s16 hBusVoltage) {s32 wIalfa_est_Next, wIbeta_est_Next; s32 wBemf_alfa_est_Next, wBemf_beta_est_Next; s16 hValfa, hVbeta; s16 hIalfa_err, hIbeta_err; s32 bDirection; s16 hRotor_Speed; if (pHandle->STO_Observer.wBemf_alfa_est > (s32)(S16_MAX * pHandle->STO_Observer.hF2)) {pHandle->STO_Observer.wBemf_alfa_est = S16_MAX * pHandle->STO_Observer.hF2; } else if (pHandle->STO_Observer.wBemf_alfa_est <= (s32)(S16_MIN * pHandle->STO_Observer.hF2)) {pHandle->STO_Observer.wBemf_alfa_est = -S16_MAX * pHandle->STO_Observer.hF2; } if (pHandle->STO_Observer.wBemf_beta_est > (s32)(S16_MAX * pHandle->STO_Observer.hF2)) {pHandle->STO_Observer.wBemf_beta_est = S16_MAX * pHandle->STO_Observer.hF2; } else if (pHandle->STO_Observer.wBemf_beta_est <= (s32)(S16_MIN * pHandle->STO_Observer.hF2)) {pHandle->STO_Observer.wBemf_beta_est = -S16_MAX * pHandle->STO_Observer.hF2; } if (pHandle->STO_Observer.wIalfa_est > (s32)(S16_MAX * pHandle->STO_Observer.hF1)) {pHandle->STO_Observer.wIalfa_est = S16_MAX * pHandle->STO_Observer.hF1; } else if (pHandle->STO_Observer.wIalfa_est <= (s32)(S16_MIN * pHandle->STO_Observer.hF1)) {pHandle->STO_Observer.wIalfa_est = -S16_MAX * pHandle->STO_Observer.hF1; } if (pHandle->STO_Observer.wIbeta_est > S16_MAX * pHandle->STO_Observer.hF1) {pHandle->STO_Observer.wIbeta_est = S16_MAX * pHandle->STO_Observer.hF1; } else if (pHandle->STO_Observer.wIbeta_est <= S16_MIN * pHandle->STO_Observer.hF1) {pHandle->STO_Observer.wIbeta_est = -S16_MAX * pHandle->STO_Observer.hF1; } hIalfa_err = (s16)((pHandle->STO_Observer.wIalfa_est >> F1LOG)- pfoc->Ialphabeta.alpha); hIbeta_err = (s16)((pHandle->STO_Observer.wIbeta_est >> F1LOG)- pfoc->Ialphabeta.beta); hValfa = (s16)((pfoc->Valphabeta.alpha * hBusVoltage) >> 15); //�������ߵ�ѹĿ���Ǽ�С���ߵ�ѹ������ϵͳ��Ӱ�� hVbeta = (s16)((pfoc->Valphabeta.beta * hBusVoltage) >> 15); //�������ߵ�ѹĿ���Ǽ�С���ߵ�ѹ������ϵͳ��Ӱ�� /*alfa axes observer*/ wIalfa_est_Next = (s32)(pHandle->STO_Observer.wIalfa_est - (s32)(pHandle->STO_Observer.hC1 * (s16)(pHandle->STO_Observer.wIalfa_est >> F1LOG)) +(s32)(pHandle->STO_Observer.hC2 * hIalfa_err)+(s32)(pHandle->STO_Observer.hC5 * hValfa) -(s32)(pHandle->STO_Observer.hC3 * (s16)(pHandle->STO_Observer.wBemf_alfa_est >> F2LOG))); //I(n+1)=I(n)-rs*T/Ls*I(n)+K1*(I(n)-i(n))+T/Ls*V-T/Ls*emf wBemf_alfa_est_Next = (s32)(pHandle->STO_Observer.wBemf_alfa_est + (s32)(pHandle->STO_Observer.hC4 * hIalfa_err) +(s32)(pHandle->STO_Observer.hC6 * pHandle->STO_Speed.hRotor_Speed_dpp * (pHandle->STO_Observer.wBemf_beta_est / (pHandle->STO_Observer.hF2 * pHandle->STO_Observer.hF3))));//(wBemf_beta_est>>20))); //emf(n+1)=emf(n)+K2*(I(n)-i(n))+p*w*emfb*T /*beta axes observer*/ wIbeta_est_Next = (s32)(pHandle->STO_Observer.wIbeta_est - (s32)(pHandle->STO_Observer.hC1 * (s16)(pHandle->STO_Observer.wIbeta_est >> F1LOG)) +(s32)(pHandle->STO_Observer.hC2 * hIbeta_err)+(s32)(pHandle->STO_Observer.hC5 * hVbeta) -(s32)(pHandle->STO_Observer.hC3 * (s16)(pHandle->STO_Observer.wBemf_beta_est >> F2LOG))); wBemf_beta_est_Next = (s32)(pHandle->STO_Observer.wBemf_beta_est + (s32)(pHandle->STO_Observer.hC4 * hIbeta_err) -(s32)(pHandle->STO_Observer.hC6 * pHandle->STO_Speed.hRotor_Speed_dpp * (pHandle->STO_Observer.wBemf_alfa_est / (pHandle->STO_Observer.hF2 * pHandle->STO_Observer.hF3))));//(wBemf_alfa_est>>20))); /* Extrapolation of present rotation direction, necessary for PLL */ if (pHandle->STO_Speed.hRotor_Speed_dpp >= 0) {bDirection = -1; } else {bDirection = 1; } /*Calls the PLL blockset*/ pHandle->STO_Observer.hBemf_alfa_est = pHandle->STO_Observer.wBemf_alfa_est >> F2LOG; pHandle->STO_Observer.hBemf_beta_est = pHandle->STO_Observer.wBemf_beta_est >> F2LOG; pHandle->hRotor_Speed = Calc_Rotor_Speed(pHandle,(s16)(pHandle->STO_Observer.hBemf_alfa_est * bDirection),(s16)(-pHandle->STO_Observer.hBemf_beta_est * bDirection)); if(pfoc->Vqd.q > 0) {if(pHandle->hRotor_Speed < 0) {pHandle->hRotor_Speed = -pHandle->hRotor_Speed; } } else //MotorCtrl.Dir == CCW {if(pHandle->hRotor_Speed > 0) {pHandle->hRotor_Speed = -pHandle->hRotor_Speed; } } Store_Rotor_Speed(pHandle,pHandle->hRotor_Speed); pHandle->hRotor_El_Angle = (s16)(pHandle->hRotor_El_Angle + pHandle->hRotor_Speed); /*storing previous values of currents and bemfs*/ pHandle->STO_Observer.wIalfa_est = wIalfa_est_Next; pHandle->STO_Observer.wBemf_alfa_est = wBemf_alfa_est_Next; pHandle->STO_Observer.wIbeta_est = wIbeta_est_Next; pHandle->STO_Observer.wBemf_beta_est = wBemf_beta_est_Next; } /**** END OF FILE ****/ 3.2 三段式启动状态机模块
3.2.1 mc_statemachine.h
mc_statemachine.h定义相关变量和结构体以及函数申明:
/** ****************************************************************************** * @file mc_statemachine.h * @author hlping * @version V1.0.0 * @date 2022-11-28 * @brief ****************************************************************************** * @attention * ****************************************************************************** */ #ifndef __MC_STATEMACHINE_H #define __MC_STATEMACHINE_H /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" {#endif /* Includes -----------------------------------------------------------------*/ #include
#include "Luenberger.h" /* Macros -------------------------------------------------------------------*/ /* Typedefs -----------------------------------------------------------------*/ #define OPEN_LOOP 0 #define CLOSE_LOOP 1 #define IDLE_STATE 2 #define CLOSE_SWITCH 3 #define OPENLOOPTIMEINSEC 8.0 typedef enum{MOTOR_STOP=0, MOTOR_INIT=1, MOTOR_START=2, MOTOR_RUN=3, MOTOR_FAULT=4, MOTOR_BRAKE=5 } MCStatus_t; //typedef struct //{// MCStatus_t Status; // u32 StatusMacCnt; // u32 Dir; // bool_t DirChangeFlag; // bool_t StartupFlag; // s16 SpdRampRef; // s16 SpdRef; //}mc_control_t; typedef struct {u32 State; u32 Angle; s16 LockCnt; u16 pole; u32 pwm_frequency; float looptimeinsec; //u32 time; u32 locktime; u16 initialSpeedinRpm; u16 start_iq; u16 start_iq_max; u16 min_iq; u16 start_vq; u16 endSpeedOpenloop; u16 inc_iq; u32 ramp_time; u32 delta_startup_ramp; s16 ElangleError; bool_t speed_loop_enable; bool_t current_loop_enable; }mc_openloop_t; /* Function declarations ----------------------------------------------------*/ void mc_statemachine_init(mc_openloop_t *ploop); void mc_statemachine_process(mc_openloop_t *popen,STO_luenberger *pHandle,FOCVars_t *pfoc,s16 hBusVoltage); u16 mc_get_state(mc_openloop_t *ploop); bool_t mc_get_speed_loop_enable(mc_openloop_t *ploop); void mc_set_speed_loop_enable(mc_openloop_t *ploop,bool_t state); bool_t mc_get_current_loop_enable(mc_openloop_t *ploop); void mc_set_current_loop_enable(mc_openloop_t *ploop,bool_t state); void mc_set_vf_iqRef(FOCVars_t *pfoc,int16_t piqref); void mc_parameter_init(mc_openloop_t *ploop); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* __MC_STATEMACHINE_H */ /**** END OF FILE ****/ 3.2.2 mc_statemachine.c
/** ****************************************************************************** * @file mc_statemachine.c * @author hlping * @version V1.0.0 * @date 2023-01-08 * @brief ****************************************************************************** * @attention * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "mc_statemachine.h" #include "public_global.h" /* Variable definitions ------------------------------------------------------*/ /** * @brief 初始化电机启动控制器状态机 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void mc_statemachine_init(mc_openloop_t *ploop) { ploop->speed_loop_enable = FALSE; ploop->current_loop_enable = FALSE; // locktime = ploop->time; // ploop->Angle = 0; // ploop->State = IDLE_STATE; // ploop->LockCnt = 0; // endSpeedOpenloop = ploop->endSpeedOpenloop; ploop->looptimeinsec = 1/(float)ploop->pwm_frequency; ploop->inc_iq = 32767 * (ploop->start_iq_max - ploop->start_iq)/ploop->locktime; ploop->ramp_time = (u32)(ploop->endSpeedOpenloop * ploop->pole * 65536 * ploop->looptimeinsec * 65536 /60 ); ploop->delta_startup_ramp = (u32)((ploop->ramp_time/OPENLOOPTIMEINSEC)/(float)ploop->pwm_frequency); } /** * @brief 处理电机启动控制器状态机 * @param popen 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @param pHandle 指向STO_luenberger结构体的指针,用于存储观测器状态 * @param pfoc 指向FOCVars_t结构体的指针,用于存储FOC相关变量 * @param hBusVoltage 输入电压,单位为V * @return 无返回值 */ void mc_statemachine_process(mc_openloop_t *popen,STO_luenberger *pHandle,FOCVars_t *pfoc,s16 hBusVoltage) { if(popen->LockCnt >= popen->locktime && popen->State != IDLE_STATE) STO_CalcElAngle(pHandle,pfoc, hBusVoltage); if(popen->State == OPEN_LOOP) {if(popen->LockCnt < popen->locktime) //LOCK {static s32 iq_ref_temp = 0; if (popen->LockCnt == 0) iq_ref_temp = 0; popen->LockCnt++; // if( FOCVars.Vqd.q > 0) //��ת // iq_ref_temp += inc_iq; // else if(FOCVars.Vqd.q < 0) //��ת // iq_ref_temp -= inc_iq; // else //ֹͣ // iq_ref_temp = 0; iq_ref_temp += popen->inc_iq; FOCVars.Iqdref.q = iq_ref_temp >> 15; } else if(popen->Angle < popen->ramp_time) //SPEED RAMP {if (popen->Angle == 0) {//FOCVars.Vqd.q = popen->start_vq * 32767 ; FOCVars.Vqd.q = popen->start_vq ; FOCVars.Vqd.d = 0 ; } popen->Angle += popen->delta_startup_ramp; if( FOCVars.Vqd.q > 0) //正转 FOCVars.hElAngle += (popen->Angle >> 16); else if(FOCVars.Vqd.q < 0) //反转 FOCVars.hElAngle -= (popen->Angle >> 16); } else {popen->State = CLOSE_LOOP; //#ifndef NDEBUG // OpenLoopSpeed = STO_Get_Speed(); // for test only //#endif #if 0 //just for test,openloop for observation angle popen->speed_loop_enable = FALSE; popen->current_loop_enable = FALSE; #else popen->speed_loop_enable = TRUE; popen->current_loop_enable = TRUE; #endif popen->ElangleError = STO_Get_Electrical_Angle(pHandle) - FOCVars.hElAngle; //FOCVars.hElAngle = STO_Get_Electrical_Angle(pHandle); } } else if(popen->State == CLOSE_LOOP) { FOCVars.hElAngle = STO_Get_Electrical_Angle(pHandle) - popen->ElangleError; // FOCVars.hElAngle = STO_Get_Electrical_Angle(pHandle) - (popen->ElangleError>>2); // //s16 err = popen->ElangleError>>2; // if(popen->ElangleError > 0) // popen->ElangleError--; // else if(popen->ElangleError < 0) // popen->ElangleError++; } } /** * @brief 初始化电机控制器参数 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @return 无返回值 */ void mc_parameter_init(mc_openloop_t *ploop) { ploop->State = OPEN_LOOP; //开环启动 ploop->Angle = 0; //如等于RAMP_TIME就意味着跳过RAMP阶段,直接速度闭环 ploop->LockCnt = 0; ploop->speed_loop_enable = FALSE; ploop->current_loop_enable = FALSE; } /** * @brief 设置电机控制器的中间变量 * @param pfoc 指向FOCVars_t结构体的指针,用于存储电机控制器的中间变量 * @param piqref 输入的iq参考值 * @return 无返回值 */ void mc_set_vf_iqRef(FOCVars_t *pfoc,int16_t piqref) { pfoc->Iqdref.q = piqref; pfoc->Iqdref.d = 0; } /** * @brief 获取电机控制器的状态 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @return 返回控制器的状态 */ u16 mc_get_state(mc_openloop_t *ploop) { return (ploop->State); } /** * @brief 获取电机控制器是否启用速度环 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @return 返回true或false,表示是否启用速度环 */ bool_t mc_get_speed_loop_enable(mc_openloop_t *ploop) { return (ploop->speed_loop_enable); } /** * @brief 设置电机控制器是否启用速度环 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @param state 设置为true或false,表示是否启用速度环 * @return 无返回值 */ void mc_set_speed_loop_enable(mc_openloop_t *ploop,bool_t state) { ploop->speed_loop_enable = state; } /** * @brief 获取电机控制器是否启用电流环 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @return 返回true或false,表示是否启用电流环 */ bool_t mc_get_current_loop_enable(mc_openloop_t *ploop) { return (ploop->current_loop_enable); } /** * @brief 设置电机控制器是否启用电流环 * @param ploop 指向mc_openloop_t结构体的指针,用于存储控制器的状态信息 * @param state 设置为true或false,表示是否启用电流环 * @return 无返回值 */ void mc_set_current_loop_enable(mc_openloop_t *ploop,bool_t state) { ploop->current_loop_enable = state; } /**** END OF FILE ****/
3.3 初始化及函数调用
定义全局变量:
STO_luenberger STO_LBG; //龙伯格观测器相关变量 mc_openloop_t mc_openloop; //三段式启动相关变量
3.3.1 初始化
当编码器类型为ENCODER_TYPE_UNKNOWN时为无感运行模式:
if(sensor_peripheral.Encoder_Sensor.encType == ENCODER_TYPE_UNKNOWN)//just for sensorless {sensor_peripheral.Encoder_Sensor.encRes=65535; /* init Luenberger parameter */ STO_Parameter_t Parameter={ .Rs = 55, //0.055 pMotorParSet.tBasePar.resist[A_AXIS] .Rs_factor = 1000, .Ls = 21, //2.1e-4 pMotorParSet.tBasePar.inductance[A_AXIS] .Ls_factor = 100000, .Pole = pMotorParSet.tBasePar.poles[A_AXIS], //4 .pwm_frequency = SAMPLE_FREQUENCY, //10000 //.max_speed_rpm = pMotorParSet.tBasePar.ratedVel[A_AXIS]*60/sensor_peripheral.Encoder_Sensor.encRes,//rpm .max_speed_rpm = 3000,//rpm .max_voltage = (s16)(ProtectPar.regenOn/1000), //36000 mV //.max_current = pMotorParSet.tBasePar.maxPhaseCurr[A_AXIS]/1000, //A .max_current = 31, //A .motor_voltage_constant = 4, //4v/1000rpm .motor_voltage_constant_factor = 1, }; memcpy(&STO_LBG.STO_Parameter,&Parameter,sizeof(STO_Parameter_t)); STO_Init(&STO_LBG); STO_Set_k1k2(&STO_LBG,-24225,25925); STO_Gains_Init(&STO_LBG); STO_PLL_Set_Gains(&STO_LBG,638,45); mc_openloop_t openloop={ .State= IDLE_STATE, .Angle = 0, .LockCnt = 0, .pole = pMotorParSet.tBasePar.poles[A_AXIS], .pwm_frequency = SAMPLE_FREQUENCY, .looptimeinsec = 1/(float)SAMPLE_FREQUENCY, .locktime = SAMPLES_PER_50MSECOND, .start_iq = 0, //Q轴启动电流 .start_iq_max = 3000, //mA .endSpeedOpenloop = 300, //rpm .start_vq = 4000, //VF启动电压 }; memcpy(&mc_openloop,&openloop,sizeof(mc_openloop_t)); mc_statemachine_init(&mc_openloop); }
3.3.2 反馈速度处理
void AxisVelocityCalc() {float ftempll; if(sensor_peripheral.Encoder_Sensor.encType != ENCODER_TYPE_UNKNOWN) { pAxisPar.vel[A_AXIS][2] = sensor_peripheral.Encoder_Sensor.deltaPos * SAMPLE_FREQUENCY; //TODO: ftempll = (float) pAxisPar.vel[A_AXIS][2]; ftempll =_filterPar._velFdk(&ftempll,&_filterPar);//250 point 1.5us pAxisPar.vel[A_AXIS][1] = (long) ftempll; pAxisPar.vel[A_AXIS][0] = pAxisPar.vel[A_AXIS][1]; }else { pAxisPar.vel[A_AXIS][2] = STO_Get_Speed(&STO_LBG)*sensor_peripheral.Encoder_Sensor.encRes/(pMotorParSet.tBasePar.poles[A_AXIS] * 2 * PI);//we->rpm->plus; //TODO: ftempll = (float) pAxisPar.vel[A_AXIS][2]; ftempll =_filterPar._velFdk(&ftempll,&_filterPar);//250 point 1.5us pAxisPar.vel[A_AXIS][1] = (long) ftempll; pAxisPar.vel[A_AXIS][0] = pAxisPar.vel[A_AXIS][1]; } }
3.3.3 FOC模块处理
/** * @brief FOC function * @param None * @retval None **/ void FOC_Model(void) { FOCVars.Iqdref.q = pMotorParSet.currRef[A_AXIS];//*1.414; // RMS result FOCVars.Iqdref.d = 0; // FOC_Cal(&FOCVars); FOCVars.Ialphabeta = Clark(FOCVars.Iab); FOCVars.Iqd = Park(FOCVars.Ialphabeta, FOCVars.hElAngle); FOCVars.IqdErr.d = FOCVars.Iqdref.d - FOCVars.Iqd.d; FOCVars.IqdErr.q = FOCVars.Iqdref.q - FOCVars.Iqd.q; if(sensor_peripheral.Encoder_Sensor.encType != ENCODER_TYPE_UNKNOWN) {FOCVars.Vqd.d = PI_Controller(&PidIdHandle, FOCVars.IqdErr.d); PidIqHandle.hKpGain = PidIdHandle.hKpGain; PidIqHandle.hKiGain = PidIdHandle.hKiGain; FOCVars.Vqd.q = PI_Controller(&PidIqHandle, FOCVars.IqdErr.q); }else { if(mc_get_current_loop_enable(&mc_openloop) == TRUE) { FOCVars.Vqd.d = PI_Controller(&PidIdHandle, FOCVars.IqdErr.d); PidIqHandle.hKpGain = PidIdHandle.hKpGain; PidIqHandle.hKiGain = PidIdHandle.hKiGain; FOCVars.Vqd.q = PI_Controller(&PidIqHandle, FOCVars.IqdErr.q); } //mc_statemachine_process(&mc_openloop,&STO_LBG,&FOCVars,sensor_peripheral.pVbusPar.glVBus);//放在这里主要是可以重置FOCVars.Vqd.q mc_statemachine_process(&mc_openloop,&STO_LBG,&FOCVars,24000);//放在这里主要是可以重置FOCVars.Vqd.q } #if 1 //STO_CalcElAngle(&FOCVars,sensor_peripheral.pVbusPar.glVBus); glDebugTestD[12] = STO_Get_Speed(&STO_LBG)*sensor_peripheral.Encoder_Sensor.encRes/(pMotorParSet.tBasePar.poles[A_AXIS] * 2 * PI);//we->rpm->plus glDebugTestD[13] = STO_Get_Electrical_Angle(&STO_LBG); glDebugTestD[16] = FOCVars.hElAngle; #endif FOCVars.Vqd = Circle_LimitationFunc(&FOCVars.CircleLimitationFoc, FOCVars.Vqd); //340 point FOCVars.Valphabeta = Rev_Park(FOCVars.Vqd, FOCVars.hElAngle); //TODO: USING COSA COSB calc infront..... FOCVars.DutyCycle = SVPWM_3ShuntCalcDutyCycles(&FOCVars); pMotorParSet.va[A_AXIS] = MID_PWM_CLK_PRD - FOCVars.DutyCycle.CntPhA; pMotorParSet.vb[A_AXIS] = MID_PWM_CLK_PRD - FOCVars.DutyCycle.CntPhB; pMotorParSet.vc[A_AXIS] = MID_PWM_CLK_PRD - FOCVars.DutyCycle.CntPhC; }
实际效果(约100rpm)
目前代码还有优化空间:实现正反转(反转先降速切开环,反向开环拖动,最后切闭环)