【STM32】VOFA+上位机 PID调参

【STM32】VOFA+上位机 PID调参

前言

参考文章如下:VOFA+使用说明
使用VOFA+上位机进行PID调参
PID参数整定

VOFA+

VOFA+是一款简单易上手的上位机调试软件(超级串口助手),可以动态调节PID参数,直观的显示数据的变化曲线
建议先把官方文档看一遍VOFA+官方文档

简介

VOFA+支持3种数据流方式:FireWater、JustFloat、RawData

FireWater :编程类似 printf,但字符串解析消耗资源,适用于通道少、发送频率低的场景。
JustFloat :以小端浮点数组形式传输,适合通道多、频率高的场景。
RawData:不进行采样数据解析,类似普通串口助手。

VOFA+配置

使用FireWater字节流协议

FireWater字节流协议
使用说明

FireWater遇到换行才会打印数据,可自行选择加或不加标签 < any >

以打印电机转速为例

c 复制代码
PRINTF_PC("speed_r:%f,%f\n",wheel_rpm_Ref_R,wheel_rpm_Fdb_R);

标签:speed_r

ch0数据:wheel_rpm_Ref_R

ch1数据:wheel_rpm_Fdb_R

打开波形图

** 填充 **

VOFA+动态调节PID参数

VOFA+控件


拖拽出来

添加命令

命令和命令组的区别是,命令组是一系列连续的命令,命令是单步命令。我们目前使用命令就行

编辑命令

一会儿着重讲一下如何解析VOFA+发送的数据包

根据所需,设置控件指令的最值、步进、发送模式等等

STM32解析数据包

数据包是以什么形式发送的?

以 VOFA+ 发送 "PR=2.32!" 为例,每个字符会被转换为对应的 ASCII 码并以二进制数的形式发送。例如,"PR=2.32!" 被解析为 ASCII 码:80 82 61 50 46 51 50 33,再以二进制数值发送

解析思路

  1. 找到有效数据的开始(=)和结束(!)索引
  2. 提取等号与感叹号之间的字符,将其存入 valueStr
  3. 将 valueStr中的字符串转换为浮点数
  4. 根据头两个字符(如 PR),将浮点数赋值给相应的 PID 参数

代码示例

c 复制代码
//入参:字符串数组(存储ascii码数组)的地址 ; 字符串数组的长度
void get_PIDdata(uint8_t *data, uint16_t size)
{
	int startIdx,endIdx;		//定义有效数据的起始索引和结束索引
	char valueStr[10] = {0}; 	//定义有效数据对应的字符串
	float PIDpara;				//
	
	if(data[size-1] == '!')		//当最后一位为字符'!'(说明下,==进行判断时,两端都必须是数值,也即左侧会解析为数值(uint8_t数组的值),右侧也会解析为数值(字符'!'对应的ascii值)
	{
		//找到 '=' 的索引
		for(int i=0;i<size;i++)
		{
			if(data[i] == '=')
			{
				startIdx = i + 1;	//找到有效数据起始索引
				break;
			}
		}
		//找到 '!' 的索引
		for (int i = startIdx; i < size; i++)
        {
            if (data[i] == '!')
            {
                endIdx = i;		//找到有效数据结束索引
                break;
            }
        }
		//提取 '='与'!'之间的数值
		if (startIdx > 0 && endIdx > startIdx)
		{
			strncpy(valueStr, (char*)&data[startIdx], endIdx - startIdx);	//将有效数据长度的字符从data源字符串中拷贝到valueStr字符串中
			valueStr[endIdx - startIdx] = '\0';	//将valueStr字符串尾部补上'\0',作为字符串结束标志
			PIDpara = atof(valueStr);		//将字符串转换为浮点数("2.32"-->2.32)
		}
		// 设置左右电机的PID参数
		if (data[0] == 'P' && data[1] == 'L')
		{
			speed_pid_L.kp = PIDpara;
			PRINTF_PC("L_KP = %.3f\n", speed_pid_L.kp);
		}
		else if (data[0] == 'I' && data[1] == 'L')
		{
			speed_pid_L.ki = PIDpara;
			PRINTF_PC("L_KI = %.3f\n", speed_pid_L.ki);
		}
		else if (data[0] == 'D' && data[1] == 'L')
		{
			speed_pid_L.kd = PIDpara;
			PRINTF_PC("L_KD = %.3f\n", speed_pid_L.kd);
		}
		else if (data[0] == 'M' && data[1] == 'L')
		{
			speed_pid_L.maxIntegral = PIDpara;
			PRINTF_PC("L_MaxIntegral = %.3f\n", speed_pid_L.maxIntegral);
		}
		else if (data[0] == 'P' && data[1] == 'R')
		{
			speed_pid_R.kp = PIDpara;
			PRINTF_PC("R_KP = %.3f\n", speed_pid_R.kp);
		}
		else if (data[0] == 'I' && data[1] == 'R')
		{
			speed_pid_R.ki = PIDpara;
			PRINTF_PC("R_KI = %.3f\n", speed_pid_R.ki);
		}
		else if (data[0] == 'D' && data[1] == 'R')
		{
			speed_pid_R.kd = PIDpara;
			PRINTF_PC("R_KD = %.3f\n", speed_pid_R.kd);
		}
		else if (data[0] == 'M' && data[1] == 'R')
		{
			speed_pid_R.maxIntegral = PIDpara;
			PRINTF_PC("R_MaxIntegral = %.3f\n", speed_pid_R.maxIntegral);
		}
	}
}

PID参数整定

注意,在一般的控制系统中,只用pi或pd就能满足需求

一般调节法

设定比例系数(P) :将积分和微分系数置零,系统设为比例控制,将输出设为最大值的 60%-70%,逐步增大比例系数至系统振荡,再减小至振荡消失,设定为此时比例系数的 60%-70%。

设定积分系数(I) :在确定比例系数后,设定较小的积分系数,逐步增大至系统振荡,再减小至振荡消失,设为此时积分系数的 55%-65%。

微分系数(D) :通常为 0。如果系统有小幅振荡,通过 P、I 无法优化,可按相同方法调整 D,设为系统不振荡时的 30%。
联调 :系统空载、带载联调,并对 PID 参数进行微调。
建议:PID 的 P 是必须的,通常只使用两个参数组合(如 PI 用于稳定系统,PD 用于快速响应),三个参数更难调,通常前两个参数已足够。

临界比例法

4.1 内容

将系统设置为纯比例控制,逐渐增大比例系数,直至系统曲线出现等幅振荡,然后根据公式计算 PID 参数

4.2 调节思路

  1. 将积分、微分系数置零,系统按比例控制运行一段时间。
  2. 逐渐增大比例系数,观察曲线变化,若振荡减小则继续增大,振荡变大则减小,直到出现等幅振荡,记录临界比例系数和振荡周期。
  3. 根据经验公式计算 PID 参数
控制环节 Kp Ki Kd
P δK/2 0 0
PI δK/2.2 Kp / (0.833 * Tk) 0
PID δK/1.7 Kp / (0.5 * Tk) 0.125 * Tk * Kp

试凑法

结合系统的具体情况以及经验,先试凑几组合理的 PID 系数,同时需要观察系统的曲线变化,确定每一个系数对于整个系统曲线的大致影响,然后再根据具体的曲线进行调整。

调节思路

① 先是比例(P),再积分(I),最后是微分(D)

② 按纯比例系统整定比例系数,使其得到比较理想的调节过程曲线,然后再把比例系数缩小 1.2 倍左右,将积分系数从小到大改变,使其得到较好的调节过程曲线

③ 在这个积分系数下重新改变比例系数,再看调节过程曲线有无改善

④ 如果有改善,可将原整定的比例系数减少,改变积分系数,这样多次的反复,就可得到合适的比例系数和积分系数

⑤ 如果存在外界的干扰,系统的稳定性不好,可把比例、积分系数适当减小,使系统足够稳定

⑥ 如果系统存在小幅度超调,可以将整定好的比例系数和积分系数适当减小,增大微分系数,以得到超调量最小、调节作用时间最短的系统曲线。

相关推荐
MGT_97969 小时前
ESP01的AT指令连接到阿里云平台
嵌入式硬件·物联网·阿里云·云计算
OH五星上将10 小时前
如何编译OpenHarmony SDK API
嵌入式硬件·移动开发·api·sdk·harmonyos·openharmony·鸿蒙开发
JT灬新一10 小时前
ARM驱动学习之 IOremap实现GPIO 读
arm开发·单片机·学习
我的老子姓彭13 小时前
STM32启用FPU浮点运算
stm32·单片机·嵌入式硬件
AI+程序员在路上13 小时前
STM32读写内部flash
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi16 小时前
基于单片机的风机故障检测装置的设计与实现(论文+源码)
stm32·单片机·嵌入式硬件·物联网·毕业设计
OH五星上将17 小时前
如何更换OpenHarmony SDK API 10
驱动开发·嵌入式硬件·sdk·harmonyos·openharmony·鸿蒙开发
马浩同学17 小时前
【ESP32】Arduino开发 | 中断矩阵+按键输入中断例程
c语言·单片机·嵌入式硬件·mcu
c106389151419 小时前
STM32之FMC—扩展外部 SDRAM
stm32·单片机·嵌入式硬件·fmc
CV金科21 小时前
蓝桥杯-STM32G431RBT6(解决LCD与LED引脚冲突的问题)
c语言·stm32·单片机·嵌入式硬件·蓝桥杯