使用VOFA+工具用于调试PID算法

继上一篇介绍如何使用VOFA+之后,本文介绍使用VOFA+工具用于调试PID算法(重点是实现使用此工具用于调试,而非介绍算法,我也不确定以下算法的正确性,大家参考即可)。

一、首先验证发的数据正确性。

当我配置发送“0”和“0”数据时,上位机收到数据如图。00 00 80 7F为帧尾。

当我配置发送“1”和“2”数据时,上位机收到数据如图。00 00 80 7F为帧尾。

如果收到数据不是以上情况,则说明串口发送数据的格式不正确。

定时器中断中调用,控制算法和发送函数均在一个函数中实现。

//定时器中,1Ms调用一次,固定时间调用
void AppAlgDeal(void)
{
	static int32_t TimeCnt;
	static float tempFloat[2];
	static uint8_t tempData[12] = {0,0,0,0,0,0,0,0,0,0,0x80,0x7F};
	int32_t speed;
	TimeCnt++;
	if(TimeCnt >= 10)
	{
		TimeCnt = 0;
		
		//1. 速度计算(固定时间中,所走的路程,这里简化计算,按照固定实际所走的脉冲)
		speed = SpeedCalc.CntCurt - SpeedCalc.CntRecd;
		SpeedCalc.CntRecd = SpeedCalc.CntCurt;
		//计算速度平均值(因速度计算波动大,所以采用求和进行滤波,但这样带来的结果是响应变慢)
		SpeedCalc.SpeedSum = SpeedCalc.SpeedSum + speed - SpeedCalc.CntRecord[SpeedCalc.Cnt];
		SpeedCalc.CntRecord[SpeedCalc.Cnt] = speed;
		SpeedCalc.Cnt++;
		SpeedCalc.Cnt&=3;
		
		//2. PID算法(位置式PID)
		pwmVal += PID_Contrl(&PID_Para, SpeedCalc.SpeedSum);
		
		//3. PWM限幅,最大为500,最小为0
		if(pwmVal > 500)
			pwmVal = 500;
		else if(pwmVal < 0)
			pwmVal = 0;
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, pwmVal);	//送出到PWM输出

		//4. 串口发送
		tempFloat[0] = PID_Para.TitelVal;
		tempFloat[1] = (float)SpeedCalc.SpeedSum;
		memcpy(tempData, (uint8_t *)&tempFloat, sizeof(tempFloat));
		HAL_UART_Transmit_IT(&huart6, (uint8_t *)tempData, 12);
	}
}

 二、PID介绍。PID在离散领域实现时分为位置式和增量式。

以下介绍中使用位置式。(不过我也不确定我使用的对不对)

位置式PID算法。

/*************************************************
 *函数名称:float PID_Contrl(sPID_Reg* sPt,float RealVal)
 *功    能:PID控制                                   
 *参    数:sPt PID参数,RealVal 当前实际值
 *返 回 值:void                                       
*************************************************/
float PID_Contrl(sPID_Reg* sPt,float RealVal)
{
	float error,add;
	
	error = sPt->TitelVal - RealVal;	//当前误差  设定的目标值和实际值的偏差
	
	add = sPt->Kp * error				//增量计算
			  - sPt->Ki * sPt->LastError
			  + sPt->Kd * sPt->PrevError;
	
	/*存储误差  用于下次计算*/
	sPt->PrevError = sPt->LastError;
	sPt->LastError = error;
	
	return add;							//返回增量值
}

参数初始化


typedef struct{
	float TitelVal;		//目标值
	float SumError;		//累计误差
	float Kp;					//比例项
	float Ki;					//积分项
	float Kd;					//微分项
	float LastError;	//上次偏差
	float PrevError;	//上上次偏差值
}sPID_Reg;

sPID_Reg PID_Para;		//定义PID参数

void PID_Arg_Init(sPID_Reg* sPt)
{
	memset(sPt, 0, sizeof(sPID_Reg));
	sPt->Kp = 0.5;
	sPt->Ki = 0.1;
	sPt->Kd = 0.01;
	sPt->TitelVal = 100;
}

三、配置发送2个数据。分别为目标速度和实际速度。

 以下图片中,红色为目标速度,绿色为实际速度。右边框中分别为Kp,Ki,Kd数据。

Kp,Ki,Kd分别为1.5,0,0。

Kp,Ki,Kd分别为1,0,0。

Kp,Ki,Kd 分别为0.5,0,0。

Kp,Ki,Kd 分别为1,0.2,0。

 Kp,Ki,Kd 分别为1,0.4,0。

 Kp,Ki,Kd 分别为0.5,0.1,0.01。 

以上工程我放在此链接下,供下载参考。(Stm32CubeMx工程也在附件中)

https://download.csdn.net/download/weixin_42316458/79692273

我使用的是STM32F401RCT6芯片。

以上完结。

本人新建了个QQ群,如想进一步沟通可添加:947187213。

版权声明:本文为CSDN博主「一个做底层的码农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42316458/article/details/121502912

生成海报
点赞 0

一个做底层的码农

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

使用VOFA+工具用于调试PID算法

继上一篇介绍如何使用VOFA之后,本文介绍使用VOFA工具用于调试PID算法(重点是实现使用此工具用于调试,而非介绍算法,我也不确定以下算法的正确性,大家参考即可&#xff0

基于STM32的指纹密码锁

设计简介: 本设计是基于单片机的指纹密码锁,主要实现以下功能: 矩阵按键输入密码,并通过按键显示*号可通过按键或手机开门密码可通过按键进行开门可通过蓝牙模块连接手机进行开门可通过指纹进

定时器触发STM32 ADC的采样转换示例

开发板:STM32F446 Nucleo开发板IDE:  keil MDK初始化配置工具:stm32cubeMx例程内容:通过定时器触发ADC规则通道及注入通道的模数转换工作。下面基于STM32CubeMx进行些必要