编码机

电机控制进阶3PID串级控制附全套代码

发布时间:2022/7/26 15:02:18   

前两篇文章,别离引见了PID速率管束和PID场所管束,别离用来管束机电以希望的速率接续滚动以及以希望的场所(圈数)滚动,这边的希望值都惟独一个,然则,假设想要以希望的速率滚动到希望的场所(启动与中止的加加速经过不思索),该何如管束呢?那就要将两者连合起来了,即PID的串级管束来管束机电。

串级PID构造图

PID串级管束的典范构造为场所环+速率环+电流环,以下图。

PID串级管束中,最外环是输入是全部管束系统的希望值,外环PID的输出值是内环PID的希望值。

也许哄骗三环管束的前提是要硬件撑持,譬喻场所环和速率环须要及时的机电滚动场所和滚动速率做为反应,这就须要机电须要配有编码器用于测速与衡量滚动的场所;电流环须要有电流采样电路来及时猎取机电的电流做为反应。

假设没有电流采样电路,也许将电流环去掉,只哄骗场所环+速率环,系统的希望还是滚动的场所,内环也许调度滚动的速率。

别的,假设不过想管束机电转速实行机电调速,也许哄骗速率环+电流环,系统的希望还是滚动的场所,内环也许调度机电的电流,巩固系统滚动调度的抗搅扰才略。

场所环+速率环理论

由于我的机电没有电流衡量电路,是以,本文以场所环+速率环来研习PID串级管束。即是遵循上面这个图:

PID参数界说

由因而串级PID管束,每甲第的PID都要有本身的参数,本次实践哄骗场所PID+速率PID,参数界说以下:

/*界说场所PID与速率PID构造体型的全面变量*/PIDpid_location;PIDpid_speed;/***

briefPID参数初始化*  

note  无*

retval无*/voidPID_param_init(){  /*场所关连初始化参数*/  pid_location.target_val=TOTAL_RESOLUTION*10;          pid_location.output_val=0.0;  pid_location.err=0.0;  pid_location.err_last=0.0;  pid_location.integral=0.0;  pid_location.Kp=0.05;  pid_location.Ki=0;  pid_location.Kd=0;  /*速率关连初始化参数*/  pid_speed.target_val=10.0;          pid_speed.output_val=0.0;  pid_speed.err=0.0;  pid_speed.err_last=0.0;  pid_speed.integral=0.0;  pid_speed.Kp=80.0;  pid_speed.Ki=2.0;  pid_speed.Kd=.0;}场所PID的实行

这边有两点须要留心:

闭环死区的设定

闭环死区是指履行机构的最小管束量,无奈再经过调度来餍足管束精度,假设仍旧接续调度,系统则会在目的值先后屡次行为,不能安稳下来。

譬喻某个系统的管束精度是1,但目的值须借使1.5,则不论何如调度,终究的结束只可管束在1或2,不停无奈来到预设值。这1.5L少量点后的范畴,即是闭环死区,系统是无奈管束的,过错会向来存在,简单产生震动形势。

对应精度请求不高的系统,也许设定闭环死区,譬喻将许可的过错范畴设为0.5,则终究结束在1或2都觉得是没有过错,这时将目的值与理论值之差强逼设为0,觉得没有过错,即限定了闭环死区。

积分分散的设定

经过积分分散的方法来实行抗积分饱和,积分饱和是指履行机构来到极限输出才略了,仍无奈来到目的值,在很长一段时候内无奈消除静差形成的。

比方,PWM输出到了%,仍达不到希望场所,此时若向来实行过错累加,在一段时候后,PID的积分项累计了很大的数值,假设这岁月来到了目的值也许从头设定了目的值,由于积分由于累计的过错很大,系统并不能登时调度到目的值,或者形成超调或平衡的形势。

处置积分饱和的一种办法是哄骗积分分散,该办法是在累计过错小于某个阈值才哄骗积分项,累计过错过大则不再连续累计过错,相当于只哄骗了PD管束器。

管束过程图

带有闭环死区与积分分散的PID管束过程以下图:

完好的场所PID代码以下:

/***

brief场所PID算法实行*

paramactual_val:理论值*  

note  无*

retval经过PID打算后的输出*/#defineLOC_DEAD_ZONE60/*场所环死区*/#defineLOC_INTEGRAL_START_ERR/*积分分散时对应的过错范畴*/#defineLOC_INTEGRAL_MAX_VAL/*积分范畴限定,避免积分饱和*/floatlocation_pid_realize(PID*pid,floatactual_val){  /*打算目的值与理论值的过错*/  pid-err=pid-target_val-actual_val;  /*设定闭环死区*/  if((pid-err=-LOC_DEAD_ZONE)(pid-err=LOC_DEAD_ZONE))  {    pid-err=0;    pid-integral=0;    pid-err_last=0;  }  /*积分项,积分分散,差池较大时去掉积分影响*/  if(pid-err-LOC_INTEGRAL_START_ERRpid-errLOC_INTEGRAL_START_ERR)  {    pid-integral+=pid-err;/*积分范畴限定,避免积分饱和*/    if(pid-integralLOC_INTEGRAL_MAX_VAL)    {      pid-integral=LOC_INTEGRAL_MAX_VAL;    }    elseif(pid-integral-LOC_INTEGRAL_MAX_VAL)    {      pid-integral=-LOC_INTEGRAL_MAX_VAL;    }  }    /*PID算法实行*/  pid-output_val=pid-Kp*pid-err+  pid-Ki*pid-integral+  pid-Kd*(pid-err-pid-err_last);  /*过错转达*/  pid-err_last=pid-err;  /*返回暂时理论值*/  returnpid-output_val;}速率PID实行

速率PID的实行代码与场所PID的相同:

/***

brief速率PID算法实行*

paramactual_val:理论值*  

note  无*

retval经过PID打算后的输出*/#defineSPE_DEAD_ZONE5.0f/*速率环死区*/#defineSPE_INTEGRAL_START_ERR/*积分分散时对应的过错范畴*/#defineSPE_INTEGRAL_MAX_VAL/*积分范畴限定,避免积分饱和*/floatspeed_pid_realize(PID*pid,floatactual_val){  /*打算目的值与理论值的过错*/  pid-err=pid-target_val-actual_val;  /*设定闭环死区*/  if((pid-err-SPE_DEAD_ZONE)(pid-errSPE_DEAD_ZONE))  {    pid-err=0;    pid-integral=0;    pid-err_last=0;  }  /*积分项,积分分散,差池较大时去掉积分影响*/  if(pid-err-SPE_INTEGRAL_START_ERRpid-errSPE_INTEGRAL_START_ERR)  {    pid-integral+=pid-err;/*积分范畴限定,避免积分饱和*/    if(pid-integralSPE_INTEGRAL_MAX_VAL)    {      pid-integral=SPE_INTEGRAL_MAX_VAL;    }    elseif(pid-integral-SPE_INTEGRAL_MAX_VAL)    {      pid-integral=-SPE_INTEGRAL_MAX_VAL;    }  }      /*PID算法实行*/  pid-output_val=pid-Kp*pid-err+  pid-Ki*pid-integral+  pid-Kd*(pid-err-pid-err_last);  /*过错转达*/  pid-err_last=pid-err;  /*返回暂时理论值*/  returnpid-output_val;}串级管束代码

//周期准时器的回调函数voidAutoReloadCallback(){  staticuint32_tlocation_timer=0;//场所环周期    static__IOintencoderNow=0;/*暂时岁月总共数值*/static__IOintencoderLast=0;/*上一岁月总共数值*/  intencoderDelta=0;/*暂时岁月与上一岁月编码器的改变量*/  floatactual_speed=0;/*理论测得速率*/  intactual_speed_int=0;    intres_pwm=0;/*PID打算获得的PWM值*/  staticinti=0;    /*读取编码器的值*/  encoderNow=read_encoder()+EncoderOverflowCnt*ENCODER_TIM_PERIOD;/*猎取暂时的累计值*/  encoderDelta=encoderNow-encoderLast;/*获得改变值*/  encoderLast=encoderNow;/*革新前次的累计值*/    /*场所PID运算,获得PWM管束值*/  if((location_timer++%2)==0)  {    floatcontrol_val=0;/*暂时管束值*/        /*场所PID打算*/    control_val=location_pid_realize(pid_location,encoderNow);    /*目的速率值束缚*/    speed_val_protect(control_val);    /*设定速率PID的目的值*/    set_pid_target(pid_speed,control_val);  }    /*转速(1秒钟转几许圈)=单元时候内的计数值/总分辩率*时候系数,再乘60变成1分钟转几许圈*/actual_speed=(float)encoderDelta/TOTAL_RESOLUTION*10*60;  /*速率PID运算,获得PWM管束值*/  actual_speed_int=actual_speed;  res_pwm=pwm_val_protect((int)speed_pid_realize(pid_speed,actual_speed));    /*PWM管束机电*/  set_motor_rotate(res_pwm);    /*数据上传到上位机显示*/  set_

转载请注明:http://www.aideyishus.com/lkyy/896.html

------分隔线----------------------------

热点文章

  • 没有热点文章

推荐文章

  • 没有推荐文章