DSP28335实现PID闭环
1 Simulink下的模型及结果
给定参考是0.5,经过PID,然后执行机构,最后输出,Simulink的仿真结果如下:
Kp=10;Ki=5;Kd=0.5


2 增量式PID介绍
采用增量式PID算法:

比例P:e(k) - e(k-1),这次误差 - 上次误差
积分I:e(i),误差
微分D:e(k) - 2e(k-1) + e(k-2),这次误差 - 2*上次误差 + 上上次误差
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| clc clear all; close all;
ts=0.001; sys=tf(400,[1,50,0]); dsys=c2d(sys,ts,'z'); [num,den]=tfdata(dsys,'v');
u_1=0.0;u_2=0.0;u_3=0.0; y_1=0;y_2=0;y_3=0; x=[0,0,0]';
error_1=0; error_2=0; for k=1:1:1000 time(k)=k*ts; yd(k)=2.0; kp=8; ki=0.2; kd=10; du(k)=kp*x(1)+kd*x(2)+ki*x(3); u(k)=u_1+du(k); if u(k)>10 u(k)=10; end if u(k)<-10 u(k)=-10; end y(k)=-den(2)*y_1-den(3)*y_2+num(2)*u_1+num(3)*u_2; u_3=u_2;u_2=u_1;u_1=u(k); y_3=y_2;y_2=y_1;y_1=y(k); error=yd(k)-y(k); x(1)=error-error_1; x(2)=(error-error_1)-(error_1-error_2); x(3)=error; error_2=error_1; error_1=error; end figure(1); plot(time,yd,'r',time,y,'b','linewidth',2); xlabel('时间(s)'); ylabel('误差'); grid on title('增量式PKD跟踪响应曲线'); legend('理想位置','位置追踪'); figure(2); plot(time,yd-y,'r','linewidth',2); xlabel('时间(s)');ylabel('误差'); grid on title('增量是PID跟踪误差');
|
运行结果:

参考材料《MATLAB_SIMULINK系统仿真》
C语言实现增量式PID:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| typedef struct PID { float P,I,D,limit; }PID; typedef struct Error { float Current_Error; float Last_Error; float Previous_Error; }Error;
int32 PID_Increase(Error *sptr, PID *pid, int32 NowPlace, int32 Point) { int32 iError, Increase; iError = Point - NowPlace; Increase = pid->P * (iError - sptr->Last_Error) + pid->I * iError + pid->D * (iError - 2 * sptr->Last_Error + sptr->Previous_Error); sptr->Previous_Error = sptr->Last_Error; sptr->Last_Error = iError; return Increase; }
|
3 增量式PID之Matlab-simulink仿真
模型建立:

PID参数设置:

运行结果:


4 DSP实现
包括两块:定时器0中断,PID函数。主要就是在中断函数中实现PID。
定时器0中断函数及PID初始化,运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| void TIM0_Init(float Freq,float Period) { EALLOW; SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK=1; EDIS; EALLOW; PieVectTable.TINT0=&TIM0_IRQn; EDIS; CpuTimer0.RegsAddr = &CpuTimer0Regs; CpuTimer0Regs.PRD.all = 0xFFFFFFFF; CpuTimer0Regs.TPR.all = 0; CpuTimer0Regs.TPRH.all = 0; CpuTimer0Regs.TCR.bit.TSS = 1; CpuTimer0Regs.TCR.bit.TRB = 1; CpuTimer0.InterruptCount = 0; ConfigCpuTimer(&CpuTimer0, Freq, Period); CpuTimer0Regs.TCR.bit.TSS=0; IER |= M_INT1; PieCtrlRegs.PIEIER1.bit.INTx7 = 1; EINT; ERTM; }
void PID_initial(void) { pidStr.KP=10; pidStr.KI=5; pidStr.KD=0.5; }
float PID_control(float adcvalue, float ref) { float Inck=0.0; pidStr.Ek=ref-adcvalue; Inck = pidStr.KP*(pidStr.Ek - pidStr.Ek_1) + pidStr.KI*pidStr.Ek + pidStr.KD*(pidStr.Ek - 2*pidStr.Ek_1 + pidStr.Ek_2); pidStr.Ek_2 = pidStr.Ek_1; pidStr.Ek_1 = pidStr.Ek; pidStr.dacOut = pidStr.dacOut + Inck*1.000/60; if(pidStr.dacOut < 0.0000) pidStr.dacOut = 0.0000; if(pidStr.dacOut > 0.7) pidStr.dacOut = 0.7; return pidStr.dacOut; }
interrupt void TIM0_IRQn(void) { EALLOW; LED2_TOGGLE; PID_control(a,0.5); DELAY_US(1); a=1.5*pidStr.dacOut; aa[ai]=a; ai++; PieCtrlRegs.PIEACK.bit.ACK1=1; EDIS; }
|
主函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void main() { InitSysCtrl(); p=0; a=0.0; ai=0; LED_Init(); int i; for(i=0;i<500;i++) { aa[i]=0; } InitPieCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); PID_initial(); TIM0_Init(150,1000); while(1) { p++; if((p%2)==0) { LED1_TOGGLE; } } }
|
全局变量的定义:
1 2 3 4 5 6
| #include “canshu.h” PID_ValueStr pidStr; float32 a; float32 aa[500]; Uint16 ai;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| extern float32 m[100]; extern float32 aa[500]; extern float32 a; extern Uint16 ai;
typedef struct { float KP; float KI; float KD; float Ek; float Ek_1; float Ek_2; float dacOut; } PID_ValueStr;
extern PID_ValueStr pidStr;
|
最终效果:
