飞思卡尔智能车 电机PID

2020-02-11 09:03发布

提到小车的控制必然想到的PID控制,这也是各技术报告都不会漏掉的名词,在飞思卡尔XS128系列(二)PWM模块中已经提到了一些电机控制方面的东西,主要讲了用PID和BANG-BANG控制相结合的方式来控制电机,就是由BANG-BANG来控制力度,用PID来控制精度,下面就具体来讲讲。

  先说控制,所谓控制首先由闭环控制和开环控制之分,就是所谓的有反馈和无反馈,当然PID显然是有反馈的控制。所谓的闭环控制就是要根据被控制量的实际情况参与运算来决定操作量的大小或者方向。因为在单回路控制系统中,由于扰动的作用使被控参数偏离给定值,从而产生偏差,而自动控制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分和微分运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量和速度等的自动控制。

  然而牵扯到高级PID,像有自适应控制、模糊控制、预测控制、神经网络控制、专家智能控制等等,里面也就模糊控制搞过一定时间,其它我也不懂,就不瞎扯了。





      比例、积分和微分的线性组合,构成控制量u(t),称为:比例(Proportional)、积分(Integrating)和微分(Differentiation)控制,简称PID控制。比例作用P只与偏差成正比,积分作用I是偏差对时间的累积,而微分作用D是偏差的变化率。

  用一句形象的比喻,比例P代表着现在,积分I代表着过去,而微分D则代表着未来。





公式如图:

  具体于比例、积分和微分,网上有很多这方面的资料,我就不多说了。

  下面是关于参数的调整,比例系数、积分系数和微分系数的合理调整时整个PID系统可以正常温度工作的关键。

  而最好的寻找PID参数的办法是从系统的数学模型出发,从想要的反应来计算参数。很多时候一个详细的数学描述是不存在的,这时候就需要从实际出发去调整PID参数了。



Ziegler——Nichols方法



  Ziegler——Nichols方法是基于系统稳定性分析的PID整定方法,在设计过程中无需要考虑任何特性要求,整定方法简单。





Tyreus——Luyben的整定值即减少了震荡的作用,而且增强了系统的稳定性。

理论上的就不多说了,我自己都懒得多看。

复制代码
    /****************************************************************
    Code Warrior 5.0
    Target : MC9S12XS128
    Crystal: 16.000Mhz  
    by:庞辉
    芜湖联大飞思卡尔项目组   
    ******************************************************************/  
      
    sint16 ideal_speed; //车的理想速度  
      
    //拨码开关选择脉冲  
    const sint16 speed_arr1[253] = {  
         37,37,37,85,85,85,37,37,37     
            
    };  
    const sint16 speed_arr2[253] = {  
         38,38,38,90,90,90,38,38,38   
    };  
      
      
    const sint16 speed_arr3[253] = {  
         40,40,40,95,95,95,40,40,40   
    };  
      
    const sint16 speed_arr4[253] = {  
         45,45,45,95,95,95,45,45,45  
    };  
      
    const sint16 speed_arr5[253] = {  
         50,50,50,95,95,95,50,50,50   
    };  
      
    const sint16 speed_arr6[253] = {  
         37,37,37,100,100,100,37,37,37  
            
    };  
      
    const sint16 speed_arr7[10] =   
    {  
        40,40,40,100,100,100,40,40,40  
    };  
      
      
    void Motor_Change(void)  
    {   
         
         
         
        if(PORTA_PA0 == 0)  
        {  
            ideal_speed = speed_arr1[pos_ + 4];  
        }  
        else if(PORTA_PA1 == 0)  
        {  
            ideal_speed = speed_arr2[pos_ + 4];  
        }                                                
        else if(PORTA_PA2 == 0)  
        {  
            ideal_speed = speed_arr3[pos_ + 4];  
        }  
         else if(PORTA_PA3 == 0)  
        {  
            ideal_speed = speed_arr4[pos_ + 4];  
        }  
        else  if(PORTA_PA4 == 0)  
        {  
            ideal_speed = speed_arr5[pos_ + 4];  
        }  
        else if(PORTA_PA5 == 0)  
        {  
            ideal_speed = speed_arr6[pos_ + 4];  
        }  
        else if(PORTA_PA6 == 0)  
        {  
            ideal_speed = speed_arr7[pos_ + 4];  
        }  
        else   
        {  
            ideal_speed = speed_arr1[pos_ + 4];  
        }  
         
        //ideal_speed = speed_arr7[pos_ + 4];  
         
         speed_error = ideal_speed - pulse_count;  
         
        if(speed_error >= 10) //情况1,全加速  
        {  
            Set_PWM01(10000, 10000);  
        }  
         
        else if(speed_error > -10) //情况2,用PID减速  
        {  
            pid();  
        }  
        else  
        {  
            Set_PWM01(0,10000);   
        }         
            
    }  
复制代码


复制代码
    #define kp_motor 15  
    #define ki_motor 4//1  
    #define kd_motor 8//10   
      
    sint16 speed_error; //理想与实际速度偏差值  
    sint16 pre_error; //速度PID 前一次的速度误差值ideal_speed- pulse_count  
    sint16 pre_d_error; //速度PID 前一次的速度误差之差d_error-pre_d_error  
    sint16 pk; //速度PID值  
      
    void pid(void)   
    {  
        sint16 error,d_error,dd_error;  
         
        error = ideal_speed - pulse_count;  
        d_error = error - pre_error;  
        dd_error = d_error - pre_d_error;  
         
        pre_error = error; //存储当前偏差  
        pre_d_error = d_error;  
         
        pk += kp_motor * d_error + ki_motor * error + kd_motor * dd_error;  
         
        if(pk >= 10000)   
        {  
            pk = 10000;  
        }  
        else if(pk <= 0)   
        {  
            pk = 0;  
        }  
         
        Set_PWM01(pk,10000);  
    }  



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。