DSPwilliam hill官网
直播中

王锁

8年用户 28经验值
擅长:处理器/DSP 控制/MCU
私信 关注

利用DSP2812编写直流电机PID调速程序(C语言)

本人现在已经通过DSP2812中SCIA接收上位机发送的数据来控制电机的转速,采用CAP3来捕获光电编码器来测量电机的转速,现在想在程序里面添加PID调节电机的转速,主要通过PID输出调整PWM波形的占空比来调节电机的转速,请各位大神赐教
已退回3积分

回帖(16)

杨森

2017-9-6 23:55:57
赞赞赞赞赞赞赞赞赞赞
举报

队长shiwo

2017-9-7 16:26:13
回帖是美德!
举报

1406093611

2017-9-11 12:04:07
看楼主所说,现在是由上位机来控制电机转速,现在是想加入PID来实现电机转速的调速。楼主可以先将上位机发送给DSP的数据作为电机转速的目标值,由CAP采集回来的编码器的值作为当前的电机转速值,然后通过标准PID公式进行控制即可(PID这一块可以在网上查点资料了解一下)。祝楼主能够顺利实现串口+PID电机控制!
举报

2大爷

2017-9-11 21:38:01
请联系我,数字增量式PID调节,PWM输出
举报

王锁

2017-9-12 10:42:56
引用: 1406093611 发表于 2017-9-11 12:04
看楼主所说,现在是由上位机来控制电机转速,现在是想加入PID来实现电机转速的调速。楼主可以先将上位机发送给DSP的数据作为电机转速的目标值,由CAP采集回来的编码器的值作为当前的电机转速值,然后通过标准PID公式进行控制即可(PID这一块可以在网上查点资料了解一下)。祝楼主能够顺利实现串口+PID电机控制! ...

你好,我已经实现了上位机发送数据控制电机转速,并CAP捕获光电编码器的值计算电机转速,但是我不晓得该把PID程序放在什么位置,什么时候进行调速,可否指导一下
举报

1406093611

2017-9-12 11:32:40
引用: MMMEEELLL 发表于 2017-9-12 10:42
你好,我已经实现了上位机发送数据控制电机转速,并CAP捕获光电编码器的值计算电机转速,但是我不晓得该把PID程序放在什么位置,什么时候进行调速,可否指导一下

你可以单独建一个PID源文件,PID主要用于反馈回来的电机实际转速的参数进行矫正,比如在这里,DSP从上位机接收到了电机转速的目标值,而实际的转速值与设定的目标值不一致,就可以通过PID控制让实际转速达到目标值。PID程序放在哪里不重要,重要的是你要调用PID的子程序来实现参数的控制,将PID处理过的数据,转变为控制电机的实际转速值,去主程序执行就可以了。
举报

王锁

2017-9-12 15:47:42
引用: 1406093611 发表于 2017-9-12 11:32
你可以单独建一个PID源文件,PID主要用于反馈回来的电机实际转速的参数进行矫正,比如在这里,DSP从上位机接收到了电机转速的目标值,而实际的转速值与设定的目标值不一致,就可以通过PID控制让实际转速达到目标值。PID程序放在哪里不重要,重要的是你要调用PID的子程序来实现参数的控制,将PID处理过的数据,转变为控制 ...

可以加我QQ***,跟你请教一下嘛?
举报

王锁

2017-9-12 20:47:56
引用: 1406093611 发表于 2017-9-12 11:32
你可以单独建一个PID源文件,PID主要用于反馈回来的电机实际转速的参数进行矫正,比如在这里,DSP从上位机接收到了电机转速的目标值,而实际的转速值与设定的目标值不一致,就可以通过PID控制让实际转速达到目标值。PID程序放在哪里不重要,重要的是你要调用PID的子程序来实现参数的控制,将PID处理过的数据,转变为控制 ...

你好,想向你请教一下,PID的输出与PWM占空比的关系,如果用PID的输出调节PWM占空比是不是就把PID的输出直接加到PWM占空比上,还是要经过一定的比例关系再加到PWM占空比上?
举报

1406093611

2017-9-13 11:46:12
引用: MMMEEELLL 发表于 2017-9-12 20:47
你好,想向你请教一下,PID的输出与PWM占空比的关系,如果用PID的输出调节PWM占空比是不是就把PID的输出直接加到PWM占空比上,还是要经过一定的比例关系再加到PWM占空比上?

你好,由于白天上班,所以QQ不好回复,请谅解。
PID和PWM的关系是这样的:PID和PWM是独立的,但是PID可以影响PWM占空比的输出,也就是说,PID调整后会产生一个值,那么这个值是一个参考值,你在程序用的时候是需要判断这个参考值在什么范围内,然后在相应的范围内再给出对应的PWM占空比,这是一种PID与PWM的处理方式。

PID就是(比例+积分+微分)P+I+D,实际使用中可以是PI控制,也可以是PD控制,也可以是PID控制,需要根据实际情况做相应的调整。

楼主现在应该分清楚PID只是一种算法,它服务于其他控制类函数,比如就是PWM控制。

给楼主总结一下:1、PID和PWM是独立的个体,不是把PID的处理后的调整值直接作为PWM的占空比,除非你用PID处理后的值是整数并且在PWM占空比精度范围内,那就直接作为PWM占空比是可以的。2、PID处理就包括了比例、积分、微分,是将实际值进行比例积分微分运算后去快速地尽可能地稳定在设定值附近。
举报

SXST_T

2017-9-14 10:08:36
这应该挺简单的吧。。。。。PID主要是在固定的时间内,通过负反馈调节当前输出,即目标速度=当前速度+增量;即可达到直流电机线性输出的效果。光编当前速度你已经有了,目标速度有了,解决增量问题需要调节比例、积分、微分值就可以实现了。附上贴,原理一样的,如果适用,麻烦点一下标准答案,谢谢【教程】如何在STM32上实现增量式PID转
https://bbs.elecfans.com/jishu_484125_1_1.html
(出处: 中国电子技术william hill官网 )
举报

SXST_T

2017-9-14 10:10:44
对了,关于什么时候调节的问题,可以做一个100MS的定时器,定时器去读出速度,然后进行PID调节,编码器测速也很好做,用M/T法测速直接就可以用了
举报

王锁

2017-9-14 15:28:11
引用: 1406093611 发表于 2017-9-13 11:46
你好,由于白天上班,所以QQ不好回复,请谅解。
PID和PWM的关系是这样的:PID和PWM是独立的,但是PID可以影响PWM占空比的输出,也就是说,PID调整后会产生一个值,那么这个值是一个参考值,你在程序用的时候是需要判断这个参考值在什么范围内,然后在相应的范围内再给出对应的PWM占空比,这是一种PID与PWM的处理方式。

//主函数
void main(void)
{
        InitSysCtrl();
        DINT;
        IER=0x0000;
        IFR=0x0000;
        InitPieCtrl();
        InitPieVectTable();
        InitCpuTimers();
        InitGpio();
        InitEv();
        InitSci();
        InitPeripherals();
        //变量初始化

        Speedlimit=10;
        OutMax=Speedlimit;
        OutMin=-Speedlimit;
        n1=0;

        for(i=0;i<6;i++)
        {
                Scia_VarRx=0;
        }
        i=0;
        for(j=0;j<200;j++)
        {
                n[j]=0;
        }
        j=0;
    freq=0;
    temp1=temp2=0;
        Ref=Fdb=0;
        Kp=2;
        Ki=1.5;
        Kd=0;
        T=0.005;
        a0=a1=a2=0;
        Err=Err_1=Err_2=0;
        Out=Out_1=0;
    t1cmpr=0;
    kb=hd=de=un=d1=d2=D=0;
    cap1=cap2=0;
    capint3=t2pint=t1pint=0;
    T1=T2=0;
    k=0;
    duty=D=pwm_duty=0;
    pwm=0;
    EvaRegs.T1CMPR=0;

    //中断使能模块
    PieCtrl.PIEIER9.bit.INTx1=1;
        PieCtrl.PIEIER3.bit.INTx1=1;
        PieCtrl.PIEIER3.bit.INTx7=1;
        PieCtrl.PIEIER2.bit.INTx4=1;

    //开CPU中断
    IER|=M_INT9;
        IER|=M_INT3;
        IER|=M_INT2;

    //开全局中断,开实时中断
    EINT;
    ERTM;
        EvaRegs.T1CON.bit.TENABLE=1;
        EvaRegs.CAPCON.bit.CAP3EN=1;


    for(;;)
    {

    }
       
}




interrupt void SCIRXINTA_ISR(void)     // SCI-A接收中断函数
{
          Scia_VarRx=SciaRegs.SCIRXBUF.all;
          if(Scia_VarRx==48)
          {
          Scia_VarRx=0;
          }
          if(Scia_VarRx==49)
          {
          Scia_VarRx=1;
          }
          if(Scia_VarRx==50)
          {
          Scia_VarRx=2;
          }
            if(Scia_VarRx==51)
          {
          Scia_VarRx=3;
          }
            if(Scia_VarRx==52)
          {
          Scia_VarRx=4;
          }
            if(Scia_VarRx==53)
          {
          Scia_VarRx=5;
          }
            if(Scia_VarRx==54)
          {
          Scia_VarRx=6;
          }
            if(Scia_VarRx==55)
          {
          Scia_VarRx=7;
          }
            if(Scia_VarRx==56)
          {
          Scia_VarRx=8;
          }
            if(Scia_VarRx==57)
          {
          Scia_VarRx=9;
          }

          kb=Scia_VarRx[0]*1000;
          hd=Scia_VarRx[1]*100;
          de=Scia_VarRx[2]*10;
          un=Scia_VarRx[3];
          d1=Scia_VarRx[4];
          d2=Scia_VarRx[5];
          D=kb+hd+de+un;
          pwm_duty=0;

          i++;
          if(i==6)
            {

              i=0;

             }


          EALLOW;
          GpioDataRegs.GPADAT.bit.GPIOA0=d1;        //通过串口助手发送的数据来改变PWM1引脚的高低
          GpioDataRegs.GPADAT.bit.GPIOA1=d2;        //通过串口助手发送的数据来改变PWM1引脚的高低
          EDIS;

          PieCtrl.PIEACK.bit.ACK9=1;

      EINT;
}


interrupt void CAPINT3_ISR(void)
{

        capint3++;

        if(capint3==1)
        {
                EvaRegs.T2CON.bit.TENABLE=1;
                cap1=EvaRegs.T2CNT;
                T1=t2pint;

        }

        if(capint3==2)
        {

                cap2=EvaRegs.T2CNT;
                T2=t2pint;
                temp1=cap2+(T2-T1)*65535-cap1;
                freq=300000;
                n1=freq/(float)temp1;

                for(j=0;j<200;j++)
                {
                        n[j]=n1;
                }

                t2pint=0;
                T1=T2=0;
                capint3=0;
                EvaRegs.T2CNT=0;
                EvaRegs.T2CON.bit.TENABLE=0;

        }

        EvaRegs.EVAIFRC.bit.CAP3INT=1;
        EvaRegs.EVAIMRC.bit.CAP3INT=1;
        PieCtrl.PIEACK.bit.ACK3=1;
}

interrupt void T2PINT_ISR(void)
{

   t2pint++;
   EvaRegs.EVAIFRB.bit.T2PINT=1;
   EvaRegs.EVAIMRB.bit.T2PINT=1;
   PieCtrl.PIEACK.bit.ACK3=1;

   EINT;
}


interrupt void T1PINT_ISR(void)    // 通用定时器T1的周期中断
{

        t1pint++;
        if(t1pint==100)       //达到5ms开始进行PID运算
            {

                Ref=D*10/1500;
                Fdb=n1;
                Err=Ref-Fdb;

                a0=Kp*(1+T/Ki+Kd/T);
                a1=Kp*(1+2*Kd/T);
                a2=Kp*Kd/T;
                Out=Out_1+a0*Err-a1*Err_1+a2*Err_2;

        pwm+=Out;   //增量
        duty=D+(int)pwm;      
     if(duty>1500)
     {
             t1cmpr=1500;
     }
     else
     {
             t1cmpr=duty;
     }
     EvaRegs.T1CMPR=t1cmpr;

            Out_1=Out;
            Err_2=Err_1;
            Err_1=Err;
            }

    EvaRegs.EVAIFRA.bit.T1PINT=1;
    EvaRegs.EVAIMRA.bit.T1PINT=1;
    PieCtrl.PIEACK.bit.ACK2=1;

    EINT;

}

上面是我自己编写的程序,测速采用的T法测速,请你帮忙看一下,谢谢
举报

王者树人

2017-9-18 19:45:33
看看吧!看看吧!
举报

梅雪正

2017-10-16 23:56:32
楼主解决问题了嘛?
举报

570015

2017-12-6 18:07:46
PieCtrl.PIEIER3.bit.INTx5 = 1;
        IER |= M_INT3;
        EINT;
        ERTM;
举报

王尼玛120

2018-5-4 22:21:26
您好,可以分享一下测速的程序吗
举报

更多回帖

×
20
完善资料,
赚取积分