在使用PID时往往会出现加速度过大不和预期的情况,为了提高电机运载物品稳定度,我们需要充分考虑原有的PID存在的问题,即参数固定。所以常用办法是通过对PID在特定时间的参数RESET实现加速度控制,但是调节参数毕竟不太方便,且程序不具备通用性,所以能不能设计出一种较为通用的办法去控制PID加速度呢?
由此出发,我们分析一下PID常用的控制,其控制缺乏前置反馈,是针对现有测得数据进行计算,所以应当考虑加入前置控制,最简单的办法是先在知道要加速前先设定一个较低的速度环预期速度,从而使加速度较小,但是如果前置速度环预期速度和后面的SETSPEED相差较大仍然会导致较大的波动与加速,这种方式更适合在减速时使用(速度环),所以如果我们增加前置速度设置呢,是不是就可以进行离散化,运用分辨率的思想,我们这样设计程序
设计一个全局变量做传递量(如果采用全局结构体更好)做出一个填充值设计函数,然后通过定时器扫描实现
/**
* @brief 直线PID加速度离散控制法,核心思路是通过将目标值进行拆分逐步逼近以控制加速度()
* @param direction:设置横向或正向 forward = 0,sidle = 1
* @param MODE:模式选择 分为SPEED_MODE 和 POSITION_MODE(双环)
* @param setspeed: 设置速度目标值(单环).
* @param setlocation_cycles:位置输出轴圈数增加
* @param setlocation_microtarget:位置输出轴角度增加
* @param resolution_ratio:分辨率设置,控制每次扫描增加目标值比例
* @param interval_time:间隔时间用于每次离散延时
* @return 成功为1,失败-1.
*/
//设计思路是先将定时器开启,从定时器内执行函数,再控制加速量并增加次数
int accelerated_speed(uint8_t direction,uint8_t MODE,__IO float setspeed,__IO int32_t setlocation_cycles,
__IO int32_t setlocation_microtarget,uint32_t resolution_ratio,uint16_t interval_time)
{
//填充全局变量
accelerated_direction = direction;
accelerated_MODE = MODE;
accelerated_setspeed = setspeed;
accelerated_setlocation_cycles = setlocation_cycles;
accelerated_setlocation_microtarget = setlocation_microtarget;
accelerated_resolution_ratio = resolution_ratio;
accelerated_interval_time = interval_time;
TIMCOMMON9_Configuration(interval_time);//开启扫描定时器
// for(int i = 1;i<=resolution_ratio;i++)
// {
// if(MODE == SPEED_MODE)
// {
// int16_t average_speed = 0,disperse_speed = 0;//离散设置速度
// average_speed = (MOTORSPEED[0]+MOTORSPEED[1]+MOTORSPEED[2]+MOTORSPEED[3])/4;
// disperse_speed = average_speed + (1/resolution_ratio)*i*(setspeed - average_speed);
// if(direction == forward)
// {
// motor_straight_control(SPEED_MODE,disperse_speed,0,0);
accelerated_speed_time = interval_time;
//
accelerated_speed_delayms();
// }
// else if(direction == sidle)
// {
// motor_straight_control_sidle(SPEED_MODE,disperse_speed,0,0);
accelerated_speed_time = interval_time;
//
accelerated_speed_delayms();
// }
// else return -1;
// }
// if(MODE == POSITION_MODE)
// {
//
// }
// }
// return 1;
}
void TIM1_BRK_TIM9_IRQHandler(void)
{
if(TIM9CNT<=accelerated_resolution_ratio)
{
if(accelerated_MODE == SPEED_MODE)
{
int16_t average_speed = 0,disperse_speed = 0;//离散设置速度
average_speed = (MOTORSPEED[0]+MOTORSPEED[1]+MOTORSPEED[2]+MOTORSPEED[3])/4;
disperse_speed = accelerated_setspeed + (1/accelerated_resolution_ratio)*TIM9CNT*(accelerated_setspeed - average_speed);
if(accelerated_direction == forward)
{
motor_straight_control(SPEED_MODE,disperse_speed,0,0);
}
else if(accelerated_direction == sidle)
{
motor_straight_control_sidle(SPEED_MODE,disperse_speed,0,0);
}
else return ;
}
if(accelerated_MODE == POSITION_MODE)
{
int16_t disperse_position = 0;//离散设置位置
__IO float DIF = 0;
DIF = target_transform[0]+TRANSFORM_TARGET(accelerated_setlocation_cycles,accelerated_setlocation_microtarget) - NOWMEASURE[0];//位置差值计算
disperse_position = (1/accelerated_resolution_ratio)*TIM9CNT*DIF;//以0号电机为参考量
if(accelerated_direction == forward)
{
//调用底层直接增加设置位置量减去反复转换过程 本代码为四电机直行控制底层
positioncmd = 1;//设置双环控制
for(int x=0;x<4;x++)
{
cmdaddflag[x] = 1;//开启增加位置量
}
//设置增加位置量
Delta_microtarget[0] = disperse_position;
Delta_microtarget[1] = -disperse_position;
Delta_microtarget[2] = disperse_position;
Delta_microtarget[3] = -disperse_position;
}
else if(accelerated_direction == sidle)
{
positioncmd = 1;//设置双环控制
for(int x=0;x<4;x++)
{
cmdaddflag[x] = 1;//开启增加位置量
}
//设置增加位置量
Delta_microtarget[0] = -disperse_position;
Delta_microtarget[1] = -disperse_position;
Delta_microtarget[2] = disperse_position;
Delta_microtarget[3] = disperse_position;
}
else return ;
}
else return ;
}
else
{
TIM9CNT = 0;
return ;
}
TIM9CNT++;
}
如此一来就实现了速度环的加速度控制,具体值仍然需要根据与其加速度控制
同理,我们把相同的思想运用到位置环上,但是这里有一个问题,位置环本身并不能直接控制速度,要通过计算后的值带入速度环才是最终输出电流值,所以我们直接离散控制速度就不行了,这时候,我们可以根据位置环的特点,控制最大速度,即通过离散化控制位置环最大速度实现对位置环的加速度控制,具体代码可以参考上面,仅需将对目标速度控制换为位置环最大速度即可,这里要再次强调,不要使用离散化的目标位置控制,首先是离散化位置控制会导致误差加大,预期位置必须设计成累加式而不是直接赋值,同时如何确保中间没有较大卡顿也是难点,所以采用最大速度控制法较好,既能避免位置环加速过快,又能有效保证连续性与计算准确度,防止跃迁。
以上就是关于PID加速度的一点示例,当然鉴于笔者能力有限,在此抛砖引玉,希望能向各位学到更好的改进办法。
于2023年8月5日