找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3345|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机PID示例程序及Proteus仿真实现 TLC5615+LTC1292采集

[复制链接]
跳转到指定楼层
楼主
示波器图中,紫色线高点是3.5v,低点是1.5v
一一对应程序中的getset(350),getset(150)
仿真正确
此pid封装成.c .h文件形式,可以直接调用

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


(1) 了解工业过程控制的一般情况;
(2)  掌握数字PID控制器程序设计方法;

2.实验内容
设计单片机控制电路,采用TLC5615和LTC1292芯片采集电压和输出电压,并编写数字PI控制器程序,对直流电机进行控制,要求采样周期100毫秒,对设定值转速和实际转速进行实时显示。
PID采用增量式,定点计算,输入要滤波,输出要限幅。

3、预备知识
控制系统软件的设计,一般必须有严格的时间限制,故必须基于定时中断进行设计,在中断中运行实时性要求的程序,如A/D采样程序、PID控制程序、D/A输出程序、数码管显示刷新程序和键盘扫描程序等。在主程序中进行一些实时性要求低的程序,如打印程序、数据输入程序等。

4、实验步骤
从D/A输出点接一个二阶惯性对象,将对象输出接A/D输入点。
在PC机输入源程序并汇编,然后下载到单片机上,进行调试。
注意二阶系统的电路需要与单片机共地

(1) 整理好实验程序。
(2) 总结比例参数P积分参数I和采样周期对控制系统性能的影响。

单片机源程序如下:
PID.C
  1. #include "pid.h"

  2. PID pid;

  3. void PIDParament_Init()  //
  4. {
  5.     pid.choose_model = MODEL_PID;
  6.     pid.T=5;                //采样周期
  7.                 pid.set =280;            //用户设定值
  8.     pid.Kp=20;                //比例系数
  9.     pid.Ti=100;                //积分比例常数
  10.     pid.Td=5;                //微分时间常数
  11.     pid.OUT0=0;                //一个维持的输出

  12.     pid.pwmcycle = 280;    //PWM的周期
  13. }

  14.    
  15. void pid_calc()  //pid计算
  16. {
  17.   float dk1;float dk2;
  18.   float t1,t2,t3;   
  19. //    if(pid.Tdata < (pid.T))  //最小计算周期未到
  20. //     {
  21. //            return ;
  22. //     }
  23. //    pid.Tdata = 0;
  24.     pid.curr=LTC1292();                //A/D输入值
  25.                  
  26.     pid.En=pid.set-pid.curr;  //本次误差
  27.                  
  28.                  
  29.     dk1=pid.En-pid.En_1;   //本次误差与上次误差之差
  30.     dk2=pid.En-2*pid.En_1+pid.En_2;        //理解为第二个误差
  31.    
  32.                 t1=pid.Kp*dk1;                            //比例
  33.    
  34.     t2=(pid.Kp*pid.T)/pid.Ti;      //积分
  35.     t2=t2*pid.En;
  36.    
  37.     t3=(pid.Kp*pid.Td)/pid.T;        //微分
  38.     t3=t3*dk2;
  39.    
  40.     switch(pid.choose_model)
  41.      {
  42.          case MODEL_P:     pid.Dout= t1;    //仅使用P计算               
  43.                         
  44.              break;
  45.          
  46.          case MODEL_PI:  pid.Dout= t1+t2;    //使用PI计算            
  47.                         
  48.              break;
  49.                  
  50.          case MODEL_PID: pid.Dout= t1+t2+t3; //使用PID计算      

  51.              break;
  52.      }
  53.          
  54.     pid.currpwm+=pid.Dout;  //本次应该输出的PID
  55. //    if(pid.currpwm>pid.pwmcycle)            //判断本次输出的PID在输出要求之间
  56. //    {
  57. //      pid.currpwm=pid.pwmcycle;
  58. //    }
  59. //    if(pid.currpwm<0)
  60. //    {
  61. //     pid.currpwm=0;
  62. //    }
  63.     if(pid.currpwm>1023*15) pid.currpwm=1023*15;//输出扩大,使效果明显
  64.                 if(pid.currpwm<0) pid.currpwm=0;
  65.     pid.En_2=pid.En_1;//每次更新的交换,先交换e2的值,再交换e1
  66.     pid.En_1=pid.En;
  67.     //此处输出PWM
  68.                 TLC5615(pid.currpwm/15);
  69. }
复制代码
  1. #include <reg52.h>
  2. #include <pid.h>
  3. #define  uchar unsigned char
  4. #define  uint unsigned int
  5. #define  ulong unsigned long
  6. //sfr AUXR =0x8E;
  7. sbit ADAT=P2^5;
  8. sbit ACLK=P2^6;
  9. sbit ACS =P2^7;
  10. sbit Set=P3^7;
  11. uint LTC1292(void)        //输入值
  12. {
  13.         uint i,x;
  14.         ACLK=0; ADAT=1; ACS=0;
  15.         for(i=0;i<14;i++)
  16.         {
  17.                 ACLK=1;         
  18.                 x<<=1;
  19.                 if(ADAT==1) x++;
  20.                 ACLK=0;
  21.         }
  22.         ACS=1;
  23.         return (x&0xfff);
  24. }
  25. sbit DDAT  = P3^4;
  26. sbit DCS  = P3^3;
  27. sbit DCLK  = P3^2;
  28. void TLC5615(uint j) //输出值,PID计算后输出
  29. {
  30.   uchar i;
  31.   DCLK=0; DCS=0;
  32.   j=j<<6;
  33.   for(i=0;i<12;i++)
  34.   {
  35.     j=j<<1; DDAT=CY;
  36.     DCLK=0;  DCLK=1;
  37.   }
  38.   DCLK=0; DCS=1;
  39. }
  40. #define kp 20                //比例系数
  41. #define ki 1                //积分系数
  42. #define kd 15                //微分系数
  43. #define TIM -10000                //采样周期
  44. int e0=0,e1=0,e2=0;                //三个时刻
  45. int s;                                        //增量式PID计算本次应该输出的增量值
  46. uint r,y;                                //r是实际要求的输出,Y是A/D传过来的输出
  47. long u;                                       
  48. void PID_in() interrupt 3
  49. {
  50. //        float dk1,dk2;
  51. //        float t1,t2,t3;//分别为比例、积分、微分
  52.   TH1=TIM>>8; TL1=TIM&0Xff;
  53. //  y=LTC1292();                //A/D输入值
  54. //  e2=e1=e0;
  55. //        e0=r-y;        //本次误差
  56. //        
  57. //        dk1 = e0-e1;//上一次误差
  58. //        dk2 = e0-2*e1+e2;//上上次误差
  59. //        
  60. //  u+=dk1*kp+e0*ki+dk2*kd;        
  61. //  if(u>1023*kd) u=1023*kd;
  62. //  if(u<0) u=0;
  63. //  s=u/kd;
  64. //  TLC5615(s);
  65.         pid_calc();
  66. }

  67. uint GetSet(ulong x)
  68. {
  69.   ulong m;
  70.   m=x*4095;
  71.   return m/500;
  72. }
  73. void main()
  74. {
  75.   IE=0x88;TMOD=0X11;
  76.   TH1=TIM>>8; TL1=TIM&0xff;TR1=1;
  77.         PIDParament_Init();
  78.   while(1)
  79.   {
  80.                
  81.     if(Set)        pid.set=GetSet(350);
  82.                 else  pid.set=GetSet(150);
  83.                
  84.   }
  85. }
复制代码

仿真代码资料51hei附件下载:
PID资料.7z (106.09 KB, 下载次数: 78)

评分

参与人数 1黑币 +80 收起 理由
admin + 80 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶1 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表