|
本代码采用Proteus仿真,采用51单片机模拟PWM,用定时器获取电机转速信息,用PID算法控制转速,转速、P、I、D都可以用按钮设置,LCD显示屏显示出电机的转速、差值、设定值、P、I、D,并可以粗调跟微调,还有闪烁提示,用来指示当前的设置项目。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
不按设定键直接调整的是设定速度值因为速度值是以周期形式调整,所以速度值越小,转速越高,2秒钟无操作退出设置模式,非设置模式调节转速
单片机源程序如下:
- //************************项目信息**************************
- //项目名称:
- //客户名称:
- //************************文件信息**************************
- //文件名称:pi.c
- //作 者:Lebo
- //文件版本:
- //校 验 和:
- //************************硬件信息**************************
- //目标器件:
- //源 时 钟:
- //UCBA型号:
- //************************平台信息**************************
- //开发环境:
- //烧录环境:
- //配置内容:
- //************************功能信息**************************
- //程序功能:
- //函数列表:
- //************************修改记录**************************
- // <author> <time> <version> <desc>
- //1.Lebo 15/01/11 V1.0 build this moudle
- //2.
- //**********************************************************
- //**********************************************************
- //程序名称:头文件
- //程序说明:
- //**********************************************************
- #include "pid.h"
- //**********************************************************
- //程序名称:增量式PID初始化 函数
- //入口参数:*ptrPID
- //出口参数:e0, e1, e2, ka, kb, kc, kz, max_adjust, max_out, min_out
- //返回参数:
- //调用函数:
- //程序说明:
- //**********************************************************
- void PID_IncInit(PID_TypeDef *ptrPID){
- (* ptrPID).e0 = 0;
- (* ptrPID).e1 = 0;
- (* ptrPID).e2 = 0;
-
- (* ptrPID).ka = 0;
- (* ptrPID).kb = 0;
- (* ptrPID).kc = 0;
- (* ptrPID).kz = 0;
-
- (* ptrPID).maxAdjust = 0;
- (* ptrPID).maxOut = 0;
- (* ptrPID).minOut = 0;
- }
- //**********************************************************
- //程序名称:增量式PID系数设置 函数
- //入口参数:kp, ki, kd, z, *pid_ptr
- //出口参数:ka, kb, kc, kz
- //返回参数:
- //调用函数:
- //程序说明:
- /*
- T--------采样周期
- Ti-------积分时间
- Td-------微分时间
- Kp = Kp
- Ki = Kp*T/Ti
- Kd = Kp*Td/T
- A = Kp+Ki+Kd = Kp*(1 + T/Ti + Td/T)
- B = Kp+2*Kd = Kp*(1 + 2Td/T)
- C = Kd = Kp*Td/T
- *///120,11,0,10
- //**********************************************************
- void PID_IncSetRatio(u8 kp, u8 ki, u8 kd, u8 kz, PID_TypeDef *ptrPID){
- (* ptrPID).ka = kp + ki + kd;
- (* ptrPID).kb = kp + (2 * kd);
- (* ptrPID).kc = kd;
- (* ptrPID).kz = kz;
- }
- //**********************************************************
- //程序名称:PID系数极限设置 函数
- //入口参数:max_ajst, max_outval, min_outval, *pid_ptr
- //出口参数:max_adjust, max_out, min_out
- //返回参数:
- //调用函数:
- //程序说明:
- //**********************************************************
- void PID_IncSetRatioLimit(s8 maxAdjust, u8 maxOut, u8 minOut, PID_TypeDef *ptrPID){
- (* ptrPID).maxAdjust = maxAdjust;
- (* ptrPID).maxOut = maxOut;
- (* ptrPID).minOut = minOut;
- }
- //**********************************************************
- //程序名称:增量式PID 函数
- //入口参数:nonce_error, pid_ptr, out_ptr
- //出口参数:*out_ptr
- //返回参数:
- //调用函数:
- //程序说明:
- /*
- ////位置式PID控制算式
- //// 离散的PID表达式:
- //// U(n) = Kp*{e(n) + (T/Ti)*Sum[e(0)+e(1)...+e(n)] + (Td/T)*[e(n)-e(n-1)]}
- //// U(n) = Kp*e(n) + Ki*Sum[e(0)~e(n)] + Kd*[e(n)-e(n-1)]
- //// 说明:
- //// n--------采样序号,n=0,1,2,…… 。
- //// U(n)-----第n次采样时刻的计算输出量
- //// e(n)-----第n次采样时刻输入的偏差值
- //// e(n-1)---第n-1次采样时刻输入的偏差值
- //// T--------采样周期
- //// Ti-------积分时间
- //// Td-------微分时间
- //// Kp-------比例系数
- //// Ki-------积分系数,Ki = Kp*T/Ti
- //// Kd-------微分系数,Kd = Kp*Td/T
- 增量式PID控制算式(广泛应用)
- 增量式PID控制算法公式:
- dU(n) = U(n)-U(n-1)
- dU(n) = Kp*[e(n)-e(n-1)] + Ki*e(n) + Kd*[e(n)-2*e(n-1)+e(n-2)]
- dU(n) = (Kp+Ki+Kd)*e(n) - (Kp+2*Kd)*e(n-1) + e(n-2)*Kd
- dU(n) = A*e(n) - B*e(n-1) + C*e(n-2)
- 说明:
- T--------采样周期
- Ti-------积分时间
- Td-------微分时间
- Kp = Kp
- Ki = Kp*T/Ti
- Kd = Kp*Td/T
- A = Kp+Ki+Kd = Kp*(1 + T/Ti + Td/T)
- B = Kp+2*Kd = Kp*(1 + 2Td/T)
- C = Kd = Kp*Td/T
- 由于单片机的处理速度和ram 资源的限制,一般不采用浮点数运算,而将所有参数全部用整
- 数,运算到最后再除以一个2的N次方数据(相当于移位),作类似定点数运算,可大大提高
- 运算速度,根据控制精度的不同要求,当精度要求很高时,注意保留移位引起的“余数”,做
- 好余数补偿。
- */
- //**********************************************************
- void PID_IncCompute(s16 offset, u8 *ptrOut, PID_TypeDef *ptrPID){
- s16 outResult = (s16)(* ptrOut);
- s32 median;
- s8 adjust;
- (* ptrPID).e2 = (* ptrPID).e1;
- (* ptrPID).e1 = (* ptrPID).e0;
- (* ptrPID).e0 = offset;
- median = (s32)(* ptrPID).ka * (* ptrPID).e0 -\
- (s32)(* ptrPID).kb * (* ptrPID).e1 +\
- (s32)(* ptrPID).kc * (* ptrPID).e2;
- median = median >> (* ptrPID).kz;
- if(median < -(* ptrPID).maxAdjust)
- adjust = -(* ptrPID).maxAdjust;
- else if(median > (* ptrPID).maxAdjust)
- adjust = (* ptrPID).maxAdjust;
- else
- adjust = (s8)median;
- outResult += adjust;
- if(outResult > (* ptrPID).maxOut)
- outResult = (* ptrPID).maxOut;
- else if(outResult < (* ptrPID).minOut)
- outResult = (* ptrPID).minOut;
- *ptrOut = (u8)outResult;
- }
复制代码
所有资料51hei提供下载:
PID Proteus.rar
(172.39 KB, 下载次数: 382)
|
评分
-
查看全部评分
|