模糊PID控制算法实战讲解-案例温度控制(附C语言实现)

 可结合之前的文章一起理解:

控制算法-PID算法总结-从公式原理到参数整定解析(附C源码)_pid自整定算法-CSDN博客

模糊控制算法实战讲解-案例温度控制(附C语言实现)-CSDN博客 

 

目录

一、模糊PID控制的原理

1.1 模糊化

1.2 模糊规则库

1.3 模糊推理

1.4  去模糊化

1.5 PID控制输入计算

二、特点和应用场景

三、案例温度控制

简化版本:

加入重心法后的模糊PID版本:


模糊PID控制算法是将传统的PID控制与模糊逻辑控制相结合的一种控制策略。这种算法尝试通过模糊逻辑系统来自动调整PID控制器的参数(比例系数Kp​、积分系数Ki​、微分系数Kd​),以适应系统动态变化的需求,从而提高控制系统的性能。模糊PID控制在处理非线性、时变系统或者模型不完全已知的系统时尤其有效。

一、模糊PID控制的原理

传统的PID控制器根据偏差e(t)(期望输出与实际输出之间的差值)和偏差的变化率e1(t)来计算控制输入。PID控制器的输出由三部分组成:比例(P)、积分(I)和微分(D)项,计算公式为:

                               

在模糊PID控制中,系统利用模糊逻辑根据当前的偏差e(t)和偏差变化率e1(t)来动态调整Kp​、Ki​、Kd​的值,以适应系统的变化。

1.1 模糊化

将偏差e(t)和偏差变化率e1(t)的精确值转换为模糊值,这些模糊值对应于模糊集合中的语言变量,例如“正大”、“正小”、“零”、“负小”、“负大”。

1.2 模糊规则库

建立一个模糊规则库,这些规则基于专家知识或经验,描述了在特定偏差和偏差变化率的情况下如何调整PID参数。例如:如果偏差是正大,且变化率是正小,则增大比例系数Kp​。

1.3 模糊推理

根据模糊化的输入e(t)和e1(t))和模糊规则库,通过模糊推理得出每个PID参数的调整策略。

1.4  去模糊化

将模糊推理的结果转换为精确的PID参数值。

1.5 PID控制输入计算

使用调整后的PID参数计算控制输入u(t)

二、特点和应用场景

模糊PID控制器的主要优点是它结合了PID控制的直观性和模糊控制的适应性,能够在系统模型不完全已知或存在较大不确定性时提供良好的控制性能。控制更平稳。

应用场景:工业控制系统、机器人、汽车电子控制等领域

三、案例温度控制

考虑一个温度控制系统,其中模糊PID控制器用于调整加热器的功率输出,以维持设定的温度。根据温度偏差和偏差变化率的不同,模糊控制器会动态调整Kp​、Ki​、Kd​,以快速响应温度变化并减小超调,提高系统的稳定性和响应速度。

简化版本:

控制目标是使系统温度维持在一个设定值(比如25°C)。

PID参数(Kp​,Ki​,Kd​)需要根据温度偏差e(t)和偏差变化率e1(t)动态调整。

 PID控制器的结构体:

typedef struct {float Kp, Ki, Kd; // PID参数float integral;   // 积分项累计值float prev_error; // 上一次的偏差
} PIDController;

模糊规则:

void adjustPIDParams(PIDController* pid, float error, float delta_error) {// 假设根据偏差的大小和变化率调整PID参数// 这里的逻辑非常简化,实际应用中应该基于详细的模糊规则// 如果偏差大,增加Kp来快速减少偏差if (error > 5.0) pid->Kp += 0.1;else if (error < -5.0) pid->Kp -= 0.1;// 如果偏差变化快,增加Kd来减少超调if (delta_error > 0.5) pid->Kd += 0.05;else if (delta_error < -0.5) pid->Kd -= 0.05;// 保证PID参数在合理范围内if (pid->Kp < 0) pid->Kp = 0;if (pid->Kd < 0) pid->Kd = 0;
}

控制逻辑:

float computePIDOutput(PIDController* pid, float setpoint, float measured) {float error = setpoint - measured;float delta_error = error - pid->prev_error;// 简单的模糊逻辑调整PID参数adjustPIDParams(pid, error, delta_error);// 计算PID输出float output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * delta_error;// 更新状态pid->integral += error;pid->prev_error = error;return output;
}
int main() {PIDController pid = {0.1, 0.01, 0.05, 0, 0}; // 初始化PID参数和状态float setpoint = 25.0; // 目标温度float measured_temp = 20.0; // 测量温度,示例值// 模拟控制循环for (int i = 0; i < 100; ++i) {float control_signal = computePIDOutput(&pid, setpoint, measured_temp);// 应用control_signal到加热器...// 更新measured_temp...printf("Control Signal: %f\n", control_signal)

加入重心法后的模糊PID版本:

1)定义输入输出的模糊集合:

输入:温度误差e和误差变化率de

每个输入都可以定义为几个模糊集合,例如:负大(NB),负小(NS),零(ZE),正小(PS),正大(PB)。

输出:PID参数的调整量,包括ΔKpΔKiΔKd。输出也可以定义为类似的模糊集合。

 2)定义隶属度函数:

   对于每个模糊集合,定义一个隶属度函数来量化一个具体的输入值属于该模糊集合的程度。隶属度函数可以是三角形、梯形或是其他形状。

3)模糊规则

  • 基于经验或专家知识制定一组模糊规则,用于描述输入模糊集合之间的关系以及它们如何影响输出模糊集合。
  • 例如:“如果e是PB并且de是ZE,则ΔKp是PB”。

4)去模糊化

 使用重心法(或其他去模糊化方法)将模糊输出转换为一个具体的数值,用于调整PID参数。

 只考虑e的影响,以kp的变化量调整为例:

#include <stdio.h>// 示例:简化的隶属度计算函数
float calculateMembership(float value, float min, float max) {if (value <= min) return 0;else if (value >= max) return 1;else return (value - min) / (max - min);
}// 示例:计算ΔKp的重心
float calculateDeltaKp(float e, float de) {// 示例:隶属度值计算(这里仅为示例,实际情况下更复杂)float eNB = calculateMembership(e, -10, -5);float eNS = calculateMembership(e, -5, -2);float eZE = calculateMembership(e, -2, 2);float ePS = calculateMembership(e, 2, 5);float ePB = calculateMembership(e, 5, 10);// 示例:简化的模糊规则处理,假设只根据e的模糊集合调整Kpfloat deltaKp = (eNB * -2) + (eNS * -1) + (eZE * 0) + (ePS * 1) + (ePB * 2);float totalMembership = eNB + eNS + eZE + ePS + ePB;// 重心法去模糊化return totalMembership > 0 ? deltaKp / totalMembership : 0;
}int main() {float e = -3;  // 示例误差值float de = 0;  // 示例误差变化率float deltaKp = calculateDeltaKp(e, de);printf("Calculated ΔKp: %f\n", deltaKp);return 0;
}

考虑e和de影响:

#include <stdio.h>// 示例:隶属度计算函数
float calculateMembership(float value, float min, float max) {if (value < min) return 0;else if (value > max) return 1;else return (value - min) / (max - min);
}// 示例:根据e和de的模糊规则计算ΔKp
float calculateDeltaKp(float e, float de) {// 隶属度值计算float eNB = calculateMembership(e, -10, -5);float deNB = calculateMembership(de, -10, -5);float eNS = calculateMembership(e, -5, -2);float deNS = calculateMembership(de, -5, -2);float eZE = calculateMembership(e, -2, 2);float deZE = calculateMembership(de, -2, 2);float ePS = calculateMembership(e, 2, 5);float dePS = calculateMembership(de, 2, 5);float ePB = calculateMembership(e, 5, 10);float dePB = calculateMembership(de, 5, 10);float deltaKpValues[] = {-2, -1, 0, 1, 2}; // 对应NB, NS, ZE, PS, PB// 模糊规则处理float rule1Output = eNB * deNB  * deltaKpValues[0]; // float rule2Output = eNS * deNS * deltaKpValues[1]; // float rule3Output = eZE * deZE * deltaKpValues[2]; // 如果e和de都是ZE,则ΔKp保持不变float rule4Output = ePS * dePS  * deltaKpValues[3]; //float rule5Output = ePB * dePB * deltaKpValues[4]; //// 假设这是根据所有规则计算出的ΔKp总和float deltaKpTotal = rule1Output+rule2Output +rule3Output +rule4Output +rule5Output ; float totalMembership = eNB +deNB +eNS + deNS +eZE + deZE+ePB +dePB ; // 重心法去模糊化return totalMembership > 0 ? deltaKpTotal / totalMembership : 0;
}int main() {float e = -1;  // 示例误差值float de = 1;  // 示例误差变化率float deltaKp = calculateDeltaKp(e, de);printf("Calculated ΔKp: %f\n", deltaKp);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499492.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java009 - Java调试debugger

1、debugger概述 程序的调试工具&#xff0c;用于查看追踪程序的执行流程&#xff0c;也可以调试程序。 2、debugger调试流程 2.1 如何加断点 2.2 如何运行加了断点的程序 在代码区域右键---->debugger执行 2.3 看哪里 看console窗口 2.4 点哪里 点step into(F7)这个箭…

5个顶级AI训练数据提供商

人工智能革命极大地改变了世界&#xff0c;其影响遍及全球各个行业。 它改变了企业的典型运营方式&#xff0c;从而显着提高了生产力。 大多数公司已经使用或正在考虑某种形式的人工智能。 但为了让机器获得准确的结果&#xff0c;需要可以输入机器学习算法的高质量标记数据。…

HarmonyOS—开发云数据库

您可以在云侧工程下开发云数据库资源&#xff0c;包括创建对象类型、在对象类型中添加数据条目、部署云数据库。 创建对象类型 对象类型&#xff08;即ObjectType&#xff09;用于定义存储对象的集合&#xff0c;不同的对象类型对应的不同数据结构。每创建一个对象类型&#…

【软件测试】接口调不通排查分析+常遇面试题总结

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、接口调不通&am…

代码随想录算法训练营 Day29 | LeetCode491.递增子序列、LeetCode46.全排列、LeetCode47.全排列 II

LeetCode491.递增子序列 该题强调与之前的题目的不同在于给的数组顺序不能变换&#xff0c;这就导致了不能用used数组判断与前一个元素是否相同的方法进行去重的操作&#xff0c;因此该题加入了一个set&#xff0c;不和前一个元素比&#xff0c;而是判断之前有没有处理过这个值…

我是怎样看待 “祖传代码” (浅聊)

来感受一下压迫感吧~ 敬畏之心 程序员应该对祖传代码保有敬畏之心。这些代码库往往承载着公司的核心业务&#xff0c;是前人们花了无数心思&#xff0c;改了无数 bug 后的产物&#xff0c;同时也是公司的命脉所在。对于新加入的程序员来说&#xff0c;理解这些代码的结构、逻…

CentOS7——主机动态地址修改为静态地址

目录 1、查看本机的网络配置&#xff08;vmnet8网关&#xff09; 2、修改虚拟机主机网络信息配置文件 3、重启network服务使生效 4、测试 1、查看本机的网络配置&#xff08;vmnet8网关&#xff09; windows&#xff1a;“网络图标”——>“属性”——>“网络和共享中…

比亚迪领航新能源时代:汉唐传承,品牌力量

比亚迪&#xff0c;以中国文化的深度与自信&#xff0c;为新能源汽车领域注入强大动力。汉唐车型&#xff0c;不仅承载着中国古代文明的辉煌&#xff0c;更以其创新技术和环保理念&#xff0c;终结油电之争&#xff0c;让燃油车再次破防。作为销量冠军&#xff0c;比亚迪品牌的…

C语言基础18 循环

们可能需要多次执行同一块代码。一般情况下&#xff0c;语句是按顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了更为复杂执行路径的多种控制结构。 循环语句允许我们多次执行一个语句或语句组&#xff0…

zookeeper启动报错

启动zookeeper报错 从报错中可以看到 Invalid config, exiting abnormally 意思是&#xff1a;配置无效&#xff0c;异常退出 在往上看是没有zoo.cof这个配置文件 2024-02-27 14:47:03,285 [myid:] - ERROR [main:o.a.z.s.q.QuorumPeerMain99] - Invalid config, exiting…

(Linux学习二)文件管理基础操作命令笔记

Linux目录结构&#xff1a; bin 二进制文件 boot 启动目录 home 普通用户 root 超管 tmp 临时文件 run 临时运行数据 var 日志 usr 应用程序、文件 etc 配置文件 dev 文件系统 一、基础操作 在 Linux 终端中&#xff0c;你可以使用以下命令来清屏&#xff1a; clear 命令&am…

Mysql的储存引擎

储存引擎介绍 1. 文件系统 操作系统存取数据的一种机制 2. 文件系统类型 不管使用什么文件系统&#xff0c;数据内容不会变化 不同的是&#xff0c;存储空间、大小、速度 3. MySQL存储引擎 可以理解为&#xff0c;MySQL的“文件系统”&#xff0c;只不过功能更加强大 4. MySQL…