VOFA+ :PID速度环调参
一、PID
PID是一种常见的反馈控制系统,广泛应用于工业控制、自动化和机器人等领域。PID控制器基于当前系统的误差(偏差)、积分(偏差的累积)和微分(偏差的变化率)来调整控制输出,以使系统的实际输出尽可能接近期望值或设定点。
这里是PID的三个组成部分:
- 比例(Proportional, P):该部分产生一个输出,与当前误差成比例。增加比例增益(P增益)会增加系统对误差的敏感度,但可能导致系统过冲或振荡。
- 积分(Integral, I):该部分根据时间对误差的积累来产生一个输出。它可以用来消除静态误差,即使系统有漂移或存在持续偏差。
- 微分(Derivative, D):该部分根据误差变化率来产生一个输出。它可以减少系统的超调,并改善系统的动态响应,但过大的D增益可能导致系统过于敏感,产生噪声或抖动。
PID控制器的输出是这三个部分的加权和,通常用以下公式表示:
O
u
t
p
u
t
=
K
p
∗
e
r
r
o
r
+
K
i
∗
∫
e
r
r
o
r
d
t
+
K
d
∗
d
(
e
r
r
o
r
)
/
d
t
Output = Kp * error + Ki * ∫error dt + Kd * d(error)/dt
Output=Kp∗error+Ki∗∫errordt+Kd∗d(error)/dt
其中,
K
p
、
K
I
、
K
D
K_p、K_I、K_D
Kp、KI、KD分别是比例、积分和微分的增益(参数),error表示期望值与实际值之间的偏差。
PID控制器的参数调整通常是一个挑战,需要根据具体的应用和系统特性进行调整。常见的方法包括手动调节、试错法、自动调节算法等。
这里对PID原理的介绍可以参考:一文读懂PID控制算法(抛弃公式,从原理上真正理解PID控制)
二、代码部分
PID有位置式和增量式的PID:
1.位置式PID
#define INTEGRAL_MAX 1000
#define OUTPUTVAL_MAX 1000
typedef struct
{
float targetVal;//目标值
float error;//误差
float lastError;//上次误差
float P;
float I;
float D;
float integral;//积分项
float outPutVal;//输出
}PID;
uint16_t getPlacePIDVal(float nowVal,PID *pid)
{
pid->error = pid->targetVal - nowVal;
//积分限幅
if (fabs(pid->integral) < INTEGRAL_MAX)
{
pid->integral += pid->error;
}
pid->outPutVal += (pid->P * pid->error + pid->I * pid->integral + pid->D * (pid->error - pid->oldError));
//输出限幅
pid->outPutVal = (pid->outPutVal > OUTPUTVAL_MAX) ? OUTPUTVAL_MAX : pid->outPutVal;
pid->oldError = pid->error;
return pid->outPutVal;
}
2.增量式PI
#define OUTPUTVAL_MAX 1000
typedef struct
{
float targetVal;//目标值
float error;//误差
float lastError;//上次误差
float P;
float I;
float outPutVal;//输出
}PID;
uint16_t getIncrementPIDVal(float nowVal,PID *pid)
{
pid->error = pid->targetVal - nowVal;
pid->outPutVal += (float)(pid->P * (pid->error - pid->oldError) + pid->I * pid->error);
//输出限制
pid->outPutVal = (pid->outPutVal > OUTPUTVAL_MAX) ? OUTPUTVAL_MAX : pid->outPutVal;
pid->oldError = pid->error;
return pid->outPutVal;
}
这里速度环我选择使用增量式PI来控制
三、VOFA+
简单地来说,VOFA+是一个超级串口助手,除了可以实现一般串口助手的串口数据收发,它还可以实现数据绘图(包括直方图、FFT图),控件编辑,图像显示等功能。使用VOFA+,可以给我们平常的PID调参等调试带来方便,还可以自己制作符合自己要求的上位机,为嵌入式开发带来方便。
怎么使用呢?可以简单的的阅读一下官网的手册
这里我们选择使用FireWater模式
控制布局如上
因为我们PID的参数一般是浮点型,需要用四个字节来表示,我参考了很多文章发现大家都是换算得到的,这里我推荐使用c语言的库函数sscanf()
在串口所收集到的数组里面读取,这里参考一下我的命令格式
代码如下:
#include "cs_vofa.h"
#define CMD_MAX 10
char cmd[CMD_MAX];
float parameter;
void messageSetPID(char * str)
{
if(sscanf(str,"%4s%f",cmd,¶meter) != 2) return;
if(cmd[0] == 'R')
{
if(cmd[1] != '_' || cmd[3] != '=') return;
if(cmd[2] == 'P')
{
R_PID.P = parameter;
}
else if(cmd[2] == 'I')
{
R_PID.I= parameter;
}
else if(cmd[2] == 'D')
{
R_PID.D= parameter;
}
else if(cmd[2] == 'T')
{
R_PID.targetVal = parameter;
}
}
else if(cmd[0] == 'L')
{
if(cmd[1] != '_' || cmd[3] != '=') return;
if(cmd[2] == 'P')
{
L_PID.P = parameter;
}
else if(cmd[2] == 'I')
{
L_PID.I= parameter;
}
else if(cmd[2] == 'D')
{
L_PID.D= parameter;
}
else if(cmd[2] == 'T')
{
L_PID.targetVal = parameter;
}
}
}
上面是处理VOFA所的命令
那么怎么把下位置的数据发给VOFA,VOFA做出波形图呢?
这边其实很简单,我们采用FireWater模式
所以我们只需要把对应的速度以上面格式发送就行。
四、效果
资源下载:百度网盘