关键词:
STM32F103C8T6,MPU6050,DMP
问题描述:
在给小车进行PID调参时,小车无论如何也不收敛,永远会发散震荡,根本停不下来,误差越震越大。
问题排查:
进行问题排查后,发现是采样频率的问题。
互联网上的开源方案大多是采用MPU6050+外部中断方式。而我选择使用stm32的TIM3作为中断源,将采样函数方式在中断函数内,72M系统时钟,7199分频系数,49预装载值。
我原以为这样可以实现200HZ的采样频率,但是我错了。真实的采样时间,是从定时器一次中断标志位清零到下一次中断标志位清零的时间。而为了防止中断溢出,我的定时器清零位放置在中断函数的末尾,也就是说,我实际的一次采样时间,是定时器的5ms+中断函数执行的时间。而由于MPU6050的I2C通信又是一个相对耗时的任务,所以我的实际的一次采样时间远大于5ms,这也就导致了无论怎么调节参数,小车都无法收敛,因为采样频率达不到要求。
而采取外部中断的方式则不会有这种担忧,因为中断源和MCU是并行关系。
问题解决:
在定时器初始化时,将定时器的预装载值从49调小到24,问题解决。
一些思考:
其实修改定时器预装载值并不是一个很好的方案,因为会导致采样频率不精确。
除了修改定时器的预装载值,还可以将清零标志位移动到中断函数的开头。这样精确得到了保证,但是却增加了溢出的风险。
目前我能想到的最好的办法,是将采样函数放在main函数内,在中断函数内放置一个全局的flag并将其置为1,在主函数内查询这个flag,作为采样函数的触发条件,等待采样结束后,将这个flag置为0。这样,可以在保证精度的前提下杜绝中断溢出的风险。