電機控制進階3——PID串級控制

      網友投稿 1066 2022-05-30

      前兩篇文章,分別介紹了PID速度控制和PID位置控制,分別用來控制電機以期望的速度持續轉動以及以期望的位置(圈數)轉動,這里的期望值都只有一個,但是,如果想要以期望的速度轉動到期望的位置(啟動與停止的加減速過程不考慮),該怎么控制呢?那就要將兩者結合起來了,即PID的串級控制來控制電機。

      串級PID結構圖

      PID串級控制的典型結構為位置環+速度環+電流環,如下圖。

      PID串級控制中,最外環是輸入是整個控制系統的期望值,外環PID的輸出值是內環PID的期望值。

      能夠使用三環控制的前提是要硬件支持,比如位置環和速度環需要實時的電機轉動位置和轉動速度作為反饋,這就需要電機需要配有編碼器用于測速與測量轉動的位置;電流環需要有電流采樣電路來實時獲取電機的電流作為反饋。

      如果沒有電流采樣電路,可以將電流環去掉,只使用位置環+速度環,系統的期望仍是轉動的位置,內環可以調節轉動的速度。

      另外,如果只是想控制電機轉速實現電機調速,可以使用速度環+電流環,系統的期望仍是轉動的位置,內環可以調節電機的電流,增強系統轉動調節的抗干擾能力。

      位置環+速度環實踐

      由于我的電機沒有電流測量電路,所以,本文以位置環+速度環來學習PID串級控制。就是按照下面這個圖:

      PID參數定義

      由于是串級PID控制,每一級的PID都要有自己的參數,本次實驗使用位置PID+速度PID,參數定義如下:

      /*定義位置PID與速度PID結構體型的全局變量*/ PID pid_location; PID pid_speed; /** * @brief PID參數初始化 * @note 無 * @retval 無 */ void PID_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 = 100.0; }

      位置PID的實現

      這里有兩點需要注意:

      閉環死區的設定

      閉環死區是指執行機構的最小控制量,無法再通過調節來滿足控制精度,如果仍然持續調節,系統則會在目標值前后頻繁動作,不能穩定下來。

      比如某個系統的控制精度是1,但目標值需要是1.5,則無論怎么調節,最終的結果只能控制在 1或 2,始終無法達到預設值。這 1.5L小數點后的范圍,就是閉環死區,系統是無法控制的,誤差會一直存在,容易發生震蕩現象。

      對應精度要求不高的系統,可以設定閉環死區,比如將允許的誤差范圍設為0.5,則最終結果在 1或 2都認為是沒有誤差,這時將目標值 與實際值之差強制設為 0,認為沒有誤差,即限定了閉環死區。

      積分分離的設定

      通過積分分離的方式來實現抗積分飽和,積分飽和是指執行機構達到極限輸出能力了,仍無法到達目標值,在很長一段時間內無法消除靜差造成的。

      例如,PWM輸出到了100%,仍達不到期望位置,此時若一直進行誤差累加,在一段時間后, PID 的積分項累計了很大的數值,如果這時候到達了目標值或者重新設定了目標值,由于積分由于累計的誤差很大,系統并不能立即調整到目標值,可能造成超調或失調的現象。

      解決積分飽和的一種方法是使用積分分離,該方法是在累計誤差小于某個閾值才使用積分項,累計誤差過大則不再繼續累計誤差,相當于只使用了PD控制器。

      控制流程圖

      帶有閉環死區與積分分離的PID控制流程如下圖:

      完整的位置PID代碼如下:

      /** * @brief 位置PID算法實現 * @param actual_val:實際值 * @note 無 * @retval 通過PID計算后的輸出 */ #define LOC_DEAD_ZONE 60 /*位置環死區*/ #define LOC_INTEGRAL_START_ERR 200 /*積分分離時對應的誤差范圍*/ #define LOC_INTEGRAL_MAX_VAL 800 /*積分范圍限定,防止積分飽和*/ float location_pid_realize(PID *pid, float actual_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_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算法實現*/ pid->output_val = pid->Kp * pid->err + pid->Ki * pid->integral + pid->Kd * (pid->err - pid->err_last); /*誤差傳遞*/ pid->err_last = pid->err; /*返回當前實際值*/ return pid->output_val; }

      速度PID實現

      速度PID的實現代碼與位置PID的類似:

      /** * @brief 速度PID算法實現 * @param actual_val:實際值 * @note 無 * @retval 通過PID計算后的輸出 */ #define SPE_DEAD_ZONE 5.0f /*速度環死區*/ #define SPE_INTEGRAL_START_ERR 100 /*積分分離時對應的誤差范圍*/ #define SPE_INTEGRAL_MAX_VAL 260 /*積分范圍限定,防止積分飽和*/ float speed_pid_realize(PID *pid, float actual_val) { /*計算目標值與實際值的誤差*/ pid->err = pid->target_val - actual_val; /* 設定閉環死區 */ if( (pid->err>-SPE_DEAD_ZONE) && (pid->errerr = 0; pid->integral = 0; pid->err_last = 0; } /*積分項,積分分離,偏差較大時去掉積分作用*/ if(pid->err > -SPE_INTEGRAL_START_ERR && pid->err < SPE_INTEGRAL_START_ERR) { pid->integral += pid->err; /*積分范圍限定,防止積分飽和*/ if(pid->integral > SPE_INTEGRAL_MAX_VAL) { pid->integral = SPE_INTEGRAL_MAX_VAL; } else if(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; /*返回當前實際值*/ return pid->output_val; }

      串級控制代碼

      //周期定時器的回調函數 void AutoReloadCallback() { static uint32_t location_timer = 0; // 位置環周期 static __IO int encoderNow = 0; /*當前時刻總計數值*/ static __IO int encoderLast = 0; /*上一時刻總計數值*/ int encoderDelta = 0; /*當前時刻與上一時刻編碼器的變化量*/ float actual_speed = 0; /*實際測得速度*/ int actual_speed_int = 0; int res_pwm = 0;/*PID計算得到的PWM值*/ static int i=0; /*【1】讀取編碼器的值*/ encoderNow = read_encoder() + EncoderOverflowCnt*ENCODER_TIM_PERIOD;/*獲取當前的累計值*/ encoderDelta = encoderNow - encoderLast; /*得到變化值*/ encoderLast = encoderNow;/*更新上次的累計值*/ /*【2】位置PID運算,得到PWM控制值*/ if ((location_timer++ % 2) == 0) { float control_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; /*【3】速度PID運算,得到PWM控制值*/ actual_speed_int = actual_speed; res_pwm = pwm_val_protect((int)speed_pid_realize(&pid_speed, actual_speed)); /*【4】PWM控制電機*/ set_motor_rotate(res_pwm); /*【5】數據上傳到上位機顯示*/ set_computer_value(SEND_FACT_CMD, CURVES_CH1, &encoderNow, 1); /*給通道1發送實際的電機【位置】值*/ }

      PID的計算是通過定時器調用,每10ms一次,從代碼中可以看到,內環(速度PID)控制的周期要比外環(位置PID)的周期短,位置PID是每兩次循環計算一次,因為內環控制著最終的輸出,這個輸出對應的就是實際場景中的控制量 (本實驗最終控制的是位置),位置是無法突變,是需要時間積累的,所以內環輸出盡可能快些。

      視頻演示

      電機控制進階3——PID串級控制

      視頻中,測試以不同的目標速度到達目標位置,視頻后半段測試引入干擾情況下的控制效果:

      視頻連接:https://www.bilibili.com/video/BV1QK4y1g7yg

      開源代碼

      本篇以及前面幾篇電機與PID的完整程序代碼,共享至我的gitee倉庫。

      https://gitee.com/xxpcb/stm32-motor-pid

      單片機 嵌入式 視頻

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:數據湖探索的Serverless計算
      下一篇:Spring Security 竟然可以同時存在多個過濾器鏈?
      相關文章
      亚洲成av人片天堂网无码】| 亚洲国产精品无码久久久不卡| 亚洲精华国产精华精华液好用| 亚洲无砖砖区免费| 亚洲精品无码成人片在线观看| 亚洲最大福利视频网站| 亚洲一级Av无码毛片久久精品| 亚洲高清一区二区三区| 亚洲日本一区二区| 国产成人精品日本亚洲专区 | 亚洲高清在线mv| 亚洲人成网77777色在线播放 | 亚洲Av无码专区国产乱码DVD| 在线观看亚洲专区| 亚洲一区在线观看视频| 久久亚洲精品中文字幕无码| 亚洲人成电影在线播放| 亚洲精品视频免费| 久久久久无码专区亚洲av| 亚洲精品视频久久久| 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲码在线中文在线观看| 国产亚洲综合网曝门系列| 亚洲国产天堂久久久久久| 亚洲国产精品碰碰| 超清首页国产亚洲丝袜| 亚洲中文字幕第一页在线| 国产亚洲一区二区精品| 亚洲国产精品久久久久婷婷软件| 亚洲午夜精品久久久久久人妖| 亚洲精品免费在线视频| 亚洲一级黄色大片| 亚洲欧美日韩中文二区| 亚洲宅男精品一区在线观看| 亚洲精品午夜久久久伊人| 国产精品亚洲精品青青青| 亚洲丁香婷婷综合久久| 亚洲精品WWW久久久久久| 亚洲综合AV在线在线播放| 亚洲AV乱码久久精品蜜桃| 亚洲美女大bbbbbbbbb|