使用CCS软件查看PID曲线

news2024/11/25 12:40:23

  在刚开始学习PID的时候,都需要借助PID的曲线来理解比例,积分,微分这三个参数的具体作用。但是这些曲线生成一般都需要借助上位机软件或者在网页上才能实现。如果是在单片机上调试程序的话,想要看曲线,一般就是通过串口将数据发送出去,然后使用串口波形显示软化将曲线打印出来。
如果使用的是CCS软件来开发的话,那么就可以直接使用CCS软件自带的图形显示工具来打印曲线。
  比如要测试的代码如下:

typedef struct
{
	float P;
	float I;
	float D;
	float limit;
}PID;

typedef struct
{
	float Current_Error;			//当前误差
	float Last_Error;				//上一次误差
	float Previous_Error;			//上上次误差
}ERROR;
// 位置式PID
float PID_Realize(ERROR *err, PID *pid, float feedback, float reference)
{
	float iError, Realize;    						// 当前误差 实际输出

	iError = reference - feedback;					// 计算当前误差  期望值-当前值
	err->Current_Error += pid->I * iError;    		// 误差积分
	err->Current_Error = err->Current_Error > pid->limit ? pid->limit : err->Current_Error;	//积分限幅
	err->Current_Error = err->Current_Error < -pid->limit ? -pid->limit : err->Current_Error;

	Realize = pid->P * iError       				//比例P
	+ err->Current_Error    						//积分I
			+ pid->D * (iError - err->Last_Error);  //微分D

	err->Last_Error = iError;		  				// 更新上次误差
	return Realize;    								// 返回实际值
}

// 增量式PID
float PID_Increase(ERROR *err, PID *pid, float feedback, float reference)
{

	float iError, Increase;    						// 当前误差  最后得出的实际增量

	iError = reference - feedback;    				// 计算当前误差

	Increase = pid->P * (iError - err->Last_Error)  //比例P
	+ pid->I * iError      							//积分I
	+ pid->D * (iError - 2 * err->Last_Error + err->Previous_Error);    //微分D

	err->Previous_Error = err->Last_Error;    		// 更新前次误差
	err->Last_Error = iError;		  				// 更新上次误差

	return Increase;								// 返回增量
}

  这是两种很典型的PID算法,一个位置式,一个增量式。下面就在CCS软件中测试这两个函数,这里使用的是dsp28335芯片。首先定义PID和ERROR结构体变量。

PID pid = { 0.1, 0.01, 0.001, 100.0 };
ERROR err = { 0.0, 0.0, 0.0 };

  接下来就可以直接在main函数中调用上面两种pid的算法了。

float ref = 100;		//参考值
float sample1=0,sample2=0;	//采样值
void main()
{
	InitSysCtrl();
	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();
	LED_Init();
	while(1)
	{
		sample1 += PID_Realize(&err,&pid,sample1,ref);
		sample2 += PID_Increase(&err,&pid,sample2,ref);
	}
}

  将需要设定的参考值ref设置为100,然后两个采样值sample1sample2都设置为0,将PID计算出来的结果作为第二次的输入,然后在调用PID计算,这样一直循环。

  代码编写完成之后,直接debug开始调试。

进入调试界面之后,在变量sample1上单击鼠标右键,选择添加到观察窗口
在这里插入图片描述
弹出的窗口上点OK
在这里插入图片描述
此时窗口右边就会出现一个变量显示区域
在这里插入图片描述
同样在变量sample2上也单击右键,添加到观察窗口。
在这里插入图片描述
  添加完成之后,将黄色箭头的图标选中,这个是实时刷新功能,这样在代码全速运行的时候,就可实时看到变量值在变化。接下来全速运行代码。
在这里插入图片描述
  此时可以看到这两个变量值都停在在100作用不变化了,没有看到变换的过程。下面将这两个值添加到图形显示中。在观测窗口变量值上单击鼠标右键,选择Graph。

在这里插入图片描述
此时就会新增一个图形显示窗口
在这里插入图片描述
在另一个变量上右键,选择Graph。
在这里插入图片描述
  此时又增加了一个显示窗口,但是这两个窗口重叠在了一起,看起来不方便,在窗口标题处按住鼠标左键,拖动窗口,将两个图形显示调节到合适的位置。
在这里插入图片描述

  然后再这两个图形显示窗口上,将实时刷新的按钮选中。
在这里插入图片描述
接下里全速运行程序。
在这里插入图片描述
  这时候PID调节的曲线就显示出来了,但是这个曲线和PID调节的曲线看起来不太一样,难道是程序有问题吗?当然不是程序的问题,是这个图形显示的刷新率太低了,而我们的程序执行的太快了。下面在代码中添加延时。

while(1)
	{
		sample1 += PID_Realize(&err,&pid,sample1,ref);
		sample2 += PID_Increase(&err,&pid,sample2,ref);
		DELAY_US(1000*200);
	}

  重新编译运行代码
在这里插入图片描述
在这里插入图片描述
这时候就可看到右侧的变量和曲线都在缓慢的变化,可以看到PID的调节过程了。
在这里插入图片描述
  为了方便修改PID的参数,将结构体变量pid也添加到观察窗口中。在代码中选中pid然后右键添加到观察窗口。
在这里插入图片描述
  此时右边的观察窗口中就多了一个pid的结构体变量,将PID前面的加号点开,这时候就可以看到结构体中每个成员的值了。
在这里插入图片描述
  这时候在变量窗口中就可以直接修改这些参数的值了。鼠标双击要修改的值,选中值之后,直接输入要改的值,然后按回车键。
在这里插入图片描述
这里将P的值修改为0.2在这里插入图片描述
修改完成之后,底下的曲线没有发生变化。要想重新看pid的调节过程,这里将两个采样值都改为0 。
在这里插入图片描述
这时候PID函数就会从0开始重新计算,底下的曲线也会重新绘制。
在这里插入图片描述
  这样只需要在变量观察窗口直接修改PID的参数,就能实时看到PID曲线的效果了。不用在程序里面修改一次参数然后又重新仿真运行。

  还有一种方法,不需要加延时也能实时查看波形。下面就介绍一下这个方法。
定义两个数组来存放采样值,然后增加一个变量来记录数组的下标。在主函数中将采样的两个值分别存放到数组中,当数组个数超过200个之后,将下标清零。此时代码中将延时函数去掉了。没有延时,相当于代码按照正常的计算速度运行。

int cnt=0;
float value1[200];
float value2[200];

while(1)
	{
		sample1 += PID_Realize(&err,&pid,sample1,ref);
		sample2 += PID_Increase(&err,&pid,sample2,ref);
		//DELAY_US(1000*200);
		if(cnt<200)
		{
			value1[cnt] = sample1;
			value2[cnt] = sample2;
			cnt++;
		}
		else
			cnt =0;
	}

仿真运行代码,进入仿真界面后再工具栏选择 Tools—Grapg—Single Time
在这里插入图片描述
这时候会弹出一个对话框,在对话框中填入需要观测的数组信息。
在这里插入图片描述
将数组相关信息填写进去,然后点OK按钮,此时就会新增一个图形显示窗口
在这里插入图片描述
按照同样的方法,在工具栏选择 Tools—Grapg—Single Time,将value2数组也添加到图形显示中,然后选中实时刷新按钮。
在这里插入图片描述
然后在 cnt=0这一行打个断点,用来观察一次计算完成之后的波形。全速运行代码。
在这里插入图片描述
  程序在断点处停止后,左边两个图形显示的是正常的PID调节曲线,右边两个是阶跃信号。这是因为取消延时后,图形显示的刷新率太低,不能实时捕获到每个数据,所以直接显示变量的曲线就看不出来细节了,而数组显示比较完整,是因为代码中将过程中的所有数据都先存储到了数组中,然后根据数组中的数据来绘制曲线。
  继续全速运行,这时候曲线就会变成一条直线,这是因为PID调节完成之后,数组中的值被更新了。
在这里插入图片描述

如果还想继续观察调节过程,在程序中断之后,将sample1sample2的值改为0,修改完之后,这时变量的曲线值也会从100变为0.
在这里插入图片描述
  全速运行代码
在这里插入图片描述
这时候左边两个数组的曲线就会被重新绘制出来。

  如果要修改PI参数的话,每次程序在断点处停止之后,修改PI参数,然后将sample1sample2的值改为0,接着全速运行,就可观测到新的PI参数生成的曲线了。
在这里插入图片描述
  这样在学习PID的时候就不用借助上位机软件,使用CCS本身的图形显示工具,就能看到不同参数下PID调节的差别了。
在这里插入图片描述
完整代码如下

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File
#include "leds.h"
typedef struct
{
	float P;
	float I;
	float D;
	float limit;
} PID;

typedef struct
{
	float Current_Error;			//当前误差
	float Last_Error;				//上一次误差
	float Previous_Error;			//上上次误差
} ERROR;

// 位置式PID控制
float PID_Realize(ERROR *err, PID *pid, float feedback, float reference)
{
	float iError, Realize;    						// 当前误差 实际输出
	iError = reference - feedback;					// 计算当前误差  期望值-当前值
	err->Current_Error += pid->I * iError;    		// 误差积分
	err->Current_Error = err->Current_Error > pid->limit ? pid->limit : err->Current_Error;    //积分限幅
	err->Current_Error = err->Current_Error < -pid->limit ? -pid->limit : err->Current_Error;

	Realize = pid->P * iError       				//比例P
	+ err->Current_Error    						//积分I
			+ pid->D * (iError - err->Last_Error);    //微分D

	err->Last_Error = iError;		  				// 更新上次误差
	return Realize;    								// 返回实际值
}

// 增量式PID
float PID_Increase(ERROR *err, PID *pid, float feedback, float reference)
{
	float iError, Increase;    						// 当前误差  最后得出的实际增量
	iError = reference - feedback;    				// 计算当前误差
	Increase = pid->P * (iError - err->Last_Error)    //比例P
	+ pid->I * iError      							//积分I
	+ pid->D * (iError - 2 * err->Last_Error + err->Previous_Error);    //微分D

	err->Previous_Error = err->Last_Error;    		// 更新前次误差
	err->Last_Error = iError;		  				// 更新上次误差

	return Increase;								// 返回增量
}

PID pid = { 0.1, 0.01, 0.001, 100.0 };
ERROR err = { 0.0, 0.0, 0.0 };

float ref = 100;		//参考值
float sample1 = 0, sample2 = 0;    //采样值

int cnt = 0;
float value1[200];
float value2[200];
void main()
{
	InitSysCtrl();
	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();
	while (1)
	{
		sample1 += PID_Realize(&err, &pid, sample1, ref);
		sample2 += PID_Increase(&err, &pid, sample2, ref);
		//DELAY_US(1000*200);
		if (cnt < 200)
		{
			value1[cnt] = sample1;
			value2[cnt] = sample2;
			cnt++;
		}
		else
			cnt = 0;
	}
}


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

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

相关文章

C语言 【基础语法】

一、编程环境搭建 编译器&#xff1a;gcc 集成开发环境&#xff1a;vscode 1.1 安装vscode 1.2 设置中文包 插件 1.3 设置C/C扩展 安装 C/C Compile Run extension 和 C/C Extension Pack 扩展 二、基础语法 2.1 第一个c语言程序 2.2 数据类型 2.2.1 变量的语法(重点) …

氯氟氰虫酰胺杀灭活性好成本低 目前全球市场规模小

氯氟氰虫酰胺杀灭活性好成本低 目前全球市场规模小 氯氟氰虫酰胺&#xff0c;通用名为cyhalodiamide&#xff0c;是一种双酰胺类杀虫剂&#xff0c;外观为白色固体粉末状。 氯氟氰虫酰胺属于鱼尼丁受体作用剂&#xff0c;为邻苯二甲酰胺结构的双酰胺类杀虫剂&#xff0c;作用机…

Vision Transformer (ViT)浅析

Vision Transformer (ViT) 概述 为了将Transformer引入视觉任务&#xff0c;Google团队开发出了Vision Transformer (ViT)&#xff0c;其中ViT模型以及变种在图像分类任务上一骑绝尘 ViT的结构 ViT首先将图像( R H W C \mathbb{R}^{H\times W\times C} RHWC)划分为多个Patc…

一周学会Django5 Python Web开发-Django5模型数据新增

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计46条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

上位机图像处理和嵌入式模块部署(树莓派4b实现动态插件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 和上位机一样&#xff0c;我们的智能硬件如果想应用到更多的场景&#xff0c;那么势必需要实现更多的算法。这些算法和算法之间最好是松散耦合的插…

思维导图软件Xmind for Mac 中文激活版 支持M

XMind是一款非常受欢迎的思维导图软件&#xff0c;它应用了Eclipse RCP软件架构&#xff0c;注重易用性、高效性和稳定性&#xff0c;致力于帮助用户提高生产率。 Xmind for Mac 中文激活版下载 XMind的程序主体由一组插件构成&#xff0c;包括一个核心主程序插件、一组Eclipse…

公众号开发:获取域名

公众号中的基本配置要求需要连接服务器地址&#xff0c;这个服务器地址必须是域名&#xff0c;但是域名需要进行购买&#xff0c;因此可以使用到一个内网穿透工具&#xff1a;ngrok 进行测试 国内的就可以了Sunny-Ngrok内网转发内网穿透 - 国内内网映射服务器 首先花两块钱实名…

Mybatis之SqlNodeSqlSource

SqlNode SqlNode接口 apply()是SqlNode 接口中定义的唯一方法&#xff0c;该方法会根据用户传入的实参&#xff0c; 参数解析该SqlNode所记录的动态SQL节点&#xff0c;并调用DynamicContext.appendSql()方法将解析后的SQL片段追加到DynamicContext.sqlBuilder中保存。当SQL节…

[Collection与数据结构] 二叉树(二):二叉树精选OJ例题(上)

1. 判断是否为相同的二叉树 OJ链接 public boolean isSameTree(Node p, Node q) {if (p null && q ! null || p ! null && q null){//结构不同return false;}if (p null && q null){//结构相同,都是空树return true;}if (p.value ! q.value){//…

机器人流量激增:恶意机器人活动升级与新型规避技术挑战企业安全防御

近日&#xff0c;根据Cyber News引用Thales Imperva Bad Bot发布的最新研究报告&#xff0c;揭示了一个令人警醒的现象&#xff1a;2023年&#xff0c;互联网总流量中的49.6%由机器人贡献&#xff0c;相较于上一年增长了2%&#xff0c;创下了自2013年监测以来的历史新高。这一显…

希亦、固特、大宇超声波清洗机值不值得买?宝藏机型测评争霸

在当代生活的快节奏中&#xff0c;眼镜成了我们不可或缺的伙伴&#xff0c;无论是助力视力的提升还是时尚造型的加分项。然而&#xff0c;许多人忽视了眼镜清洁的重要性&#xff0c;不知道不清洗眼镜会带来诸多危害&#xff0c;从而影响健康和生活质量。长时间累积的污垢、油脂…

苹果开发初学者指南:Xcode 如何为运行的 App 添加环境变量(Environmental Variable)

概览 Xcode 15 在运行 SwiftUI 代码时突然报告如下警告&#xff1a; Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem. 不仅如此…

【智能算法】花朵授粉算法(FPA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2012年&#xff0c;Yang等人受到自然界花朵授粉过程启发&#xff0c;提出了鸭群算法&#xff08;Flower Pollination Algorithm, FPA&#xff09;。 2.算法原理 2.1算法思想 FPA基于自然界花朵授…

idea项目启动异常:Command line is too long.

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; idea中启动项目报错&#xff1a; 解决方案 在idea 的运行配置中&#xff0c;修改enviroment下的shorten command line 为jar manifest 注&#xff1a; 有时shorten command line 可能不是默认存在的…

Kafka复习

消息中间件的作用: 异步处理: 与并行相比,虽然减少了时间,但是还是得等待其他线程执行完,但是消息中间件对于简单的业务处理,还要引入一个中间件也比较复杂如果我投递了简历之后需要发送成功邮件以及短信,就可以交给消息中间件就像数据库、redis数据一致性,需要用到延迟…

揭秘网上问卷调查:多样化类型助力数据收集

在当今数字化时代&#xff0c;问卷调查作为一种便捷、高效的数据收集和分析方式&#xff0c;被广泛运用于市场调研、学术研究、消费者反馈等领域。而在网上进行问卷调查更是提高了调查效率和覆盖范围&#xff0c;因此&#xff0c;了解网上的问卷调查类型对于设计合适的调查问卷…

如何使用Postgres的JSONB数据类型进行高效查询

文章目录 解决方案1. 创建包含JSONB列的表2. 插入JSON数据3. 使用GIN索引加速查询4. 执行高效的JSONB查询 示例代码解释 PostgreSQL的JSONB数据类型提供了一种灵活的方式来存储和查询JSON格式的数据。JSONB不仅允许你在PostgreSQL数据库中存储JSON文档&#xff0c;而且还对这些…

万字长文带你APK反编译重签名aabapks转换

Android反编译 反编译&#xff08;Decompilation&#xff09;是将已编译的程序&#xff08;比如二进制代码&#xff09;转换回更高级别的编程语言代码的过程。这通常用于理解程序的工作原理&#xff0c;进行软件审计&#xff0c;恢复丢失的源代码&#xff0c;或者进行教学研究…

CleanAmp™ dNTP应用:24min完成三重qPCR

试剂&#xff1a;CleanAmp™ PCR Kit 仪器&#xff1a;Mastercycler ep realplex4 S qPCR instrument 品牌&#xff1a;Trilink 国内授权代理&#xff1a;欣博盛生物 分子诊断需求的不断增长&#xff08;如新冠核酸检测&#xff09;&#xff0c;要求所用检测试剂、设备能在更…

OpenCV的查找命中或未命中

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV4.9更多形态转换 下一篇&#xff1a;OpenCV4.10使用形态运算提取水平线和垂直线 目标 在本教程中&#xff0c;您将学习如何使用 Hit-or-Miss 转换&#xff08;也称为 Hit-and-Miss 转换&…