在STM32上实现FuzzyPID(理论与代码实现)

在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

  • 13
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
stm32实现fuzzy PID(模糊PID)控制算法,首先我们需要了解fuzzy PID理论和算法,然后将其应用到stm32的开发环境中。 模糊PID控制算法是将PID控制算法与模糊逻辑相结合,以提高控制系统的性能和鲁棒性。它使用模糊化输入和输出,定义了模糊规则来调整PID参数,从而使控制系统的响应更加适应不确定性和非线性。具体步骤如下: 1. 模糊化输入:将输入信号(例如误差和误差变化率)通过模糊化函数转换成模糊量(例如偏差程度和变化程度的模糊量)。 2. 模糊规则库:建立模糊规则库,将输入的模糊量与输出的模糊量相对应,形成一个规则表。 3. 模糊推理:根据规则库,通过模糊推理方法得出模糊的输出量。 4. 解模糊化:将模糊输出量通过解模糊化函数转换为精确的PID控制参数。 5. PID控制:使用得到的PID参数进行控制。 在stm32实现fuzzy PID控制算法,我们可以按照以下步骤进行: 1. 建立fuzzy PID控制的规则库,包含输入模糊量和输出模糊量之间的对应关系。这个规则库可以在代码中以表格或数组的形式定义。 2. 定义模糊化函数和解模糊化函数,将输入信号模糊化为模糊量,以及将模糊输出量解模糊为精确的PID控制参数。 3. 获取输入信号,并通过模糊化函数将其转换为模糊量。 4. 根据规则库和输入的模糊量,进行模糊推理,得到模糊的输出量。 5. 将模糊输出量通过解模糊化函数转换为精确的PID控制参数。 6. 使用得到的PID参数进行控制,并更新输出信号。 以上是在stm32实现fuzzy PID控制算法的基本步骤和原理,具体代码实现会涉及到stm32的编程和相关库函数的使用,可以参考stm32的开发手册和相关资料进行具体的编写和调试工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值