在STM32上实现FuzzyPID(代码详解与实现)–以温控为例
资源下载:https://download.csdn.net/download/weixin_39092315/19524894(已更新带.h)
1.前言
模糊PID已经在实际生活当中有应用了,至于它是否真的比传统PID要好,各位就自行判断。本文基于博主做的项目中的经验总结而成,借助代码一步步推理至实现。有不错的控温效果,精度很高,但耗时挺长。
2.实现步骤
2.1输入量的量化与模糊化
在温度控制中,能够得到的数据就是温差(Error)和温差变化率(iError),所以首先确定我们的输入有两个:Error、iError。模糊PID的特点就是模糊,我们将确切的输入进行量化,就是模糊的第一步。量化就是通过量化函数将输入映射到几个数字级别,一般都是相对于0对称的数字区间。具体投射到怎样的区间根据实际情况而定。
举个例子:温控器件工作温度是25c°,目标常控温度为20c°,那么输入数据的范围为:±5c°,又由于温控器件温度变化率最大为±0.3(变化率的大小需要实际测定,具体与每周期采样时间有关)。那么,我们需要设置量化函数的两个分母为:5与0.3,因此在温控过程中,温差逐渐减少,所以量化值Error/MaxE的值随着温差减少而减小,能够表征温控当前温度与目标温度的差距(方便减小P控制和增大I控制,细品)。
代码用的是±6.
//输入值的量化论域(-6->6)
static void LinearQuantization(FUZZYPID *vPID,float _Real_Value,float *qValue)
{
float thisError;
float deltaError;
thisError=vPID->setVaule-_Real_Value; //计算当前偏差
deltaError=thisError-vPID->lasterror; //计算偏差增量
//E和EC的量化
qValue[0]=6.0*thisError/(vPID->maximum-vPID->minimum);
qValue[1]=3.0*deltaError/(vPID->maximum-vPID->minimum);
// printf("qValue[0]:%f\r\n,qValue[1]:%f\r\n",qValue[0],qValue[1]);
}
2.2规则库
#define NB -6
#define NM -4
#define NS -1
#define ZO 0
#define PS 1
#define PM 4
#define PB 6
//规则库
static const float ruleKp[7][7]={
PB, PB, PM, PM, PS, PS, ZO,
PB, PB, PM, PM, PS, ZO, ZO,
PM, PM, PM, PS, ZO, NS, NM,
PM, PS, PS, ZO, NS, NM, NM,
PS, PS, ZO, NS, NS, NM, NM,
ZO, ZO, NS, NM, NM, NM, NB,
ZO, NS, NS, NM, NM, NB, NB
};
static const float ruleKi[7][7]={
NB, NB, NB, NM, NM, ZO, ZO,
NB, NB, NM, NM, NS, ZO, ZO,
NM, NM, NS, NS, ZO, PS, PS,
NM, NS, NS, ZO, PS, PS, PM,
NS, NS, ZO, PS, PS, PM, PM,
ZO, ZO, PS, PM, PM, PB, PB,
ZO, ZO, PS, PM, PB, PB, PB
};
static const float ruleKd[7][7]={
PS, PS, ZO, ZO, ZO, PB, PB,
NS, NS, NS, NS, ZO, NS, PM,
NB, NB, NM, NS, ZO, PS, PM,
NB, NM, NM, NS, ZO, PS, PM,
NB, NM, NS, NS, ZO, PS, PS,
NM, NS, NS, NS, ZO, PS, PS,
PS, ZO, ZO, ZO, ZO, PB, PB
};
```
由代码可知,分7个等级,成3个表格,表格的正中心表示温控达到目标温度且变化率为0;表格左上方表示温差处于负的大值,且误差变化率处于负的大值,此时温控处于快速接近目标温度的误差较大期(假设输入为负且误差为负是系统开始时的输入),所以大家可以仔细分析表格不同位置所蕴含的系统当前所处状态,在中点附近,同一个位置可以有两种不同的解释(制冷or加热)
注:上述表格是指输入数据的隶属度的投影,横坐标为变化率从左到右为负大到正大,纵坐标为误差变化率从上到下为负大到正大。
2.3隶属度函数
//隶属度计算函数
static void CalcMembership(float *ms,float qv,int * index)
{
if((qv>=NB)&&(qv<NM))
{
index[0]=0;
index[1]=1;
ms[0]=-0.5*qv-2.0; //y=-0.5x-2.0
ms[1]=0.5*qv+3.0; //y=0.5x+3.0
}
else if((qv>=NM)&&(qv<NS))
{
index[0]=1;
index[1]=2;
ms[0]=-0.5*qv-1.0; //y=-0.5x-1.0
ms[1]=0.5*qv+2.0; //y=0.5x+2.0
}
else if((qv>=NS)&&(qv<ZO))
{
index[0]=2;
index[1]=3;
ms[0]=-0.5*qv; //y=-0.5x
ms[1]=0.5*qv+1.0; //y=0.5x+1.0
}
else if((qv>=ZO)&&(qv<PS))
{
index[0]=3;
index[1]=4;
ms[0]=-0.5*qv+1.0; //y=-0.5x+1.0
ms[1]=0.5*qv; //y=0.5x
}
else if((qv>=PS)&&(qv<PM))
{
index[0]=4;
index[1]=5;
ms[0]=-0.5*qv+2.0; //y=-0.5x+2.0
ms[1]=0.5*qv-1.0; //y=0.5x-1.0
}
else if((qv>=PM)&&(qv<=PB))
{
index[0]=5;
index[1]=6;
ms[0]=-0.5*qv+3.0; //y=-0.5x+3.0
ms[1]=0.5*qv-2.0; //y=0.5x-2.0
}
}
不多说,代入几个特殊数字就知道什么意思了:例如0, 0.5 2.5等,就可以知道隶属度是指某个值属于它附近两个等级的程度(1显而易见的属于0与1等级),这里需要分别计算误差和误差变化率的隶属度。
2.4模糊推理
实际上,2.3的隶属度计算已经实现了模糊推理的功能,将隶属度分别算好之后,我们已经知道了四个等级所对应的隶属度大小,可以在表格上确定四个值(这里的值指的是PID三个参数),而输入值的量化等级(各两个等级)*它们对应的四个值(PID),就完成了模糊推理到解模糊
2.5解模糊
//采用重心法计算pid增量值
pidvalue[0]=msE[0]*(msEC[0]*ruleKp[indexE[0]][indexEC[0]]+msEC[1]*ruleKp[indexE[0]][indexEC[1]])
+msE[1]*(msEC[0]*ruleKp[indexE[1]][indexEC[0]]+msEC[1]*ruleKp[indexE[1]][indexEC[1]]);
pidvalue[1]=msE[0]*(msEC[0]*ruleKi[indexE[0]][indexEC[0]]+msEC[1]*ruleKi[indexE[0]][indexEC[1]])
+msE[1]*(msEC[0]*ruleKi[indexE[1]][indexEC[0]]+msEC[1]*ruleKi[indexE[1]][indexEC[1]]);
pidvalue[2]=msE[0]*(msEC[0]*ruleKd[indexE[0]][indexEC[0]]+msEC[1]*ruleKd[indexE[0]][indexEC[1]])
+msE[1]*(msEC[0]*ruleKd[indexE[1]][indexEC[0]]+msEC[1]*ruleKd[indexE[1]][indexEC[1]]);
这段代码包括了模糊推理与解模糊两个步骤,配合2.4看,同时别忘了代入具体值计算,有助于理解。
3总结
模糊PID的思想很有意思,但在实际应用中是否能得到真正有效的应用,就需要结合自己项目的实际去完成表格的调整,输入输出正负号、以及当前系统状态等等,这都是需要在实验中一步步去调试才能得到最终适合自己的那个结果。
若有读取温度曲线、stm32串口以及在stm32上实现FreeRTOS的需要,请点击下列文章。
MATLAB的温度曲线串口处理脚本与实时画图小白
1.https://blog.csdn.net/weixin_39092315/article/details/116334084
STM32F103C8T6+FreeRTOS+USART1、3
2.https://blog.csdn.net/weixin_39092315/article/details/116329689
STM32F103C8T6的USB虚拟串口实现
3.https://blog.csdn.net/weixin_39092315/article/details/108249478
STM32的HAL库实现定时器TIM6和计算方法
4.https://blog.csdn.net/weixin_39092315/article/details/115432035
初识STM32与其选型
5.https://blog.csdn.net/weixin_39092315/article/details/115432035
STM32F103C8T6及其系列的FreeRTOS移植
6.https://blog.csdn.net/weixin_39092315/article/details/108343954