目录
前面
滑膜速度控制器
控制器所处位置
理论设计
模型搭建
滑膜观测器
基本原理
反正切函数
锁相环
滑膜观测器模型(反正切)
滑膜观测器C代码实现
SMO.c
SMO.h
前面
滑膜常见用处有两个:
1、作为滑膜控制器SMC,对速度进行直接控制
2、作为滑膜观测器SMO,获取电机角度与转速信息
滑膜速度控制器
SMC叫滑膜控制(Sliding Mode Contral)
三相PMSM是一个非线性、强耦合的多变量控制系统,对于外界的扰动或者电机自身的参数发生变化时,传统的PI控制并不能满足实际的要求。因此可以引入滑模控制SMC,它对扰动和参数不敏感,响应速度也够快。
控制器所处位置
该模型在整个控制系统中的位置:
输入是:参考转速与实际转速的误差。
输出是:Iq轴PI调节的输入。
理论设计
滑模控制其设计如下:
重点关注最后一个公式就可以。
模型搭建
公式可以转换为模型:
其中这三个属于滑模控制器关键参数:
转速:0.2秒时加载,可快速恢复到参考转速值1000。
电磁转矩
滑膜观测器
SMO叫滑膜观测器(Sliding Mode Observer),用于获取转子位置信息与转速信息。
在整个控制系统中所处的位置:
基本原理
该方法基于给定电流与反馈电流之间的误差来设计滑膜观测器,并通过该误差重构电机的反电动势,估算转子位置。
简单来说就是,滑膜观测器就是通过采样与坐标变换得到的Ualpha,Ubeta,Ialpha,Ibeta四个参数值,获取扩展反电动势Ealpha、Ebeta的值。
之后则是需要想办法通过反电动势值,来获取转子的位置角θ:常见办法有反正切函数、PLL锁相环。同理也可同时获得转速估计值。
反正切函数
转子的位置角:
转速估计值:
锁相环
滑膜观测器模型(反正切)
整体模型:
滑膜观测器总模型:
滑膜观测器获取反电动势模型:
反正切函数模型获取转子位置与速度信息:
转子位置 实际值与估计值:
转子速度 实际值与估计值:
滑膜观测器C代码实现
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 ;
}
//===========================================================================
// No more.
//===========================================================================
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*/