前兩篇文章:
http://m.xsypw.cn/d/1796839.html
http://m.xsypw.cn/d/1798370.html
分別介紹了PID速度控制和PID位置控制,分別用來(lái)控制電機(jī)以期望的速度持續(xù)轉(zhuǎn)動(dòng)以及以期望的位置(圈數(shù))轉(zhuǎn)動(dòng),這里的期望值都只有一個(gè),但是,如果想要以期望的速度轉(zhuǎn)動(dòng)到期望的位置(啟動(dòng)與停止的加減速過(guò)程不考慮),該怎么控制呢?那就要將兩者結(jié)合起來(lái)了,即PID的串級(jí)控制來(lái)控制電機(jī)。
串級(jí)PID結(jié)構(gòu)圖
PID串級(jí)控制的典型結(jié)構(gòu)為位置環(huán)+速度環(huán)+電流環(huán),如下圖。
PID串級(jí)控制中,最外環(huán)是輸入是整個(gè)控制系統(tǒng)的期望值,外環(huán)PID的輸出值是內(nèi)環(huán)PID的期望值。
能夠使用三環(huán)控制的前提是要硬件支持,比如位置環(huán)和速度環(huán)需要實(shí)時(shí)的電機(jī)轉(zhuǎn)動(dòng)位置和轉(zhuǎn)動(dòng)速度作為反饋,這就需要電機(jī)需要配有編碼器用于測(cè)速與測(cè)量轉(zhuǎn)動(dòng)的位置;電流環(huán)需要有電流采樣電路來(lái)實(shí)時(shí)獲取電機(jī)的電流作為反饋。
如果沒(méi)有電流采樣電路,可以將電流環(huán)去掉,只使用位置環(huán)+速度環(huán),系統(tǒng)的期望仍是轉(zhuǎn)動(dòng)的位置,內(nèi)環(huán)可以調(diào)節(jié)轉(zhuǎn)動(dòng)的速度。
另外,如果只是想控制電機(jī)轉(zhuǎn)速實(shí)現(xiàn)電機(jī)調(diào)速,可以使用速度環(huán)+電流環(huán),系統(tǒng)的期望仍是轉(zhuǎn)動(dòng)的位置,內(nèi)環(huán)可以調(diào)節(jié)電機(jī)的電流,增強(qiáng)系統(tǒng)轉(zhuǎn)動(dòng)調(diào)節(jié)的抗干擾能力。
位置環(huán)+速度環(huán)實(shí)踐
由于我的電機(jī)沒(méi)有電流測(cè)量電路,所以,本文以位置環(huán)+速度環(huán)來(lái)學(xué)習(xí)PID串級(jí)控制。就是按照下面這個(gè)圖:
PID參數(shù)定義
由于是串級(jí)PID控制,每一級(jí)的PID都要有自己的參數(shù),本次實(shí)驗(yàn)使用位置PID+速度PID,參數(shù)定義如下:
/*定義位置PID與速度PID結(jié)構(gòu)體型的全局變量*/
PID pid_location;
PID pid_speed;
/**
* @brief PID參數(shù)初始化
* @note 無(wú)
* @retval 無(wú)
*/
void PID_param_init()
{
/* 位置相關(guān)初始化參數(shù) */
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;
/* 速度相關(guān)初始化參數(shù) */
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 = 100.0;
}
位置PID的實(shí)現(xiàn)
這里有兩點(diǎn)需要注意:
閉環(huán)死區(qū)的設(shè)定
閉環(huán)死區(qū)是指執(zhí)行機(jī)構(gòu)的最小控制量,無(wú)法再通過(guò)調(diào)節(jié)來(lái)滿足控制精度,如果仍然持續(xù)調(diào)節(jié),系統(tǒng)則會(huì)在目標(biāo)值前后頻繁動(dòng)作,不能穩(wěn)定下來(lái)。
比如某個(gè)系統(tǒng)的控制精度是1,但目標(biāo)值需要是1.5,則無(wú)論怎么調(diào)節(jié),最終的結(jié)果只能控制在 1或 2,始終無(wú)法達(dá)到預(yù)設(shè)值。這 1.5L小數(shù)點(diǎn)后的范圍,就是閉環(huán)死區(qū),系統(tǒng)是無(wú)法控制的,誤差會(huì)一直存在,容易發(fā)生震蕩現(xiàn)象。
對(duì)應(yīng)精度要求不高的系統(tǒng),可以設(shè)定閉環(huán)死區(qū),比如將允許的誤差范圍設(shè)為0.5,則最終結(jié)果在 1或 2都認(rèn)為是沒(méi)有誤差,這時(shí)將目標(biāo)值 與實(shí)際值之差強(qiáng)制設(shè)為 0,認(rèn)為沒(méi)有誤差,即限定了閉環(huán)死區(qū)。
積分分離的設(shè)定
通過(guò)積分分離的方式來(lái)實(shí)現(xiàn)抗積分飽和,積分飽和是指執(zhí)行機(jī)構(gòu)達(dá)到極限輸出能力了,仍無(wú)法到達(dá)目標(biāo)值,在很長(zhǎng)一段時(shí)間內(nèi)無(wú)法消除靜差造成的。
例如,PWM輸出到了100%,仍達(dá)不到期望位置,此時(shí)若一直進(jìn)行誤差累加,在一段時(shí)間后, PID 的積分項(xiàng)累計(jì)了很大的數(shù)值,如果這時(shí)候到達(dá)了目標(biāo)值或者重新設(shè)定了目標(biāo)值,由于積分由于累計(jì)的誤差很大,系統(tǒng)并不能立即調(diào)整到目標(biāo)值,可能造成超調(diào)或失調(diào)的現(xiàn)象。
解決積分飽和的一種方法是使用積分分離,該方法是在累計(jì)誤差小于某個(gè)閾值才使用積分項(xiàng),累計(jì)誤差過(guò)大則不再繼續(xù)累計(jì)誤差,相當(dāng)于只使用了PD控制器。
控制流程圖
帶有閉環(huán)死區(qū)與積分分離的PID控制流程如下圖:
完整的位置PID代碼如下:
/**
* @brief 位置PID算法實(shí)現(xiàn)
* @param actual_val:實(shí)際值
* @note 無(wú)
* @retval 通過(guò)PID計(jì)算后的輸出
*/
#define LOC_DEAD_ZONE 60 /*位置環(huán)死區(qū)*/
#define LOC_INTEGRAL_START_ERR 200 /*積分分離時(shí)對(duì)應(yīng)的誤差范圍*/
#define LOC_INTEGRAL_MAX_VAL 800 /*積分范圍限定,防止積分飽和*/
float location_pid_realize(PID *pid, float actual_val)
{
/*計(jì)算目標(biāo)值與實(shí)際值的誤差*/
pid->err = pid->target_val - actual_val;
/* 設(shè)定閉環(huán)死區(qū) */
if((pid->err >= -LOC_DEAD_ZONE) && (pid->err <= LOC_DEAD_ZONE))
{
pid->err = 0;
pid->integral = 0;
pid->err_last = 0;
}
/*積分項(xiàng),積分分離,偏差較大時(shí)去掉積分作用*/
if(pid->err > -LOC_INTEGRAL_START_ERR && pid->err < LOC_INTEGRAL_START_ERR)
{
pid->integral += pid->err;
/*積分范圍限定,防止積分飽和*/
if(pid->integral > LOC_INTEGRAL_MAX_VAL)
{
pid->integral = LOC_INTEGRAL_MAX_VAL;
}
else if(pid->integral < -LOC_INTEGRAL_MAX_VAL)
{
pid->integral = -LOC_INTEGRAL_MAX_VAL;
}
}
/*PID算法實(shí)現(xiàn)*/
pid->output_val = pid->Kp * pid->err +
pid->Ki * pid->integral +
pid->Kd * (pid->err - pid->err_last);
/*誤差傳遞*/
pid->err_last = pid->err;
/*返回當(dāng)前實(shí)際值*/
return pid->output_val;
}
串級(jí)控制代碼
//周期定時(shí)器的回調(diào)函數(shù)
void AutoReloadCallback()
{
static uint32_t location_timer = 0; // 位置環(huán)周期
static __IO int encoderNow = 0; /*當(dāng)前時(shí)刻總計(jì)數(shù)值*/
static __IO int encoderLast = 0; /*上一時(shí)刻總計(jì)數(shù)值*/
int encoderDelta = 0; /*當(dāng)前時(shí)刻與上一時(shí)刻編碼器的變化量*/
float actual_speed = 0; /*實(shí)際測(cè)得速度*/
int actual_speed_int = 0;
int res_pwm = 0;/*PID計(jì)算得到的PWM值*/
static int i=0;
/*【1】讀取編碼器的值*/
encoderNow = read_encoder() + EncoderOverflowCnt*ENCODER_TIM_PERIOD;/*獲取當(dāng)前的累計(jì)值*/
encoderDelta = encoderNow - encoderLast; /*得到變化值*/
encoderLast = encoderNow;/*更新上次的累計(jì)值*/
/*【2】位置PID運(yùn)算,得到PWM控制值*/
if ((location_timer++ % 2) == 0)
{
float control_val = 0; /*當(dāng)前控制值*/
/*位置PID計(jì)算*/
control_val = location_pid_realize(&pid_location, encoderNow);
/*目標(biāo)速度值限制*/
speed_val_protect(&control_val);
/*設(shè)定速度PID的目標(biāo)值*/
set_pid_target(&pid_speed, control_val);
}
/* 轉(zhuǎn)速(1秒鐘轉(zhuǎn)多少圈)=單位時(shí)間內(nèi)的計(jì)數(shù)值/總分辨率*時(shí)間系數(shù), 再乘60變?yōu)?分鐘轉(zhuǎn)多少圈 */
actual_speed = (float)encoderDelta / TOTAL_RESOLUTION * 10 * 60;
/*【3】速度PID運(yùn)算,得到PWM控制值*/
actual_speed_int = actual_speed;
res_pwm = pwm_val_protect((int)speed_pid_realize(&pid_speed, actual_speed));
/*【4】PWM控制電機(jī)*/
set_motor_rotate(res_pwm);
/*【5】數(shù)據(jù)上傳到上位機(jī)顯示*/
set_computer_value(SEND_FACT_CMD, CURVES_CH1, &encoderNow, 1); /*給通道1發(fā)送實(shí)際的電機(jī)【位置】值*/
}
PID的計(jì)算是通過(guò)定時(shí)器調(diào)用,每10ms一次,從代碼中可以看到,內(nèi)環(huán)(速度PID)控制的周期要比外環(huán)(位置PID)的周期短,位置PID是每?jī)纱窝h(huán)計(jì)算一次,因?yàn)閮?nèi)環(huán)控制著最終的輸出,這個(gè)輸出對(duì)應(yīng)的就是實(shí)際場(chǎng)景中的控制量 (本實(shí)驗(yàn)最終控制的是位置),位置是無(wú)法突變,是需要時(shí)間積累的,所以?xún)?nèi)環(huán)輸出盡可能快些。
視頻演示
視頻中,測(cè)試以不同的目標(biāo)速度到達(dá)目標(biāo)位置,視頻后半段測(cè)試引入干擾情況下的控制效果:
https://www.bilibili.com/video/BV1QK4y1g7yg?spm_id_from=333.999.0.0
開(kāi)源代碼
-
單片機(jī)
+關(guān)注
關(guān)注
6043文章
44621瀏覽量
638624 -
電機(jī)控制
+關(guān)注
關(guān)注
3540文章
1897瀏覽量
269267 -
STM32
+關(guān)注
關(guān)注
2272文章
10924瀏覽量
357603 -
PID
+關(guān)注
關(guān)注
35文章
1473瀏覽量
85826
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論