带电位器的直流电机控制位置

2019-07-21 00:25发布

现有一个带电位器的电机,将采集到的AD值经过PID计算后更新PWM,想要实现精准控制位置(转过的角度),但是调试时一直正反来回转,不像PID控制电机转速那样可以监测到收敛的速度曲线,而是一直震荡的AD值曲线,调了很久PID都不行。请问下大家是怎么调试的,求助,为谢!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
10条回答
StayHungry123
2019-07-21 10:25
//PID3初始化参数       
        pid3.errorSumDownLim = -200;                //偏差和下限
        pid3.errorSumUpLim = 200;                        //偏差和上限
        pid3.PIDoutDownLim = -80;                        //PID输出下限(即PWM占空比)
        pid3.PIDoutUpLim = 80;                                //PID输出上限
        pid3.errorUpLim = 200;                                //偏差上限
        pid3.errorDownLim = -200;                        //偏差下限
        pid3.delErrorUpLim = 300;                        //偏差之差上限
        pid3.delErrorDownLim = -300;                        //偏差之差下限
       
        pid3.TargetVal=2000;       
       
        pid3.kp=0.2;                                                        //先开始调P参数,所以将Ki  Kd都置0了
        pid3.ki=0;
        pid3.kd=0;       

void PID3_Calc(void)
{
        pid3.error = pid3.TargetVal - pid3.NowVal;                        //偏差 = 设定 - 当前       
       
        if(pid3.error > pid3.errorUpLim)                                        //误差限幅
                pid3.error = pid3.errorUpLim;
        else if(pid3.error < pid3.errorDownLim)
                pid3.error = pid3.errorDownLim;
       
        pid3.errorSum += pid3.error;                                                //偏差求和
       
        if(pid3.errorSum > pid3.errorSumUpLim)                        //偏差和限幅
                pid3.errorSum = pid3.errorSumUpLim;
        else if(pid3.errorSum < pid3.errorSumDownLim)
                pid3.errorSum = pid3.errorSumDownLim;
       
        pid3.delError = pid3.error - pid3.error1;                        //偏差微分
        pid3.error1 = pid3.error;                                                       
       
        if(pid3.delError > pid3.delErrorUpLim)                                //偏差微分限幅
                pid3.delError = pid3.delErrorUpLim;
        else if(pid3.delError < pid3.delErrorDownLim)
                pid3.delError = pid3.delErrorDownLim;
       
        pid3.Pout = pid3.kp * pid3.error;                                        //比例输出
        pid3.Iout = pid3.ki * pid3.errorSum;                                //积分输出
        pid3.Dout = pid3.kd * pid3.delError;                                //微分输出
       
        pid3.PIDout = pid3.Pout + pid3.Iout+ pid3.Dout;        // PID输出
       
        if(pid3.PIDout > pid3.PIDoutUpLim)                                //PID输出限幅
                pid3.PIDout = pid3.PIDoutUpLim;
        else if(pid3.PIDout < pid3.PIDoutDownLim)
                pid3.PIDout = pid3.PIDoutDownLim;

}

在MAIN()函数中
                if(pid3_flag==1)                                                                //PID控制标志位 ,每0.1S进定时器中断将pid3_flag置1
                {
                                ADCVAL=Get_Adc_Average(ADC_Channel_1,5);
                                pid3.NowVal=ADCVAL;       
                                PID3_Calc();
                                PwmValue3=pid3.PIDout;                                                       
                       
                                pid3_flag=0;
                }

一周热门 更多>