串级PID控制算原理及法详解

文章目录

1. PID

2. 串级PID

3. 串级PID的物理量

4. C语言实现单极PID

5. C语言实现串极PID

6. 模拟仿真


1. PID

PID是应用最广泛的闭环控制方法之一,是一种常用的反馈控制方法,对于每个PID控制器由三个部分组成:比例控制(Proportional)、积分控制(Integral)和微分控制(Derivative)。

PID三个环节的作用

由控制无人机案例我们可以总结出PID三个环节各自的主要作用和效应:

  • 比例环节:起主要控制作用,使反馈量向目标值靠拢,但可能导致振荡。

  • 积分环节:消除稳态误差,但会增加超调量。

  • 微分环节:产生阻尼效果,抑制振荡和超调,但会降低响应速度。

对于单环PID的控制算原理及法详解可以看下面这篇文章:

PID原理及控制算法详解-CSDN博客

2. 串级PID

串级PID控制是一种高级控制策略,通过使用两个(或更多)PID控制器来提高系统的稳定性和抗干扰能力。在串级控制中,外环控制器的输出作为内环控制器的设定值。图片中的示例详细解释了这种控制策略在四轴飞行器中的应用。

为什么要用串级PID?

表面上看,单一的PID控制器好像已经足够了,只要能够给出反馈,控制相应的物理量就可以了。但是,在一些复杂的系统中,单一的PID控制器可能无法满足控制需求。这时,就需要使用串级PID控制器来提高控制性能。

当进行无人机的调试时,可能会发现一个问题,如果无人机的高度与目标高度之间的距离较远的话,无人机在运动过程中的速度会很快,会导致较大的超调,而且不论怎么修改参数都很难让系统稳定。

这时如果运动过程中的速度没这么快就好了,这样就不会产生过冲了,这就要用到串级PID了。

在上一篇PID文章中所说的算法其实就是单级PID,目标值和反馈值经过一次PID计算就得到输出值并直接作为控制量,但如果目标物理量和输出物理量之间不止差了一阶的话,中间阶次的物理量我们是无法控制的。比如:目标物理量是位置,输出物理量是加速度,则无人机的速度是无法控制的。

而串级PID就可以改善这一点。串级PID其实就是两个单级PID“串”在一起组成的,它的框图如下:

图中的外环和内环就分别是一个单级PID,每个单级PID就如我们之前所说,需要获取一个目标值和一个反馈值,然后产生一个输出值。串级PID中两个环相“串”的方式就是将外环的输出作为内环的目标值。 

小车上坡的类比

  • 单环PID的输出速度V不一定是真实的速度V,因此需要在内环再加上速度环PID,构成串级PID控制。
  • 外环控制位置,输出值是小车的理论速度,内环控制速度,输入是小车的理论速度,希望尽可能的使输出为理论速度。

四轴飞行器的控制

  • 外环为角度环,输出的是期望达到该角度所需的PWM(也可以理解为角速度和PWM的映射)。
  • 内环为角速度环,输入是期望的角速度和自身真实的角速度,输出为最终的PWM(角速度)。

串级PID控制的具体实现

  • 角度环PID控制器

    • 目标是控制四轴飞行器的角度。
    • 输入:期望角度和当前角度。
    • 输出:期望角速度(角度环PID输出值)。
  • 角速度环PID控制器

    • 目标是实现期望的角速度。
    • 输入:期望角速度和当前角速度。
    • 输出:控制电机的PWM信号。

3. 串级PID的物理量

在串级PID控制系统中,有三个输入和一个输出,且被控对象需要提供两个反馈量。我们以小球控制为例,来解释这些物理量的设置。

无人机控制案例中的串级PID设计

  1. 目标值:目标值是我们希望无人机达到的位置高度。

  2. 外环反馈:外环反馈量是无人机的实时高度位置。

  3. 内环反馈:内环反馈量是无人机的实时上升速度。

  4. 输出值:输出值是施加在无人机上的推力。

外环PID控制器

  • 输入:目标高度位置和当前实际高度位置的差值(位置误差)。
  • 输出:目标上升速度。

内环PID控制器

  • 输入:目标上升速度和当前实际上升速度的差值(速度误差)。
  • 输出:控制推力。

被控对象(无人机)

  • 输入:推力。
  • 输出:无人机的上升速度和高度位置。

具体流程

目标位置

  • 系统的目标是让无人机达到指定的高度位置。

外环PID控制器

  • 外环PID控制器接收目标高度位置和当前实际高度位置,计算出位置误差。
  • 根据位置误差,外环PID控制器计算出目标上升速度。

内环PID控制器

  • 内环PID控制器接收目标上升速度和当前实际上升速度,计算出速度误差。
  • 根据速度误差,内环PID控制器计算出需要施加的推力。

无人机

  • 施加推力后,无人机的上升速度和高度位置发生变化。
  • 实际上升速度和高度位置反馈回内环和外环控制器,形成闭环控制。

在无人机控制中,内环与无人机的速度控制形成一个闭环系统,PID内环负责无人机的速度控制;而外环与内环和无人机一起构成了一个位置控制系统,外环负责位置控制。总的来说,外环根据无人机位置误差计算出无人机需要达到的速度,而内环负责计算控制推力使无人机达到这个目标速度,两个环协同工作,就可以完成任务。

之前我们说到,使用串级PID控制后,我们可以对无人机的上升速度进行控制。那么,如何进行控制呢?其实就是对外环PID的输出进行限幅。因为外环PID输出的是目标速度,限制外环输出相当于限制了无人机目标速度的最大值,内环也就会维持无人机的上升速度不超过这个最大值。

在使用串级PID后,无人机的表现会有以下改变:

平稳的上升过程

  • 无人机不再像之前那样“着急”地向目标高度冲去,而是以近似匀速的方式上升,最终平稳地到达目标高度。

限幅作用

  • 由于高度误差较大,外环输出在大部分时间都处于限幅的最大值,这意味着无人机的上升速度被限制在一个安全的范围内,不会过快导致超调。
  • 内环PID则根据这个限幅的目标速度调整推力,使无人机平稳上升。

减少超调

  • 由于外环限制了目标速度,内环使无人机的速度变化缓慢,因此几乎没有超调。无人机的速度变化慢了,控制更加平稳。

控制位置和速度

  • 通过串级PID控制,我们不仅能精确控制无人机的高度位置,还能控制其上升速度,达到双重控制的效果。

4. C语言实现单极PID

这段代码实现了一个简单的单极PID控制器。PID控制器由三个部分组成:比例(P)、积分(I)和微分(D)。

#include <stdio.h>// 定义PID结构体用于存放一个PID的数据
typedef struct
{float kp, ki, kd;        // 三个系数:比例、积分和微分float error, lastError;  // 当前误差、上次误差float integral, maxIntegral;  // 积分、积分限幅float output, maxOutput; // 输出、输出限幅
} PID;// 用于初始化PID参数的函数
void PID_Init(PID *pid, float p, float i, float d, float maxI, float maxOut)
{pid->kp = p;  // 设置比例系数pid->ki = i;  // 设置积分系数pid->kd = d;  // 设置微分系数pid->maxIntegral = maxI;  // 设置积分限幅pid->maxOutput = maxOut;  // 设置输出限幅pid->error = 0;pid->lastError = 0;pid->integral = 0;pid->output = 0;
}// 进行一次PID计算
// 参数为(pid结构体, 目标值, 反馈值),计算结果放在pid结构体的output成员中
void PID_Calc(PID *pid, float reference, float feedback)
{// 更新数据pid->lastError = pid->error;  // 将旧error存起来pid->error = reference - feedback;  // 计算新error// 计算微分项float dout = (pid->error - pid->lastError) * pid->kd;// 计算比例项float pout = pid->error * pid->kp;// 计算积分项pid->integral += pid->error * pid->ki;// 积分限幅if (pid->integral > pid->maxIntegral) pid->integral = pid->maxIntegral;else if (pid->integral < -pid->maxIntegral) pid->integral = -pid->maxIntegral;// 计算输出pid->output = pout + dout + pid->integral;// 输出限幅if (pid->output > pid->maxOutput) pid->output = pid->maxOutput;else if (pid->output < -pid->maxOutput) pid->output = -pid->maxOutput;
}// 模拟设定执行器输出大小的函数
void setActuatorOutput(float output)
{// 这里是将PID的输出值应用到执行器上的代码// 在实际应用中,这可能是一个控制电机速度、阀门开度等的函数printf("Actuator Output: %f\n", output);
}// 模拟获取反馈值的函数
float getFeedbackValue()
{// 这里是获取系统当前反馈值的代码// 在实际应用中,这可能是从传感器读取的值// 这里暂时返回一个模拟值static float feedback = 0;feedback += 1;  // 模拟反馈值增加return feedback;
}// 模拟获取目标值的函数
float getTargetValue()
{// 这里是获取系统目标值的代码// 在实际应用中,这可能是从用户输入或者其他系统计算得到的// 这里暂时返回一个固定目标值return 100;
}int main()
{PID mypid = {0};  // 创建一个PID结构体变量// 初始化PID参数:比例系数10,积分系数1,微分系数5,最大积分800,最大输出1000PID_Init(&mypid, 10, 1, 5, 800, 1000);while (1) // 进入循环运行{float feedbackValue = getFeedbackValue();  // 获取被控对象的反馈值float targetValue = getTargetValue();  // 获取目标值PID_Calc(&mypid, targetValue, feedbackValue);  // 进行PID计算,结果在output成员变量中setActuatorOutput(mypid.output);  // 将PID输出应用到执行器// 模拟延时,这里使用sleep函数,单位为秒// 在实际应用中,这个值根据系统需求调整sleep(1);  // 等待1秒再开始下一次循环}return 0;
}

定义PID结构体

  • 存放PID控制器的参数和状态,包括比例、积分、微分系数,当前和上次误差,积分值和积分限幅,输出值和输出限幅。

初始化PID参数的函数

  • 初始化PID结构体的参数。

进行一次PID计算的函数

  • 计算比例、积分和微分项,并对积分和输出进行限幅,更新PID输出值。

模拟设定执行器输出大小的函数

  • 打印PID控制器的输出值。在实际应用中,这将是控制执行器的代码。

模拟获取反馈值的函数

  • 返回一个模拟的反馈值。在实际应用中,这将是从传感器获取的反馈值。

模拟获取目标值的函数

  • 返回一个模拟的目标值。在实际应用中,这将是用户输入或其他系统计算得到的目标值。

主程序

  • 初始化PID参数,进入一个无限循环,获取反馈值和目标值,进行PID计算,将PID输出应用到执行器,并等待一段时间再进行下一次循环。

5. C语言实现串极PID

串级PID的调试

在编写代码时,PID的调参的顺序是先调整内环参数,内环控制效果达到理想效果后,再调整外环参数。

下面的代码实现了一个串级PID控制系统,通过两个单级PID控制器分别控制系统的不同部分(内环和外环)。

外环PID控制器计算出目标速度,内环PID控制器根据目标速度计算出实际控制量。

这种结构可以提高系统的稳定性和响应速度,适用于复杂控制系统,如无人机高度和速度控制。

#include <stdio.h>// 定义PID结构体用于存放一个PID的数据
typedef struct
{float kp, ki, kd;        // 三个系数:比例、积分和微分float error, lastError;  // 当前误差、上次误差float integral, maxIntegral;  // 积分、积分限幅float output, maxOutput; // 输出、输出限幅
} PID;// 用于初始化PID参数的函数
void PID_Init(PID *pid, float p, float i, float d, float maxI, float maxOut)
{pid->kp = p;  // 设置比例系数pid->ki = i;  // 设置积分系数pid->kd = d;  // 设置微分系数pid->maxIntegral = maxI;  // 设置积分限幅pid->maxOutput = maxOut;  // 设置输出限幅pid->error = 0;pid->lastError = 0;pid->integral = 0;pid->output = 0;
}// 进行一次PID计算
// 参数为(pid结构体, 目标值, 反馈值),计算结果放在pid结构体的output成员中
void PID_Calc(PID *pid, float reference, float feedback)
{// 更新数据pid->lastError = pid->error;  // 将旧error存起来pid->error = reference - feedback;  // 计算新error// 计算微分项float dout = (pid->error - pid->lastError) * pid->kd;// 计算比例项float pout = pid->error * pid->kp;// 计算积分项pid->integral += pid->error * pid->ki;// 积分限幅if (pid->integral > pid->maxIntegral) pid->integral = pid->maxIntegral;else if (pid->integral < -pid->maxIntegral) pid->integral = -pid->maxIntegral;// 计算输出pid->output = pout + dout + pid->integral;// 输出限幅if (pid->output > pid->maxOutput) pid->output = pid->maxOutput;else if (pid->output < -pid->maxOutput) pid->output = -pid->maxOutput;
}// 一直到这里,前面的都是单极PID的代码// 串级PID的结构体,包含两个单级PID
typedef struct
{PID inner; // 内环PID outer; // 外环float output; // 串级输出,等于inner.output
} CascadePID;// 串级PID的计算函数
// 参数(PID结构体, 外环目标值, 外环反馈值, 内环反馈值)
void PID_CascadeCalc(CascadePID *pid, float outerRef, float outerFdb, float innerFdb)
{PID_Calc(&pid->outer, outerRef, outerFdb); // 计算外环PID_Calc(&pid->inner, pid->outer.output, innerFdb); // 计算内环pid->output = pid->inner.output; // 内环输出就是串级PID的输出
}// 模拟设定执行器输出大小的函数
void setActuatorOutput(float output)
{// 这里是将PID的输出值应用到执行器上的代码// 在实际应用中,这可能是一个控制电机速度、阀门开度等的函数printf("Actuator Output: %f\n", output);
}// 模拟获取反馈值的函数
float getFeedbackValue()
{// 这里是获取系统当前反馈值的代码// 在实际应用中,这可能是从传感器读取的值// 这里暂时返回一个模拟值static float feedback = 0;feedback += 1;  // 模拟反馈值增加return feedback;
}// 模拟获取目标值的函数
float getTargetValue()
{// 这里是获取系统目标值的代码// 在实际应用中,这可能是从用户输入或者其他系统计算得到的// 这里暂时返回一个固定目标值return 100;
}CascadePID mypid = {0}; // 创建串级PID结构体变量int main()
{// ...其他初始化代码// 初始化内环参数:比例系数10,积分系数0,微分系数0,最大积分0,最大输出1000PID_Init(&mypid.inner, 10, 0, 0, 0, 1000);// 初始化外环参数:比例系数5,积分系数0,微分系数5,最大积分0,最大输出100PID_Init(&mypid.outer, 5, 0, 5, 0, 100);while (1) // 进入循环运行{float outerTarget = getTargetValue(); // 获取外环目标值float outerFeedback = getFeedbackValue(); // 获取外环反馈值float innerFeedback = getFeedbackValue(); // 获取内环反馈值PID_CascadeCalc(&mypid, outerTarget, outerFeedback, innerFeedback); // 进行PID计算setActuatorOutput(mypid.output); // 设定执行器输出大小// 模拟延时,这里使用sleep函数,单位为秒// 在实际应用中,这个值根据系统需求调整sleep(1); // 等待1秒再开始下一次循环}return 0;
}

6. 模拟仿真

下面这个网站可以模拟调节PID参数来控制无人机

Webpack App

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

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

相关文章

自然语言处理——英文文本预处理

高质量数据的重要性 数据的质量直接影响模型的性能和准确性。高质量的数据可以显著提升模型的学习效果&#xff0c;帮助模型更准确地识别模式、进行预测和决策。具体原因包括以下几点&#xff1a; 噪音减少&#xff1a;高质量的数据经过清理&#xff0c;减少了无关或错误信息…

Wp-scan一键扫描wordpress网页(KALI工具系列三十)

目录 1、KALI LINUX 简介 2、Wp-scan工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描已知漏洞 4.3 扫描目标主题 4.4 列出用户 4.5 输出扫描文件 4.6 输出详细结果 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

《梦醒蝶飞:释放Excel函数与公式的力量》6.1 DATE函数

6.1 DATE函数 第一节&#xff1a;DATE函数 1&#xff09;DATE函数概述 DATE函数是Excel中的一个内置函数&#xff0c;用于根据指定的年、月、日返回对应的日期序列号。这个函数非常有用&#xff0c;尤其是在处理日期数据时&#xff0c;它可以帮助你构建特定的日期&#xff0…

pycharm工具回退键调出

pycharm工具调出回退键。 View->Appearance->Toolbar,即可调出 调不出的可以使用快捷键&#xff1a;ctrlalt向左箭头 但是这个快捷键容易和电脑屏幕旋转冲突。可将电脑的快捷键关掉&#xff0c;即可。 ctrlalt向上箭头&#xff1a;将屏幕旋转到正常&#xff08;横向&am…

【面试干货】final、finalize 和 finally 的区别

【面试干货】final、finalize 和 finally 的区别 1、final1.1 修饰类1.2 修饰方法1.3 修饰变量 2、finally3、finalize4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java编程语言中&#xff0c;final、finalize和finally都是关键…

汽车免拆诊断案例 | 2016 款吉利帝豪EV车无法加速

故障现象 一辆2016款吉利帝豪EV车&#xff0c;累计行驶里程约为28.4万km&#xff0c;车主反映车辆无法加速。 故障诊断 接车后路试&#xff0c;行驶约1 km&#xff0c;踩下加速踏板&#xff0c;无法加速&#xff0c;车速为20 km/h左右&#xff0c;同时组合仪表上的电机及控制…

设备驱动框架之LED

文章目录 前言一、什么是驱动框架二、使用步骤1.注册LED设备2.卸载LED设备3.内核中申请内存4.container_of5.platform_get_drvdata 和 platform_set_drvdata6.module_platform_driver 三、驱动示例总结 前言 为了尽量降低驱动开发者难度以及接口标准化&#xff0c;就出现了设备…

面试-Java线程池

1.利用Excutors创建不同的线程池满足不同场景的需求 分析&#xff1a; 如果并发的请求的数量非常多&#xff0c;但每个线程执行的时间非常短&#xff0c;这样就会频繁的创建和销毁线程。如此一来&#xff0c;会大大降低系统的效率。 可能出现&#xff0c;服务器在为每个线程创建…

利用powershell开展网络钓鱼

要确保人们打开我们的恶意文件并执行它们&#xff0c;我们只需让微软努力工作多年来赢得人们的信任&#xff0c;然后将一些危险的宏插入到幻灯片中。 本博文将介绍如何通过屏幕顶部的一个友好的警告提示&#xff0c;在用户启用宏后立即运行您的宏。 首先&#xff0c;我们需要打…

浏览器扩展V3开发系列之 chrome.commands 快捷键的用法和案例

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 chrome.commands API 允许开发者使用快捷键来执行特定的命令。 在使用 chrome.commands API 之前必须…

Vue 学习之 axios

目录 执行安装命令&#xff1a;npm install axios 使用的时候导入 axios以data&#xff0c;params&#xff0c;headers传参方式的区别 axios封装 是一个基于 promise 的 网络请求库&#xff0c;作用于浏览器和 node.js 中。使用Axios可以在前端项目中发送各种方式的HTTP请求…

如何查看websocket连接信息

Chrome 浏览器中查看 webSocket 连接信息_谷歌浏览器看不到 websocket-CSDN博客 Getting Started — Flask-SocketIO documentation 运作原理 | Socket.IO

VS Code准备JAVA环境

背景 由于IntelliJ IDEA是需要激活码的,简单的java demo测试,除了可以直接使用命令行java和javac进行执行, 推荐使用VS code, 其功能比较强大,扩展插件也比丰富,对阅读和书写代码都是比较友好的. JDK环境准备 Linux JDK可以使用Open JDK 11. sudo apt-get install openjdk-1…

UE引擎实现ShadowMap、体积光(C++)

前言 整体上参考了YivanLee大佬的这两篇文&#xff1a; 虚幻4渲染编程&#xff08;灯光篇&#xff09;【第一卷&#xff1a;各种ShadowMap】 虚幻4渲染编程&#xff08;灯光篇&#xff09;【第二卷&#xff1a;体积光】 正文 1、ShadowMap &#xff08;1&#xff09;创建工…

【浦语开源】深入探索:大模型全链路开源组件 InternLM Lagent,打造灵笔Demo实战指南

一、准备工作&#xff1a; 1、环境配置&#xff1a; pip、conda换源&#xff1a; pip临时换源&#xff1a; pip install -i https://mirrors.cernet.edu.cn/pypi/web/simple some-package# 这里的“https://mirrors.cernet.edu.cn/pypi/web/simple”是所换的源&#xff0c;…

AI绘画Stable Diffusion人物背景替换实操教程,让创意无限延伸

大家好&#xff0c;我是画画的小强 Stable Diffusion以其强大的能力可以实现人物背景的更换。本文将带你深入了解如何利用Stable Diffusion中的Inpaint Anything插件快速且精准地实现人物背景的替换&#xff0c;从而让你的图片焕发新生。 前期准备 本文会使用到Inpaint Anyt…

观星观景大屏呈现 实时拍摄长焦定格 当当狸智能天文望远镜TW2来啦

《宇宙的奇迹》中有这样一句话&#xff1a;“我们与那些遥远星系息息相关&#xff0c;无论它们是如何与我们天各一方&#xff0c;那些经过数十亿年旅行到达地球的光线&#xff0c;终究会把我们联系在一起”。 想象一下—— 等到繁星低垂&#xff0c;月光皎洁之时&#xff0c;…

Linux系统安装和卸载nginx

&#x1f4d6;Linux系统安装和卸载nginx ✅下载✅安装✅启动nginx✅安装成系统服务✅常见问题&#xff1a;80端口被占用了✅卸载✅目录结构 以下介绍的是以源码编译安装方式&#xff1a; ✅下载 官方地址&#xff1a;https://nginx.org/en/download.html 123云盘地址&#x…

基于springboot、vue影院管理系统

设计技术&#xff1a; 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatisvue 工具&#xff1a;IDEA、Maven、Navicat 主要功能&#xff1a; 影城管理系统的主要使用者分为管理员和用户&#xff0c; 实现功能包括管理员&#xff1a; 首页…

ELK集群设置密码

一、软件安装清单 elasticsearch7.17.22logstash7.17.22kibana:7.17.22filebeat7.17.22elasticsearch-head:5 二、配置 生成证书 进入elasticsearch容器 bin/elasticsearch-certutil cert -out /usr/share/elasticsearch/config/elastic-certificates.p12 -pass将证书拷贝…