找回密码
 立即注册
查看: 588|回复: 0

速度PID参数整定困难?来尝试位置PID实现的速度控制!

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2024-5-28 21:09:30 | 显示全部楼层 |阅读模式
本算法结构适用情况:带有位置编码器的电机对象、想要实现更快速度响应的控制、实现0速度状态的完全锁定。


最近看到有智能车的车友调速度环感觉不好调,特来分享一下经验。
先讲一下我这个通过位置环实现的速度控制优点——没有速度观测误差,速度调整性能等同于位置环调整性能。


首先说一下为什么会感觉速度环难以调节。因为速度环在测量速度的时候,会引入一个观测误差。无论是使用M法测速(计算一段时间内的脉冲数量),还是T法测速(计算两个脉冲之间的时间差)。都会出现周期短速度数据波动大 ,周期长速度数据引入延迟变得难以使用PID控制。
尽管可以使用M/T法进行混合测量,但是对M/T的权重和切换又显得较为麻烦。


但是位置环就显得好实现的多,因为位置是绝对记忆的。只需要对所有的脉冲数量进行积分,也只用关心距离目标位置还有多少个脉冲。并不需要考虑时间差的问题。既然位置环性能这么好,那么当然也可以用位置环实现速度控制。
事实上,常见的伺服控制器(脉冲控制型)就是这种原理,每次发送一个脉冲就转动一点点距离,通过控制脉冲发送频率的变化实现速度的控制。
那么,如果要实现这样一个特殊的速度环,我们应该如何使用代码实现呢?
下面以我的STC-FOC Lite中代码举例,其他类型的电机和编码器实现的方式也是大同小异
  1. void SPI_DMA_Isr(void) interrupt DMA_SPI_VECTOR
  2. {
  3.     CSN = 1;                       // 拉高使能,结束读取
  4.     if ((DMA_SPI_STA & 0x04) == 0) // 正常进入
  5.     {
  6.         _angle_this_dat = (((Encoder_Data[0] << 8) | (Encoder_Data[1] & 0xfc)) >> 2);//获取单圈绝对位置数据
  7.         //增量编码器可以统计两次中断之间的脉冲个数
  8.         _angle_dangle = (_angle_this_dat - _angle_last_dat);//计算角度差值
  9.         //绝对值编码器的过零点处理,增量编码器不需要
  10.         if (_angle_dangle < -(Encode_bit_Max / 2))
  11.         {
  12.             _postion_add_dat++;//圈数自增
  13.             _angle_dangle += Encode_bit_Max; // 过零处理
  14.         }
  15.         if (_angle_dangle > (Encode_bit_Max / 2))
  16.         {
  17.             _postion_add_dat--;//圈数自减
  18.             _angle_dangle -= Encode_bit_Max;
  19.         }
  20.         //postion_add为目标位置累加变量,判断超过1(编码器最小分辨率)后,将整数部分添加进入电机的设定位置
  21.         if (fabs(postion_add) > 1 && Mode == Speed_Mode && Run_Flag)
  22.         {
  23.             moto.set_postion += (long)postion_add;
  24.             postion_add -= (long)postion_add; // 自减整数部分,因为这部分已经添加进入设置位置了
  25.         }
  26.         // 圈数累计,可以累计正负2^31圈
  27.         _angle_last_dat = _angle_this_dat;
  28.     }
  29.     DMA_SPI_STA = 0; // 清除中断标志位
  30. }
复制代码
这部分是有关于中断的处理,其中过零处理是绝对值编码器才需要进行的操作,增量式编码器不需要。这部分主要的功能就是获取增加的角度,并且积分进入绝对位置。
并且将速度转换成的设定位置添加进入设定位置,这里因为编码器最小分辨率为1。但是累加的最小分辨率可能会很小,所以做了一个分辨率转换功能。只有超过1的部分才会添加进入设定位置。
否则就等待继续累加超过1。
  1. // 根据速度调整位置设定@30us
  2. float postion_add = 0;           // 小于分辨率编码器时的累加器
  3. long last_postion_add = 0; // 上次增量记忆
  4. void Timer0_Isr(void) interrupt TMR0_VECTOR
  5. {
  6.         if (Mode == Speed_Mode && Run_Flag && moto.set_speed != 0 && I_Error_Cnt < I_Error_Dat)
  7.         {
  8.                 postion_add += (float)moto.set_speed * 30.0 * (1.6384 / 6000.0); // us
  9.         }
  10. }
复制代码
这里就是一个普通的定时器,通过读取设定速度乘以指定的时间系数变换成位置信息。
剩下就是通过设定的位置信息moto.set_postion实现一个速度环,即可实现基于位置环的速度控制。
此时的速度控制将完全没有观测误差(因为位置采用积分,所以设定的位置信息一定会到达)
此时就算位置环调的参数不够理想,没能到达指定速度,也会在设定速度变成0后继续旋转到指定位置才停下(当然这种情况是不对的,说明位置环参数还需要调整的更加灵敏一些)
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 08:45 , Processed in 0.117666 second(s), 44 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表