打印
[DSP编程]

直流电机PID控制----剖析

[复制链接]
2030|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

/*******************************************************************/
#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "DSP281x_Examples.h"   // DSP281x Examples Include File
#define PERIOD 20000
/*******************************************************************/
unsigned int rc=4;     //设定转速rc   (round/0.1s)必须为整数(3~5)
                       //在图形窗口观察到的是10*rc   (round/s)
unsigned int curve[1000];
unsigned int int_flag=0;
unsigned int count1=0;
unsigned int count2=0;
double percent=0.0;
unsigned int i=0;
unsigned int j=0;
unsigned int k=0;
unsigned int m=0;
unsigned int n=0;
unsigned int high=0;
unsigned int low=0;
double e0,e1,e2,y0,y1,y2,x;
double Kp =3;          //3比例系数   
double Ti = 1.0;       //积分时间常数
double Td = 0.2;       //微分时间常数
double T = 0.1;        //采样周期
double a0,a1,a2;
void init_xint2()               //中断pdpintb初始化子程序
{
      XIntruptRegs.XINT2CR.all=0x0001;                           
}
void init_timer1(void)
{
    // Initialize EVA Timer 1:
    // Setup Timer 1 Registers (EV A)
    EvaRegs.GPTCONA.all = 0;
   
    // Set the Period for the GP timer 1 to 0x8200;
    EvaRegs.T1PR = 0xB200;       // Period
    EvaRegs.T1CMPR = 0x0000;     // Compare Reg
   
    // Enable Period interrupt bits for GP timer 1
    // Count up, x128, internal clk, enable compare, use own period
    EvaRegs.EVAIMRA.bit.T1PINT = 1;
    EvaRegs.EVAIFRA.bit.T1PINT = 1;
    // Clear the counter for GP timer 1
    EvaRegs.T1CNT = 0x0000;
    EvaRegs.T1CON.all = 0x1742;
    // Start EVA ADC Conversion on timer 1 Period interrupt
    EvaRegs.GPTCONA.bit.T1TOADC = 2;
}
interrupt void xint2_isr()        //外部中断2中断子程序
{   
     count1++;                  //转速计累加
  // Acknowledge interrupt to receive more interrupts from PIE group 2
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
     return;                                
}
interrupt void timer1_isr()        //定时中断子程序      
{
     if(int_flag==1)
     {
       y2 = y1;
       y1 = y0;
       y0 = count1;
       e0 = rc - y0;
       e1 = rc - y1;
       e2 = rc - y2;
       percent=(a0*e0 - a1*e1 + a2*e2)*0.05;
       high+=PERIOD*percent;
       //if(high>=20000)high=20000;
       if(high<=0)high=0;
       low=PERIOD-high;
     }
     if(n==10)
     {
        curve[m]=count2;
        m++;
        n=0;
        count2=0;
     }
     n++;
     count2+=count1;
     count1=0;                  //转速计清零
     
   // Enable more interrupts from this timer
   EvaRegs.EVAIMRA.bit.T1PINT = 1;
   // Note: To be safe, use a mask value to write to the entire
   // EVAIFRA register.  Writing to one bit will cause a read-modify-write
   // operation that may have the result of writing 1's to clear
   // bits other then those intended.
   EvaRegs.EVAIFRA.all = BIT7;
   // Acknowledge interrupt to receive more interrupts from PIE group 2
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
     return;
}
               
void main()
{
   int m;
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP281x_SysCtrl.c file.
   InitSysCtrl();
   
// Disable CPU interrupts
   DINT;
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.  
   InitPieCtrl();
   
// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).  
   InitPieVectTable();
   
    EALLOW;      
    GpioMuxRegs.GPFMUX.all=0xffff;      //as xf         
//    GpioMuxRegs.GPBMUX.all=0x0000;      //as GPIO
//    GpioMuxRegs.GPBDIR.bit.GPIOB15=1;       //GPIOB15 as output           
    EDIS;
   
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.  
   EALLOW;  // This is needed to write to EALLOW protected registers
   PieVectTable.T1PINT = &timer1_isr;
   PieVectTable.XINT2 = &xint2_isr;
   EDIS;
// This function is found in DSP281x_InitPeripherals.c
// InitPeripherals(); // Not required for this example  
   
   init_xint2();
   
   init_timer1();
   
    PieCtrlRegs.PIEIER1.all = M_INT5;  //xint2
     
    // Enable PIE group 2 interrupt 4 for T1PINT
    PieCtrlRegs.PIEIER2.all = M_INT4;
    IER |= M_INT1 ;//xint2
// Enable CPU INT2 for T1PINT
    IER |= M_INT2 ;
// Enable global Interrupts and higher priority real-time debug events:
    EINT;   // Enable Global interrupt INTM
    ERTM;   // Enable Global realtime interrupt DBGM
     
     for(m=0;m<1000;m++)
     {
       curve[m]=0;
     }
     
     a0 = Kp*(1.0 + T/Ti + Td/T);
     a1 = Kp*(1.0 + 2.0*Td/T);
     a2 = Kp*Td/T;
     e0=e1=e2=y0=y1=y2=0;
     for(i=0;i<5000;i++)       //启动电机,使之处于高速状态
     {
       for(j=0;j<5000;j++)
//       GpioDataRegs.GPBDAT.bit.GPIOB5=0;     //PWM12引脚为低   
         asm(" clrc xf");
     }
     int_flag=1;
     
     for(;;)                  
     {
//       GpioDataRegs.GPBDAT.bit.GPIOB5=0;     // as low ;     //PWM12/io7引脚为低
       asm(" clrc xf");
       for(j=0;j<high;j++);
//       GpioDataRegs.GPBDAT.bit.GPIOB5=1;     // as high      //PWM12/io7引脚为高
       asm(" setc xf");
       for(k=0;k<low;k++);
     }
}  

直流电机PID控制实验.zip

288.72 KB

PID电机

相关帖子

沙发
zhangmangui| | 2016-7-19 22:15 | 只看该作者
感谢分享

使用特权

评论回复
板凳
山东电子小菜鸟|  楼主 | 2016-7-20 13:16 | 只看该作者

谢谢老大

使用特权

评论回复
地板
qwer0145| | 2016-7-20 16:23 | 只看该作者
问个问题,如果我的电机转速每20ms算一次,那么转速单闭环时的控制频率该用多少?

使用特权

评论回复
5
山东电子小菜鸟|  楼主 | 2016-7-20 21:54 | 只看该作者
20ms

使用特权

评论回复
6
山东电子小菜鸟|  楼主 | 2016-7-20 21:54 | 只看该作者
20ms

使用特权

评论回复
7
海中水| | 2016-7-20 22:34 | 只看该作者
不错,更期待能把整个设计思路写一下我们一些学习一下、

使用特权

评论回复
8
llstarh| | 2016-7-29 17:19 | 只看该作者
计算周期大于等于采样周期,采样周期要应用山农定理来确定。

使用特权

评论回复
9
qingf25| | 2016-9-1 10:26 | 只看该作者
感谢分享~~

使用特权

评论回复
10
山东电子小菜鸟|  楼主 | 2017-3-17 17:25 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq:641208111;技术交流群:377640799 大学电子竞赛预热赛开赛啦~千元大奖等你来拿火热进行中!!点击参加活动 欢迎加个人QQ:641208111一起交流合作

140

主题

3082

帖子

23

粉丝