遥控电机PID学习及其调参—学习记录

· 一、总览

此前所需工作

1.CAN驱动设置
2.简单的应用程序编写
3.CAN数据传输实验
4.遥控器通道数据获取
5.应用程序自启动

任务目标:

实现目标是遥控麦轮车实现可控移动,使用CAN总线进行数据传输。

需要解决的问题:

直接使用遥控通道值作为电流发送给电调时,由于相同电机可能存在制作工艺上的微小差距,那么相同的通道值会驱动出不同的转速,故需要使用反馈的电流值,结合PID控制器实现转速平滑控制。

PID调试一共可分为三个阶段:
①程序设置固定转速跟随
②程序变转速跟随
③遥控PID跟随

·二、PID调试

什么是PID算法,如何理解增量式PID和位置式PID

2.1遥控电机运动控制图

通道解析
current
-feedback
遥控器
target_speed
+
增量pid
CAN总线
MOTORS

首先将遥控器的通道值读出,结合小车底盘运动学模型进行参数解析,将其转换成目标速度。
然后将目标速度target_speed与电机转速feedback的差值作为PID控制器输入,经过运动学解析得到电机的电流值,最后通过CAN数据传输协议将电流值发送出去。

使用到的电机参数
需要写CAN协议的学习

2.2电机与电调参数

对于所选取的RM C610无刷电机调速器需要给予恒定的电流进行电机稳定运行,使用该电调,电机转子转速最大可达20000rpm,电机的减速比为36:1。

通过实验测得给定电流值和反馈的速度值关系如下,其中X轴为给定电流,Y轴是速度反馈

需要注意的是当给定电流小于350,电机并不会转动,300-350需要手动波动电机才能完成电机运动,可能是需要克服静态阻力,
图一
所选电机参数如下:
在这里插入图片描述

2.3 PID调参实验

PID参数介绍

static int current[4] = {0}; //用来存储输出值,只在创建时进行初始化,故为静态变量
pid->err[4][3];//因为需要对4个电机使用增量式pid控制,故需要存储4个电机的3次位置偏差。

PID函数完整程序

int pid_out(pid_s *pid, int set, int get, int id)
{
	static int current[4] = {0};
	pid->set = set;
	pid->get = get;

	//pid->err[NOW] = (set - get)*0.005;
	pid->err[id][NOW] = abs(set - get)>=700?(set - get)*0.005 :(set - get)*0.008;//将转速误差缩放一定倍率,多倍率意在平衡动态误差范围
	/*pid参数优化*/


	current[id] += pid->p*(pid->err[id][NOW] - pid->err[id][LAST_NOW] )
							+pid->i*pid->err[id][NOW]
							+ pid->d*(pid->err[id][NOW] - 2*pid->err[id][LAST_NOW] + pid->err[id][LAST_LAST]);
	current[id] = abs_limit(current[id],1000);

	if(abs((int)pid->set)<=5000) 	current[id] = abs_limit(current[id],650);
	else if(abs((int)pid->set)<=12000 && abs((int)pid->set)>5000)	current[id] = abs_limit(current[id],850);
	else	current[id] = abs_limit(current[id],1000);


	pid->err[id][LAST_LAST] = pid->err[id][LAST_NOW];
	pid->err[id][LAST_NOW] = pid->err[id][NOW];
	
	return current[id] ;
}

由于PID动态特性的影响因素有很多,除了三个参数,还有程序的运行速率,不同速率条件下会调出不同的参数值。个人的while中设置了usleep(10000),即10ms的时间间隔,最后测试单电机运行的频率大致为90HZ左右,多电机的情况下可能频率会再降低一些,不过可以满足控制需要。

下面分享一下调参的历程:
① kp = 20, ki = 0, kd = 0;

电机不启动,原因是增量式pid中初始情况下的偏差记录值都是0,式子

current[id] += pid->p*(pid->err[id][NOW] - pid->err[id][LAST_NOW] )

的输出current始终为0,不足以启动电机。
② kp = 20, ki = 1, kd = 0;

在①的基础上加入积分环节,此时电机转速收敛,但是阶跃情况下有超调,约2次振荡,振荡的原因是累加的电流值存在惯性,积分系数越大,振荡越明显,不信看③
在这里插入图片描述)
③ kp = 20, ki = 2, kd = 0;

这里尝试调大ki,观察其对动态特性的影响,输出曲线如下,可以探得ki对响应输出的影响。
在这里插入图片描述
④ kp = 20, ki = 2, kd = 1;
这里奇怪的事情发生了,从理论和经验上讲,kd可以消除振荡,所以我在③的基础上加入了kd值,意在减小振荡
但是曲线如下,可以看出稳态时振荡加剧,至此我想先不动kd,尝试从p i上动手
在这里插入图片描述
⑤ kp = 20, ki = 1.5, kd = 0;
此时响应的效果可想而知,必然介于②和③的效果之间
在这里插入图片描述

⑥ kp = 30, ki = 1, kd = 0;
目前来讲②的效果比较好,尝试在②的基础上进行kp的调整,得出了阶跃状态下比较完美的响应曲线,能实现阶跃的快速跟随,并且无超调,稳态误差在50-150rpm之间,在可接受的范围内。
随后在此基础上进行了多次调参尝试,意在加快响应速度。
在这里插入图片描述
⑦ kp = 30, ki = 1.5, kd = 0;
积分能加快响应速度,但是积分的惯性会带来振荡
在这里插入图片描述
⑧ kp = 30, ki = 1.5, kd = 0.5;
⑨ kp = 30, ki = 1.5, kd = 0.1;
参照微分环节的作用加上kd,意在减小振荡,发现并没有用,效果都不及⑥。
在这里插入图片描述
在这里插入图片描述
最终使用⑥的参数进行遥控的控制。

放一组未调好的位置pid

int pid_out(pid_s *pid, int set, int get, int id)
{
	static int current[4] = {0};
	pid->set = set;
	pid->get = get;

	//pid->err[NOW] = (set - get)*0.005;
	pid->err[id][NOW] = abs(set - get)>=2000?(set - get)*0.02 :(set - get)*0.035;//将转速误差缩放一定倍率

	/*pid参数优化*/
	pid->p_out[id] = pid->p * pid->err[id][NOW];
	pid->i_out[id] += pid->i * pid->err[id][NOW];
	pid->d_out[id] = pid->d * (pid->err[id][NOW] - pid->err[id][LAST_NOW]);

	//pid->i_out[id] = abs_limit(pid->i_out[id],400);
	// if(abs((int)pid->set) <= 5000) pid->i_out[id] = abs_limit(pid->i_out[id],400);
	// else if (abs((int)pid->set) > 5000 && abs((int)pid->set <= 10000)) pid->i_out[id] = abs_limit(pid->i_out[id],600);
	// else if (abs((int)pid->set) > 10000 && abs((int)pid->set <= 15000)) pid->i_out[id] = abs_limit(pid->i_out[id],700);
	// else pid->i_out[id] = abs_limit(pid->i_out[id],900);
	current[id] = (int)(pid->p_out[id] + pid->i_out[id] + pid->d_out[id]);


	//current[id] = abs_limit(current[id],800);

	pid->err[id][LAST_LAST] = pid->err[id][LAST_NOW];
	pid->err[id][LAST_NOW] = pid->err[id][NOW];

	return current[id] ;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渣渣喝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值