代码
SMO.c
#include "Sensorless_SMO.h"
#include "IQ_math.h"
#define PI 3.14159265358979
extern Angle_SMO Angle_SMOPare ;
extern Speed_est Speed_estPare ;
extern SMO_Motor SMO_MotorPare ;
extern IQAtan IQAtan_Pare;
//这段代码实现了角度估计的计算过程,其中包括滑模位置观测器的更新、电流误差的计算、滑动控制量的计算和反电势的估计
void Angle_Cale(p_Angle_SMO pV)
{
/* Sliding mode current observer */
pV->EstIalpha = _IQmpy(pV->Fsmopos,pV->EstIalpha) + _IQmpy(pV->Gsmopos,(pV->Valpha-pV->Ealpha-pV->Zalpha));
pV->EstIbeta = _IQmpy(pV->Fsmopos,pV->EstIbeta) + _IQmpy(pV->Gsmopos,(pV->Vbeta -pV->Ebeta -pV->Zbeta ));
/* Current errors */
pV->IalphaError = pV->EstIalpha - pV->Ialpha;
pV->IbetaError = pV->EstIbeta - pV->Ibeta;
/* Sliding control calculator */
/* pV->Zalpha=pV->IalphaError*pV->Kslide/pV->E0) where E0=0.5 here*/
pV->Zalpha = _IQmpy(IQsat(pV->IalphaError,pV->E0,-pV->E0),_IQmpy2(pV->Kslide));
pV->Zbeta = _IQmpy(IQsat(pV->IbetaError ,pV->E0,-pV->E0),_IQmpy2(pV->Kslide));
/* Sliding control filter -> back EMF calculator */
pV->Ealpha = pV->Ealpha + _IQmpy(pV->Kslf,(pV->Zalpha-pV->Ealpha));
pV->Ebeta = pV->Ebeta + _IQmpy(pV->Kslf,(pV->Zbeta -pV->Ebeta));
}
void SMO_Pare_init(void ) // 电机参数初始化
{
SMO_MotorPare.Rs = 0.821;
SMO_MotorPare.Ls = 0.00758;
SMO_MotorPare.Ib = 6 ;
SMO_MotorPare.Vb = 14 ;
SMO_MotorPare.Ts = 0.00008;
SMO_MotorPare.POLES=4;
SMO_MotorPare.BASE_FREQ=135;
SMO_MotorPare.Fsmopos = exp((-SMO_MotorPare.Rs/SMO_MotorPare.Ls)*(SMO_MotorPare.Ts));
SMO_MotorPare.Gsmopos = (SMO_MotorPare.Vb/SMO_MotorPare.Ib)*(1/SMO_MotorPare.Rs)*(1-SMO_MotorPare.Fsmopos);
Angle_SMOPare.Fsmopos = (int32_t)( SMO_MotorPare.Fsmopos*32768);
Angle_SMOPare.Gsmopos = (int32_t)( SMO_MotorPare.Gsmopos*32768);
Angle_SMOPare.Kslide = 4500 ; //
Angle_SMOPare.Kslf =1000; //
Angle_SMOPare.E0= 32670 ; //
Speed_estPare.SpeedK1=355;
Speed_estPare.SpeedK2=669;
Speed_estPare.speed_coeff=(500*60)/(SMO_MotorPare.POLES ); // 2毫秒计算一次角度差值 1000/2ms=500 =7500
}
// 电机在2ms时间计算角度变化量。即是公式:
// Speed_estPare.Speed_ele_angleIQ =Speed_estPare.ele_angleIQ -Speed_estPare.old_ele_angleIQ
// 防止超过65535和小于0,把差值一阶滤波,插值变化量乘系数就可以得到速度。
// 速度信号的计算可以简单根据转位置的步进角计算或者直接根据角度在一定周期内的变化量计算
// 其中移位16是把角度变化量归1的一个系数,变化角度/360度,在乘一个系数得到速度,
// 可以通过示波器测量一个霍尔周期时间来计算。
// 假设一个霍尔周期时间15ms,电机极对数为4,速度RPM=1/T*60/p=1000/15*60/4=1000rpm
// 然后看在线看角度变化量(或者通讯发出来),速度RPM=变化量/65535*K=1000,求得系数K。
// 系数 :Speed_estPare.speed_coeff
void SMO_Speedcale(void) // 2ms执行一次
{
Speed_estPare.ele_angleIQ= IQAtan_Pare.IQAngle;
Speed_estPare.Speed_ele_angleIQ =Speed_estPare.ele_angleIQ- Speed_estPare.old_ele_angleIQ ;
//如果速度估计值为负数,则加上一个周期的角度(65536)来获得正数表示的速度值
if( Speed_estPare.Speed_ele_angleIQ <0)
Speed_estPare.Speed_ele_angleIQ+=65536;
//通过速度滤波器计算平滑的速度估计值
Speed_estPare.Speed_ele_angleIQFitter= _IQ10mpy(Speed_estPare.SpeedK2, Speed_estPare.Speed_ele_angleIQFitter)+_IQ10mpy(Speed_estPare.SpeedK1, Speed_estPare.Speed_ele_angleIQ);
//转换成电机的旋转速度值Speed_RPM 这个是系数角度计算系数speed_coeff
Speed_estPare.Speed_RPM = (Speed_estPare.Speed_ele_angleIQ*Speed_estPare.speed_coeff)>>16; // 最大角度 2pi是一圈 65536
//对转速值进行限制。如果转速值超过3000 RPM,则将转速值设为0
if( Speed_estPare.Speed_RPM>=3000)
Speed_estPare.Speed_RPM=0;
Speed_estPare.old_ele_angleIQ = Speed_estPare.ele_angleIQ ;
}
SMO.h
#ifndef Sensorless_SMO_H
#define Sensorless_SMO_H
#include "IQ_math.h"
#include "stm32f10x.h"
#include "math.h"
typedef struct {
int32_t Valpha; //二相静止坐标系alpha-轴电压
int32_t Ealpha; //二相静止坐标系alpha-轴反电动势
int32_t Zalpha; //alfa轴滑膜观测器的z平面
int32_t Gsmopos; //滑膜常数1
int32_t EstIalpha; //滑膜估算alpha-轴电流
int32_t Fsmopos; //滑膜常数2
int32_t Vbeta; //二相静止坐标系beta-轴电压
int32_t Ebeta; //二相静止坐标系beta-轴反电动势
int32_t Zbeta; //beta轴滑膜观测器的z平面
int32_t EstIbeta; //滑膜估算beta-轴电流
int32_t Ialpha; //二相静止坐标系alpha-轴电流
int32_t IalphaError; //二相静止坐标系beta-轴电流误差
int32_t Kslide; //滤波器系数
int32_t Ibeta; //二相静止坐标系beta-轴电流
int32_t IbetaError; //二相静止坐标系beta-轴电流误差
int32_t Kslf; //滤波器系数
int32_t E0; //滑膜的电流误差的限幅值 0.5
} Angle_SMO, *p_Angle_SMO;
#define Angle_SMO_DEFAULTS {0,0,0,0,0,0,0,0,0,0,0,0} // 初始化参数
typedef struct {
int32_t Speed_ele_angleIQ; //速度电角度值(计算速度)
int32_t old_ele_angleIQ; // 电机历史电角度
int32_t ele_angleIQ; // 电机电角度
int32_t Speed_ele_angleIQFitter; //速度电角度值(计算速度)
uint16_t Speed_RPM; //电机旋转速度
uint32_t speed_coeff; //计算速度的系数
uint16_t SpeedK1; // 速度滤波系数K1
uint16_t SpeedK2; // 速度滤波系数K2
}Speed_est;
#define Speed_est_DEFAULTS {0,0,0,0,0,0,0,0} // 初始化参数
typedef struct{
float Rs; //电机的相电阻
float Ls; //电机的相电感
float Ib; //电机控制器的基本相电流
float Vb; //电机控制器的基本相电压
float Ts; //采样周期
uint32_t POLES; // 电机的极对数
uint32_t BASE_FREQ; // 电机控制器的基本频率
float Fsmopos; //滑膜常数1
float Gsmopos; //滑膜常数2
}SMO_Motor;
#define SMO_Motor_DEFAULTS {0.0,0.0,0.0,0.0,0.0,0,0,0.0,0.0} // 初始化参数
void Angle_Cale(p_Angle_SMO pV); //滑膜电机位置电角度计算
void SMO_Pare_init (void ); // 滑膜观测器的参数初始化
void SMO_Speedcale(void) ; // 滑膜的角度计算速度函数
#endif /* Sensorless_SMO*/