目前,我正在调整PID循环。 PID函数的实现方式如下:
int16_t pid_roll(int16_t roll)
{
static int16_t roll_old = 0;
int16_t result =
(KP_ROLL * roll) +
(KI_ROLL * (roll_old + roll)) +
(KD_ROLL * (roll - roll_old))
;
roll_old += roll;
result = constrain(result, PID_MIN_ROLL, PID_MAX_ROLL);
return -result;
}
我在解释有关改变常数的系统响应时遇到麻烦。我相信问题与以下问题有关。
PID控制器应该多久更新一次电机值?目前,我的更新时间约为100-110毫秒。
PID更新对电机推力的最大变化应该是多少?目前,我的最大限制约为推力范围的+ -15%。
应在什么推力范围或值下进行调整?最小值,升空或中档还是无关紧要?
#1 楼
1)我将尝试找出您的ESC可以更新的速度,并将其用作PID更新率。您当前的速率肯定太慢了(边缘性能至少需要50Hz)。2)在最大变化量上设置阈值仅应用于处理紧急情况/意外情况。您不应该期望它是正常操作的一部分,如果在正常操作过程中出现尖峰,则意味着您需要在其他地方进行修复或降低增益。
3)随时随地调整PID需要最佳性能,这取决于您的应用程序。一种策略是针对不同情况使用不同的增益值集(例如单独的起飞增益),但是每组增益都需要分别进行调整,以增加工作量。
#2 楼
我自己编写了一个四边形,并学会了远离PulseIn函数。它基本上是在等待并不断读取该引脚。我相信Arduino UNO有2个中断输入引脚,请尝试使用它们。对于某些接收器,如果一个接一个地发送脉冲,则可以使用OR端口,并且将脉冲组合成CPPM信号。中断处理程序不需要花费太多时间,您所需要做的就是启动并读取计时器。使用这种技术,我获得了超过200Hz的频率
#3 楼
它与电子速度控制器单元和BLDC电机的响应时间有关。在离散时间中,只有Ki和Kd具有时间变量。在稳定的系统中,如果更改采样率,则必须更改Ki和Kd才能放大它。因此,您可以反过来做。您可以仅更改Ki和Kd常数,而无需更改采样率。两者产生相同的效果。您可以在此链接中找到PID与采样率之间的关系:http://support.motioneng.com/downloads-notes/tuning/scaling_pid_param.htm
评论
$ \ begingroup $
仅当系统可以使用当前时间步长进行控制时,才可以调整k值,对吗?例如,如果时间步长为2秒,则无法控制系统(飞行的物体)。
$ \ endgroup $
–GürkanÇetin
15年6月28日在13:03
$ \ begingroup $
不同的步长需要不同的常数。如果使用动态采样率,则可以与动态常数相乘。
$ \ endgroup $
– acs
15年6月28日在14:53
$ \ begingroup $
你是说增益常数可以是动态的吗?这不是违反直觉的吗?常量根据定义是常量,并且不会更改。或者,您是说在不同的条件下(如悬停和向前飞行),可以更改delta_t以使增益保持不变吗?您能否说说保持增益恒定并尝试提出动态delta_time有什么好处?我猜想调优是一样的,软件可能会变得更加复杂。
$ \ endgroup $
–GürkanÇetin
15年6月28日在15:30
$ \ begingroup $
PID只是一段代码。您可以在该代码中动态更改所有内容。如果系统更改了采样时间,则必须使用适当的常数进行更新。这意味着您可以响应采样时间的变化。
$ \ endgroup $
– acs
15年6月28日在17:08
$ \ begingroup $
是正确的,例如,您也可以更改Kd常数,实现相同结果的一种简单方法是将其与当前增量时间相乘。
$ \ endgroup $
–GürkanÇetin
15年6月28日在17:12
#4 楼
您的代码假定CPU以恒定时钟运行。但是,在现实生活中,它会发生变化,有时甚至会发生巨大变化!因此,需要在计算中将Delta时间(dt)因子插入KI和KD项。ie
(KI_ROLL * (roll_old + roll) *dt) +
(KD_ROLL * (roll - roll_old) *dt)
( dt = time_now-time_previous)
顺便说一句,您的积分术语是错误的!就目前而言,这可能会破坏整个系统的稳定性。积分控制器应使用Integral_Roll_error变量,该变量是时间上的错误。例如:
Integral_Roll_error = Integral_Roll_error + roll - roll_old;
快速运行固然重要,但需要稳定的运行速度,尤其是如果您希望能够分析系统或进行测试,比较不同的控制逻辑,以添加导航算法或以后的有效载荷控制算法,等等。
回到问题:
"I am having trouble interpreting the system response on varying the constants."
详细说明遇到的有趣或遇到的困难将是有益的。在测试中添加一些响应图可能会给社区带来许多实际的帮助。
第二个问题是关于电机控制输出命令的速率限制。这在很大程度上取决于您期望的性能。该代码仅计算roll_command。如何将其转换为电动机命令是一个相关主题。通常,只要电动机加速度不造成损害,就可以使其尽可能快。
控制器的性能要求(将系统稳定地带入所需状态的速度,应该/可能超调的距离,应具有的阻尼程度)将得出所需的motor_rate_limit。例如,升空可能是性能要求之一。从站立到举起地面,如果需要30秒,是否可以接受?或如果车辆在2秒钟内倾斜60度(如果没有补偿,则升力将下降一半),您突然需要更大的升力。因此,车辆的角度敏捷性会间接影响车辆的提升敏捷性,进而影响马达的控制速度。
3) At what thrust range or values, should the tuning be performed? Minimum, lift off, or mid-range or is it irrelevant?
这很重要。在推力极限时,您将无法使已经处于最大转速的电动机加速。 (除非您永远不允许通过放弃某些性能而超出特定的total_Thrust,这是一种解决方法。)因此,必须最大程度地调节控制器的增益以及运行范围的其他一些点(向前飞行) ,悬停)。提醒:在正常飞行中,最大推力和类似的最小推力测试很难实现。
评论
$ \ begingroup $
导数项也不正确。我将更新答案。导数应乘以误差的导数,而不是误差的差。还应检查比例项。
$ \ endgroup $
–GürkanÇetin
15年6月28日在12:59
$ \ begingroup $
我刚刚找到了进一步检查的时间。只要未定义“滚动”,我对算法的理解就不完整。也许“滚动”已经是状态错误。我对正确性的评论假定“ roll”是状态变量。
$ \ endgroup $
–GürkanÇetin
15年6月28日在16:24
评论
10Hz似乎很慢!我建议您在100Hz-1000Hz范围内进行调整。将其启动到最高可能的速度。我不知道如何将时间缩短到20-40毫秒以下。
更快的微控制器?或者,询问问题“如何优化此PID代码?”。我在PIC18上运行了一个5kHz PID控制回路,该回路还处理CAN总线流量和EEPROM的同时写入。我敢肯定,我们可以采取一些措施来将您的循环时间缩短至少于10ms。
请参阅:robotics.stackexchange.com/questions/143/…
@Rocketmagnet在看到您的评论后,我遍历了源代码并检查了每个主要功能的执行时间。经过一些实验,时间缩短到45毫秒。同样,在45毫秒中,飞行员输入功能消耗了37 ms,这可能是由于pulseIn命令所致。除此之外,IMU正在占用7毫秒。那谢谢啦! 100 Hz也许可以实现。