分享一篇在其他地方看的分享的飞思卡尔控制电机PID算法代码解析的,写得非常的好。
PID实指“比例proportional”、“积分integral”、“微分derivative” , 这三项构成PID基本要素。每一项完成不同任务对系统功能产生不同的影响。 搞软件的往往对硬件不屑 ,却忘了软件再牛B也是为硬件服务的 , PID的数字化算法就完全是为硬件而生的 , 这是控制电机算法的一个难点 , 没有一定的对软硬件的理解 , 就连调试装定PID参数都会很为难 ! 飞思卡尔智能车项目里面就会用到PID算法 , 比如车爬坡和平地连续拐弯时 , 代码里面没有PID算法 , 控制和驱动起来就会很拙急 , 对不对 ? 不过 ,搞清楚问题还是有个前提的 , 那就是懂点微积分 , 不会微积分嘛 , 下面的内容无需关注
实际上 , PID算法的应用基础始于对PCB板上的运放的PID参数进行调校 , P对应于运放增益 ; I 就是运放输入和输出端之间接一个电容引入反馈 , 就是控制器的输出与输入误差会积累起来影响输出 ; D 就是运放输入端串接一个电容 ,起的微分作用是阻止输出与输入误差的变化 . 结合示波器来观察控制电机的PID参数设定的话 , 网上有一首诗 , 它就代表我的心声了 :
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再把微分加
曲线振荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢,微分时间应加长
理想曲线两个波,前高后低四比一
一看二调多分析,调节质量不会低 !
下面贴段代码 (真的是仅供参考):
- #include /* derivative information */
- /*******************************************************************
- * 宏定义
- **********************************************************************************/
- #define STABMAX 50
- #define SENSORNUM 8
- #define SAMPLETIMES 5
- /********************************************************************
- FUNCTION PROTOTYPES
- ********************************************************************/
- int CalculateP(void);
- float CalculatePID(void);
- /********************************** PID控制程序 *******************/
- struct CARSTATE
- {
- int E0;
- int E1;
- int E2;
- int E3;
- float Integral;
- }CarState;
- /*
- ********************************************************************
- * 初始化PID参数
- ********************************************************************/
- void Init_PID()
- {
- CarState.E0 = 0;
- CarState.E1 = 0;
- CarState.E2 = 0;
- CarState.E3 = 0;
- CarState.Integral = 0;
- }
- /*
- ********************************************************************
- * 信号处理函数
- * 程序描述: 对传感器采集过来的数据进行处理,得到一些基本的计算参数
- ********************************************************************/
- int SignalProcess( unsigned int signal )
- {
- const int BitValue[8] = {43,26,12,6,-6,-12,-26,-43}; //MAX:28
- int i,CurrPoint=0,LastPoint=0,BitNum=0;
- unsigned char SignalBit[8];
- for(i=0;i<8;i++)
- {
- SignalBit = signal & 0x0001;
- BitNum += SignalBit;
- signal >>= 1;
- }
- switch(BitNum)
- {
- case 1:
- for(i=0;i<8;i++)
- if(SignalBit != 0)
- CurrPoint += BitValue;
- CarState.E0 = CurrPoint;
- break;
- case 2:
- for(i=0;i<8;i++)
- if(SignalBit != 0)
- CurrPoint += BitValue;
- CurrPoint >>= 1;
- CarState.E0 = CurrPoint;
- break;
- default:
- CarState.E0 = CarState.E1;
- break;
- }
- return CalculateP()*100;
- }
- /*******************************************************************
- * PID计算函数
- * 程序描述: 计算P参数
- ********************************************************************/
- int CalculateP(void)
- {
- CarState.E1 = CarState.E0;
- return((int)CarState.E0);
- }
- /*
- ***********************************************************************************
- * PID计算函数
- *
- * 程序描述: 对传感器采集过来的数据进行处理,得到一些基本的计算参数
- *
- ******************************************************************* ***************/
- float CalculatePID(void)
- {
- float P, I = 0, D;
- /* parameter const */
- float Kp = 1.0, Ki = -0.0002, Kd = -0.0002;
- /* P parameter */
- P = CarState.E0 * Kp;
- /* I parameter */
- if(P+I<2)
- {
- CarState.Integral += Ki * CarState.E0;
- I = CarState.Integral;
- }
- /* D parameter */
- D = Kd * ( CarState.E0 + 3*CarState.E1 - 3*CarState.E2 - CarState.E3 )/6.0;
- CarState.E3 = CarState.E2;
- CarState.E2 = CarState.E1;
- CarState.E1 = CarState.E0;
- return (P+I+D);
- }
复制代码
|