当前位置: 编码机 >> 编码机介绍 >> 电机控制进阶3PID串级控制附全套代码
前两篇文章,别离引见了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