使用CCS软件查看PID曲线

2024-04-18 1685阅读

  在刚开始学习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 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,然后两个采样值sample1、sample2都设置为0,将PID计算出来的结果作为第二次的输入,然后在调用PID计算,这样一直循环。

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

进入调试界面之后,在变量sample1上单击鼠标右键,选择添加到观察窗口

使用CCS软件查看PID曲线

弹出的窗口上点OK

使用CCS软件查看PID曲线

此时窗口右边就会出现一个变量显示区域

使用CCS软件查看PID曲线

同样在变量sample2上也单击右键,添加到观察窗口。

使用CCS软件查看PID曲线

  添加完成之后,将黄色箭头的图标选中,这个是实时刷新功能,这样在代码全速运行的时候,就可实时看到变量值在变化。接下来全速运行代码。

使用CCS软件查看PID曲线

  此时可以看到这两个变量值都停在在100作用不变化了,没有看到变换的过程。下面将这两个值添加到图形显示中。在观测窗口变量值上单击鼠标右键,选择Graph。

使用CCS软件查看PID曲线

此时就会新增一个图形显示窗口

使用CCS软件查看PID曲线

在另一个变量上右键,选择Graph。

使用CCS软件查看PID曲线

  此时又增加了一个显示窗口,但是这两个窗口重叠在了一起,看起来不方便,在窗口标题处按住鼠标左键,拖动窗口,将两个图形显示调节到合适的位置。

使用CCS软件查看PID曲线

  然后再这两个图形显示窗口上,将实时刷新的按钮选中。

使用CCS软件查看PID曲线

接下里全速运行程序。

使用CCS软件查看PID曲线

  这时候PID调节的曲线就显示出来了,但是这个曲线和PID调节的曲线看起来不太一样,难道是程序有问题吗?当然不是程序的问题,是这个图形显示的刷新率太低了,而我们的程序执行的太快了。下面在代码中添加延时。

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

  重新编译运行代码

使用CCS软件查看PID曲线

使用CCS软件查看PID曲线

这时候就可看到右侧的变量和曲线都在缓慢的变化,可以看到PID的调节过程了。

使用CCS软件查看PID曲线

  为了方便修改PID的参数,将结构体变量pid也添加到观察窗口中。在代码中选中pid然后右键添加到观察窗口。

使用CCS软件查看PID曲线

  此时右边的观察窗口中就多了一个pid的结构体变量,将PID前面的加号点开,这时候就可以看到结构体中每个成员的值了。

使用CCS软件查看PID曲线

  这时候在变量窗口中就可以直接修改这些参数的值了。鼠标双击要修改的值,选中值之后,直接输入要改的值,然后按回车键。

使用CCS软件查看PID曲线

这里将P的值修改为0.2使用CCS软件查看PID曲线

修改完成之后,底下的曲线没有发生变化。要想重新看pid的调节过程,这里将两个采样值都改为0 。

使用CCS软件查看PID曲线

这时候PID函数就会从0开始重新计算,底下的曲线也会重新绘制。

使用CCS软件查看PID曲线

  这样只需要在变量观察窗口直接修改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
			value1[cnt] = sample1;
			value2[cnt] = sample2;
			cnt++;
		}
		else
			cnt =0;
	}

	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 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 
                
                
                
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]