<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

PID算法推導+調試技巧+雙閉環控制+代碼仿真詳解

lilihe92 ? 來源:CSDN ? 2023-12-20 09:27 ? 次閱讀

正文

介紹

1.1 概述

比例(Proportion)積分(Integral)微分(Differential)控制器PID控制器或三項控制器)是一種采用反饋的控制回路機制,廣泛應用于工業控制系統和需要連續調制控制的各種其他應用。

PID控制器連續計算誤差值 e(t) 作為所需設定點(SP) 和測量過程變量(PV)之間的差值,并應用基于比例、積分和導數項(分別表示為P、I和D)的校正,因此得名。

920036d2-9e76-11ee-8b88-92fbcf53809c.png

921159b2-9e76-11ee-8b88-92fbcf53809c.png

r(t) 是期望的過程值或設定點(SP),y(t) 是測量的過程值(PV)。

1.2 歷史發展

1911年,第一個PID控制器是由Elmer Sperry開發的。

1922 年,俄裔美國工程師尼古拉斯·米諾斯基 ( Nicolas Minorsky)才首次利用理論分析制定了我們現在所說的 PID 或三項控制的正式控制律。米諾斯基當時正在為美國海軍研究和設計自動船舶轉向系統,他的分析基于對舵手的觀察。

他指出,舵手不僅根據當前航向誤差,還根據過去的誤差以及當前的變化率來駕駛船舶;然后 Minorsky 對此進行了數學處理。他的目標是穩定,而不是一般控制,這大大簡化了問題。

1933年,TIC(泰勒儀器公司)實現了完全可調節的前氣動控制器。幾年后,控制工程師通過將末端返回到一些假值,直到誤差不為零,消除了比例控制器中發現的穩態誤差。這個返回包含了誤差,這被稱為比例積分控制器。

1940年,第一個氣動PID控制器通過導數動作開發,以減少超調問題。

1942年,Ziegler & Nichols引入了調諧規則,由工程師發現和設置PID控制器的合適參數。

20世紀50年代中期,自動PID控制器在工業上得到了廣泛的應用。工業中大多數現代 PID 控制都是作為DCS、PLC單片機程序來實現的。

1.3 應用

?火箭的姿態控制

?無人機懸??刂频?/p>

?相機穩定器、相機云臺

?平衡小車

?汽車的定速巡航控制、轉向控制

?發動機轉速控制

?3D打印機上的溫度控制器

?工業自動化領域,大約95%的閉環操作使用PID控制器。

1.4 與 ON/OFF 型控制器對比

像PID控制器這樣的閉環系統包括一個反饋控制系統。該系統利用一個固定點對反饋變量進行評估,從而產生誤差信號。在此基礎上,它改變系統輸出。這個過程將繼續,直到誤差達到零,否則反饋變量的值就等于一個固定點。

與ON/OFF型控制器相比,該控制器提供了良好的效果。在開/關型控制器中,只需兩個條件即可管理系統。大多數暖通空調系統、冰箱都采用這種方法。

例如,在冰箱中,它會冷卻內部直到達到所需溫度,然后關閉冷卻器,直到達到高于所需溫度的設定值。一旦工藝值低于固定點,則開啟。

類似地,一旦該值高于固定值,它將關閉。這種控制器的輸出不穩定,在不動點的區域內振蕩頻繁。然而,與ON/OFF型控制器相比,PID 控制器更加穩定和準確。

921f8e56-9e76-11ee-8b88-92fbcf53809c.png

1.6 響應類型

由PID控制器驅動的系統通常具有三種類型的響應:欠阻尼、過阻尼和臨界阻尼。

922e53aa-9e76-11ee-8b88-92fbcf53809c.png

923be3f8-9e76-11ee-8b88-92fbcf53809c.gif

?欠阻尼響應在穩定之前圍繞參考值振蕩。

?過阻尼響應上升緩慢并且不會超過參考值。

?臨界阻尼響應具有最快的上升時間,且不會超過參考值。

公式

2.1 PID 系統定義與公式

924a37d2-9e76-11ee-8b88-92fbcf53809c.png

r(t) setpoint, reference,是期望的過程值或設定值(SP);

y(t) output, process variable,是測量的過程值,輸出值(PV);

e(t) error,是偏差;

u(t) control effort,是控制量;

PID控制器的顯著特點是能夠利用比例、積分和微分這三個控制項對控制器輸出的影響來進行精確和最優的控制。

PID 控制器,不斷計算誤差值e(t) 作為所需設定點之間的差異SP=r(t) 和測量的過程變量PV=y(t):e(t)=r(t)?y(t) ,并應用基于比例、積分和導數項的修正。

控制器嘗試通過調整控制變量來最小化隨時間變化的誤差u(t)。manipulated variable (MV)。

925abf6c-9e76-11ee-8b88-92fbcf53809c.png

9268b96e-9e76-11ee-8b88-92fbcf53809c.png

9274f3aa-9e76-11ee-8b88-92fbcf53809c.png

2.2 PID 數字公式

由于計算機控制是一種采樣控制,它只能根據采樣時刻的偏差計算控制量,而不能像模擬控制那樣連續輸出控制量,進行連續控制。由于這一特點,(式 1-1)中的積分項和微分項不能直接使用,必須進行離散化處理。

離散化處理的方法為:以τ作為采樣周期,k作為采樣序號,則離散采樣時間kτ對應著連續時間t,用矩形法數值積分近似代替積分,用一階后向差分近似代替微分,可作如下近似變換:

928487e8-9e76-11ee-8b88-92fbcf53809c.png

2.3 位置式 PID 算法

將(式 2-1)代入(式 1-1),就可以得到離散的 PID 表達式為

929407cc-9e76-11ee-8b88-92fbcf53809c.png

將(式 2-1)代入(式 1-2),就可以得到離散的PID 表達式為

92a160fc-9e76-11ee-8b88-92fbcf53809c.png

積分系數、微分系數做如下替換:

注意:必須使τ為定值,或者變化小到可以忽略,這樣P、I、D才是固定常數,才可能調節

92af9956-9e76-11ee-8b88-92fbcf53809c.png92bd6108-9e76-11ee-8b88-92fbcf53809c.png

2.4 增量式 PID 算法

92ca4422-9e76-11ee-8b88-92fbcf53809c.png

增量式 PID 控制算法可以通過(式 2-2)推導出。由(式 2-2)可以得到控制器的第 k-1 個采樣時刻的輸出值為:

92d712a6-9e76-11ee-8b88-92fbcf53809c.png

由(式 2-3)可以得到控制器的第 k-1 個采樣時刻的輸出值為:

92e2b494-9e76-11ee-8b88-92fbcf53809c.png

用(式 2-3)減去(式 2-7)相減并整理,就可以得到增量式 PID 控制算法公式:

92f2589a-9e76-11ee-8b88-92fbcf53809c.png

由(式 2-8)可以看出,如果計算機控制系統采用恒定的采樣周期τ,一旦確定 A、 B、 C,只要使用前后三次測量的偏差值,就可以由(式 2-8)求出控制量。

增量式 PID 控制算法與位置式 PID 算法(式 2-3)相比,只需要保持當前時刻以前三個時刻的偏差值即可,累計誤差較小,計算量小的多,因此在實際中得到廣泛的應用。

而位置式 PID 控制算法也可以通過增量式控制算法推出遞推計算公式:

9301c546-9e76-11ee-8b88-92fbcf53809c.png

(式 2-9)就是目前在計算機控制中廣泛應用的數字遞推 PID 控制算法。

調試技巧

93078e90-9e76-11ee-8b88-92fbcf53809c.gif

代碼實現

python

import numpy as np
import matplotlib.pyplot as plt


class PositionPID(object):
  """位置式PID算法實現"""


  def __init__(self, target, cur_val, dt, max, min, p, i, d) -> None:
    self.dt = dt # 循環時間間隔
    self._max = max # 最大輸出限制,規避過沖
    self._min = min # 最小輸出限制
    self.k_p = p # 比例系數
    self.k_i = i # 積分系數
    self.k_d = d # 微分系數


    self.target = target # 目標值
    self.cur_val = cur_val # 算法當前PID位置值,第一次為設定的初始位置
    self._pre_error = 0 # t-1 時刻誤差值
    self._integral = 0 # 誤差積分值




  def calculate(self):
    """
    計算t時刻PID輸出值cur_val
    """
    error = self.target - self.cur_val # 計算當前誤差
    # 比例項
    p_out = self.k_p * error 
    # 積分項
    self._integral += (error * self.dt)
    i_out = self.k_i * self._integral
    # 微分項
    derivative = (error - self._pre_error) / self.dt
    d_out = self.k_d * derivative


    # t 時刻pid輸出
    output = p_out + i_out + d_out


    # 限制輸出值
    if output > self._max:
      output = self._max
    elif output < self._min:
 ? ? ? ? ? ?output = self._min
 ? ? ? ?
 ? ? ? ?self._pre_error = error
 ? ? ? ?self.cur_val = output
 ? ? ? ?return self.cur_val


 ? ?def fit_and_plot(self, count = 200):
 ? ? ? ?"""
 ? ? ? ?使用PID擬合setPoint
 ? ? ? ?"""
 ? ? ? ?counts = np.arange(count)
 ? ? ? ?outputs = []


 ? ? ? ?for i in counts:
 ? ? ? ? ? ?outputs.append(self.calculate())
 ? ? ? ? ? ?print('Count %3d: output: %f' % (i, outputs[-1]))


 ? ? ? ?print('Done')
 ? ? ? ?# print(outputs)
 ? ? ? ?
 ? ? ? ?plt.figure()
 ? ? ? ?plt.axhline(self.target, c='red')
 ? ? ? ?plt.plot(counts, np.array(outputs), 'b.')
 ? ? ? ?plt.ylim(min(outputs) - 0.1 * min(outputs), max(outputs) + 0.1 * max(outputs))
 ? ? ? ?plt.plot(outputs)
 ? ? ? ?plt.show()


pid = PositionPID(10, -5, 0.5, 100, -100, 0.2, 0.1, 0.01)
pid.fit_and_plot(150)

9318518a-9e76-11ee-8b88-92fbcf53809c.png

c/c++

//首先定義PID結構體用于存放一個PID的數據
typedef struct
{
   float kp,ki,kd;//三個系數
  float error,lastError;//誤差、上次誤差
  float integral,maxIntegral;//積分、積分限幅
  float output,maxOutput;//輸出、輸出限幅
}PID;
 
//用于初始化pid參數的函數
void PID_Init(PID *pid,float p,float i,float d,float maxI,float maxOut)
{
  pid->kp=p;
  pid->ki=i;
  pid->kd=d;
  pid->maxIntegral=maxI;
  pid->maxOutput=maxOut;
}
 
//進行一次pid計算
//參數為(pid結構體,目標值,反饋值),計算結果放在pid結構體的output成員中
void PID_Calc(PID *pid,float reference,float feedback)
{
  //更新數據
  pid->lastError=pid->error;//將舊error存起來
  pid->error=reference-feedback;//計算新error
  //計算微分
  float dout=(pid->error-pid->lastError)*pid->kd;
  //計算比例
  float pout=pid->error*pid->kp;
  //計算積分
  pid->integral+=pid->error*pid->ki;
  //積分限幅
  if(pid->integral > pid->maxIntegral) pid->integral=pid->maxIntegral;
  else if(pid->integral < -pid->maxIntegral) pid->integral=-pid->maxIntegral;
  //計算輸出
  pid->output=pout+dout+pid->integral;
  //輸出限幅
  if(pid->output > pid->maxOutput) pid->output=pid->maxOutput;
  else if(pid->output < -pid->maxOutput) pid->output=-pid->maxOutput;
}
 
PID mypid;//創建一個PID結構體變量
 
int main()
{
  //...這里有些其他初始化代碼
  PID_Init(&mypid,10,1,5,800,1000);//初始化PID參數
  while(1)//進入循環運行
  {
    float feedbackValue=...;//這里獲取到被控對象的反饋值
    float targetValue=...;//這里獲取到目標值
    PID_Calc(&mypid,targetValue,feedbackValue);//進行PID計算,結果在output成員變量中
    設定執行器輸出大小(mypid.output);
    delay(10);//等待一定時間再開始下一次循環
  }
}

單環效果

932614b4-9e76-11ee-8b88-92fbcf53809c.gif

933632f4-9e76-11ee-8b88-92fbcf53809c.png

串級PID的C語言代碼

//此處需要插入上面的單級PID相關代碼
 
//串級PID的結構體,包含兩個單級PID
typedef struct
{
  PID inner;//內環
  PID outer;//外環
  float output;//串級輸出,等于inner.output
}CascadePID;
 
//串級PID的計算函數
//參數(PID結構體,外環目標值,外環反饋值,內環反饋值)
void PID_CascadeCalc(CascadePID *pid,float outerRef,float outerFdb,float innerFdb)
{
  PID_Calc(&pid->outer,outerRef,outerFdb);//計算外環
  PID_Calc(&pid->inner,pid->outer.output,innerFdb);//計算內環
  pid->output=pid->inner.output;//內環輸出就是串級PID的輸出
}
 
CascadePID mypid;//創建串級PID結構體變量
 
int main()
{
  //...其他初始化代碼
  PID_Init(&mypid.inner,10,0,0,0,1000);//初始化內環參數
  PID_Init(&mypid.outer,5,0,5,0,100);//初始化外環參數
  while(1)//進入循環運行
  {
    float outerTarget=...;//獲取外環目標值
    float outerFeedback=...;//獲取外環反饋值
    float innerFeedback=...;//獲取內環反饋值
    PID_CascadeCalc(&mypid,outerTarget,outerFeedback,innerFeedback);//進行PID計算
    設定執行機構輸出大小(mypid.output);
    delay(10);//延時一段時間
  }
}

雙環效果

9346dc8a-9e76-11ee-8b88-92fbcf53809c.gif

雙環控制

串聯

如果電機控制既要控制速度又要控制位置,因為速度和位置相關,所以需要串聯。

935cd3dc-9e76-11ee-8b88-92fbcf53809c.png

并聯

姿態角度與速度間無相關性,各自單獨算一路控制

936b0204-9e76-11ee-8b88-92fbcf53809c.png

示例

循跡小車

可見小車的循跡效果。

野火中步進電機位置速度雙環控制

步進電機速度環控制實現和 10. 步進電機位置環控制實現介紹了單環控制已經能很好地提高電機的性能了,但是仍有其局限性。

使用速度環精確控制了電機的轉速,但是停止的位置難以精確控制;

使用位置環精確控制了電機轉過的角度,卻不得不人為限制速度來防止堵轉。

位置環和速度環雙環控制,既實現位置的精確調節又實現速度的自動控制。

937b170c-9e76-11ee-8b88-92fbcf53809c.png

該控制下,編碼器不僅起到了反饋位置的作用,也起到了反饋速度的作用。

調參技巧:在PID參數整定時,采取先內環再外環的方法,也就是先單獨使用速度環控制,得到滿意的參數后, 再把位置環套在外面,整定位置環參數,最后根據整體效果對速度環參數進行微調。

bsp_pid.h

/*pid*/
typedef struct
{
 float target_val;   //目標值
 float actual_val;   //實際值
 float err;      //定義當前偏差值
 float err_next;    //定義下一個偏差值
 float err_last;    //定義上一個偏差值
 float Kp, Ki, Kd;   //定義比例、積分、微分系數
}_pid;

bsp_stepper_ctrl.h

/*宏定義*/
/*******************************************************/
#define TIM_STEP_FREQ   (SystemCoreClock/TIM_PRESCALER) // 頻率ft值


/*電機單圈參數*/
#define STEP_ANGLE             1.8f         //步進電機的步距角 單位:度
#define FSPR       (360.0f/STEP_ANGLE) //步進電機的一圈所需脈沖數


#define MICRO_STEP    32                     //細分器細分數
#define SPR        (FSPR*MICRO_STEP)  //細分后一圈所需脈沖數


#define PULSE_RATIO    (float)(SPR/ENCODER_TOTAL_RESOLUTION)//步進電機單圈脈沖數與編碼器單圈脈沖的比值
#define SAMPLING_PERIOD  50          //PID采樣頻率,單位Hz


#define MOVE_CTRL     0.1f          //啟用速度環控制量
#define TARGET_DISP    20          //步進電機運動時的目標圈數,單位:轉
#define TARGET_SPEED_MAX 800         // 目標速度的最大值


typedef struct {
 unsigned char stepper_dir : 1;        //步進電機方向
 unsigned char stepper_running : 1;      //步進電機運行狀態
 unsigned char MSD_ENA : 1;          //驅動器使能狀態
}__SYS_STATUS;

bsp_stepper_ctrl.c-增量式PID算法實現-增量式PID

/**
  * @brief 增量式PID算法實現
  * @param  val:當前實際值
  * @note  無
  * @retval 通過PID計算后的輸出
  */
 float PID_realize(_pid *pid, float temp_val)
{
  /*傳入實際值*/
  pid->actual_val = temp_val;
  /*計算目標值與實際值的誤差*/
  pid->err=pid->target_val-pid->actual_val;


  /*PID算法實現*/
  float increment_val = pid->Kp*(pid->err - pid->err_next) + pid->Ki*pid->err + pid->Kd*(pid->err - 2 * pid->err_next + pid->err_last);
  /*傳遞誤差*/
  pid->err_last = pid->err_next;
  pid->err_next = pid->err;
  /*返回增量值*/
  return increment_val;
 }

bsp_stepper_ctrl.c-步進電機位置速度雙閉環控制

 /**
  * @brief 步進電機位置速度雙閉環控制
  * @retval 無
  * @note  基本定時器中斷內調用
  */
 void Stepper_Ctrl(void)
{
  /* 編碼器相關變量 */
  static __IO float last_count = 0;
  __IO float capture_count = 0;
  __IO float capture_per_unit = 0;
  /* 經過pid計算后的期望值 */
  static __IO float speed_cont_val = 0.0f;
  static __IO float move_cont_val = 0.0f;
  static int cont_val = 0;


  /* 當電機運動時才啟動pid計算 */
  if((sys_status.MSD_ENA == 1) && (sys_status.stepper_running == 1))
  {
   /* 計算編碼器脈沖數 */
   capture_count = (int)__HAL_TIM_GET_COUNTER(&TIM_EncoderHandle) + (encoder_overflow_count * ENCODER_TIM_PERIOD);
   /* 計算速度環的傳入值 */
   capture_per_unit = capture_count - last_count;
   last_count = capture_count;


   /* 編碼器脈沖累計值作為實際值傳入位置環pid控制器 */
   move_cont_val += PID_realize_move(&move_pid, (float)capture_count);// 進行 PID 計算
   /* 判斷運動方向 */
   move_cont_val > 0 ? (MOTOR_DIR(CW)) : (MOTOR_DIR(CCW));
   /* 判斷是否啟用速度環 */
   if (fabsf(move_cont_val) >= MOVE_CTRL)
   {
    /* 傳遞位置環計算值,便于計算*/
    cont_val = move_cont_val;


    /* 目標速度上限處理 */
    if (cont_val > TARGET_SPEED_MAX)
    {
     cont_val = TARGET_SPEED_MAX;
    }
    else if (cont_val < -TARGET_SPEED_MAX)
 ? ? ? {
 ? ? ? ? cont_val = -TARGET_SPEED_MAX;
 ? ? ? }


 #if defined(PID_ASSISTANT_EN)
 ? ? ? int32_t temp = cont_val;
 ? ? ? set_computer_value(SEED_TARGET_CMD, CURVES_CH2, &temp, 1); ? ? // 給通道 2 發送目標值
 #endif
 ? ? ? /* 設定速度的目標值 */
 ? ? ? set_pid_target(&speed_pid, cont_val);
 ? ? ? /* 單位時間內的編碼器脈沖數作為實際值傳入速度環pid控制器 */
 ? ? ? speed_cont_val += PID_realize_speed(&speed_pid, (float)capture_per_unit);// 進行 PID 計算
 ? ? ? /* 由于OC_Pulse_num為uint16_t變量,取速度環輸出值的絕對值進行后續計算*/
 ? ? ? cont_val = fabsf(speed_cont_val);
 ? ? ? /* 計算比較計數器的值 */
 ? ? ? OC_Pulse_num = ((uint16_t)(TIM_STEP_FREQ / (cont_val * PULSE_RATIO * SAMPLING_PERIOD))) >> 1;
   }
   else
   {
    /* 計算比較計數器的值 */
    OC_Pulse_num = ((uint16_t)(TIM_STEP_FREQ / ((float)move_cont_val * PULSE_RATIO))) >> 1;
   }
 #if PID_ASSISTANT_EN
   int Temp_ch2 = capture_per_unit;  // 上位機需要整數參數,轉換一下
   int Temp_ch1 = capture_count;
   set_computer_value(SEED_FACT_CMD, CURVES_CH2, &Temp_ch2, 1); // 給通道 1 發送實際值   // 給通道 2 發送實際值
   set_computer_value(SEED_FACT_CMD, CURVES_CH1, &Temp_ch1, 1);   // 給通道 1 發送實際值


 #else
   printf("實際值:%d,目標值:%.0f
", capture_per_unit, pid.target_val);// 打印實際值和目標值
 #endif
  }
  else
  {
   /*停機狀態所有參數清零*/
   last_count = 0;
   speed_cont_val = 0;
   move_cont_val = 0;
   speed_pid.actual_val = 0;
   speed_pid.err = 0;
   speed_pid.err_last = 0;
   speed_pid.err_next = 0;
   move_pid.actual_val = 0;
   move_pid.err = 0;
   move_pid.err_last = 0;
   move_pid.err_next = 0;
  }
 }

main

 /**
  * @brief 主函數
  * @param 無
  * @retval 無
  */
 int main(void)
{
  /* 初始化系統時鐘為168MHz */
  SystemClock_Config();
  /*初始化USART 配置模式為 115200 8-N-1,中斷接收*/
  DEBUG_USART_Config();
  printf("歡迎使用野火 電機開發板 步進電機位置速度雙環控制 例程
");
  printf("按下按鍵3啟動和停止電機
");
  /* 初始化時間戳 */
  HAL_InitTick(5);
  /*按鍵中斷初始化*/
  Key_GPIO_Config();
  /*led初始化*/
  LED_GPIO_Config();
  /* 初始化基本定時器定時,20ms產生一次中斷 */
  TIMx_Configuration();
  /* 編碼器接口初始化 */
  Encoder_Init();
  /*步進電機初始化*/
  stepper_Init();
  /* 上電默認停止電機 */
  Set_Stepper_Stop();
  /* PID算法參數初始化 */
  PID_param_init();
 // MOTOR_DIR(CW);


  /* 目標位置轉換為編碼器的脈沖數作為pid目標值 */
  move_pid.target_val = TARGET_DISP * ENCODER_TOTAL_RESOLUTION;
  int32_t Temp = TARGET_DISP * ENCODER_TOTAL_RESOLUTION;
 #if PID_ASSISTANT_EN
  set_computer_value(SEED_STOP_CMD, CURVES_CH1, NULL, 0);  // 同步上位機的啟動按鈕狀態
  set_computer_value(SEED_TARGET_CMD, CURVES_CH1, &Temp, 1);// 給通道 1 發送目標值
 #endif


  while(1)
  {
   /* 掃描KEY1,啟動電機 */
   if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON )
   {
   #if PID_ASSISTANT_EN
    Set_Stepper_Start();
    set_computer_value(SEED_START_CMD, CURVES_CH1, NULL, 0);// 同步上位機的啟動按鈕狀態
   #else
    Set_Stepper_Start();
   #endif
   }
   /* 掃描KEY2,停止電機 */
   if( Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON )
   {
   #if PID_ASSISTANT_EN
    Set_Stepper_Stop();
    set_computer_value(SEED_STOP_CMD, CURVES_CH1, NULL, 0);// 同步上位機的啟動按鈕狀態
   #else
    Set_Stepper_Stop();
   #endif
   }
   /* 掃描KEY3,增大目標位置*/
   if( Key_Scan(KEY3_GPIO_PORT,KEY3_PIN) == KEY_ON )
   {
    /* 目標位置增加48000,對應電機位置增加20圈 */
    move_pid.target_val += 48000;


   #if PID_ASSISTANT_EN
    int temp = move_pid.target_val;
    set_computer_value(SEED_TARGET_CMD, CURVES_CH1, &temp, 1);// 給通道 1 發送目標值
   #endif
   }
   /* 掃描KEY4,減小目標位置 */
   if( Key_Scan(KEY4_GPIO_PORT,KEY4_PIN) == KEY_ON )
   {
    /* 目標位置減小48000,對應電機位置減少20圈 */
    move_pid.target_val -= 48000;


   #if PID_ASSISTANT_EN
    int temp = move_pid.target_val;
    set_computer_value(SEED_TARGET_CMD, CURVES_CH1, &temp, 1);// 給通道 1 發送目標值
   #endif
   }
  }
 }

補充知識點

模擬量數字化

實際數字化應用中,PID 系統中的積分項和微分項需要進行離散化處理。

類似的典型應用有數字示波器。對于數字示波器來說它無法直接量化模擬信號,替代的辦法就是持續周期性采樣,然后將得到的一系列采樣點顯示出來,當采樣速率越高,顯示的圖像越真實,這就是數學中極限的與微分的思想。

9386b7c4-9e76-11ee-8b88-92fbcf53809c.png

香農(Shannon) 采樣定律

93944646-9e76-11ee-8b88-92fbcf53809c.png

?定理內容

香農取樣定理是針對有限帶寬函數的,為了不失真地恢復模擬信號,采樣頻率應該不小于模擬信號頻譜中最高頻率的2倍。






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數字示波器
    +關注

    關注

    6

    文章

    495

    瀏覽量

    33282
  • PID控制器
    +關注

    關注

    2

    文章

    156

    瀏覽量

    18366
  • 雙閉環控制
    +關注

    關注

    1

    文章

    10

    瀏覽量

    9975
  • python
    +關注

    關注

    52

    文章

    4695

    瀏覽量

    83547

原文標題:一文搞定 PID算法推導+調試技巧+雙閉環控制+代碼仿真

文章出處:【微信號:最后一個bug,微信公眾號:最后一個bug】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    三相逆變器電壓閉環控制仿真

    三相逆變器電壓閉環控制仿真 一、引言 三相逆變器是電力電子技術中的重要組成部分,廣泛應用于新能源發電、電動汽車、工業自動化等領域。電壓閉環控制是逆變器控制策略中的一種常見方法,通過對輸
    的頭像 發表于 12-14 11:16 ?705次閱讀

    SVPWM的原理推導控制算法詳解

    SVPWM的原理推導控制算法詳解,不錯的資料,值得一看
    發表于 01-28 15:09

    基于PID的電機閉環控制淺析

    核心的速度控制器、三相異步交流電動機、測速發電機反饋等構成。速度控制系統的控制框圖如圖1所示。速度控制系統是一個閉環系統。
    發表于 01-28 17:40

    用labview實現伺服電機的閉環控制,用PID(泛布爾算法控制,有大神會么????

    用labview實現伺服電機的閉環控制,用PID(泛布爾算法控制,有大神會么????
    發表于 12-19 17:02

    基于閉環模糊PID控制器的開關電源控制的設計

    閉環控制律存在一定的缺陷,同時這一缺陷已經越來越無法適應集成電路工業對供電需求的發展。開關電源是一種非常典型的非線性系統,無法建立精確的模型。于此同時模糊PID
    發表于 10-08 15:32

    采用了PID控制器的閉環控制策略

    一、理論下圖是采用了PID控制器的閉環控制策略。 PID控制器的傳遞函數: 上式中,Y是控制器的
    發表于 08-23 07:07

    通過PID算法控制電機轉速和舵機角度實現閉環控制

    ,通過PID算法控制電機轉速和舵機角度,實現閉環控制。硬件電路分為:主控模塊、傳感器模塊、電源模塊、電機驅動模塊、速度檢測模塊、車距檢測模塊、通信模塊和藍牙串口等輔助
    發表于 08-26 10:45

    位置閉環控制描述

    這是三閉環里的最后一個:位置閉環控制。如果你認真的閱讀并推導了前章節,那么這一節將會很好理解。一如既往,我會使用簡練的語言來描述復雜的問題。本章節主要涉及位置環的一些概念,以及控制框圖
    發表于 09-03 09:21

    SPS閉環調試步驟

    閉環控制是指什么?SPS閉環調試步驟有哪些?
    發表于 09-24 06:20

    SPWM變頻電源的閉環控制是什么意思

    什么叫SPWM變頻電源的閉環控制?中港揚盛變頻電源電壓、電流閉環控制系統是一種多環系統,設計多環系統的一般方法 是從內環開始,然后再逐步向外面擴大,接著一環一環地進高設計。CNZG
    發表于 12-28 06:12

    PLC的PID控制怎么實現閉環控制呢?

    PLC的PID控制怎么實現閉環控制?在程序中采用PID調節指令就可以了嗎,是不是伺服電機走長了,可用PID調整那這輸入誤差怎么得到?比如說輸
    發表于 03-30 17:18

    智能車速度控制pid(電機閉環控制算法

    對于智能車的電機閉環控制算法,我之所以標題沒有寫上“智能車電機PID閉環控制算法”是因為PID
    發表于 02-05 19:36 ?5.2w次閱讀

    詳細分析PID控制算法原理和調試口訣

    PID是一個閉環控制算法。因此要實現PID算法,必須在硬件上具有閉環控制,就是得有反饋。
    的頭像 發表于 08-13 14:18 ?2.1w次閱讀
    詳細分析<b class='flag-5'>PID</b><b class='flag-5'>控制</b><b class='flag-5'>算法</b>原理和<b class='flag-5'>調試</b>口訣

    電機PID控制閉環控制

    電機PID控制閉環控制 1 PID控制 1.1 位置式PID 理論公式:
    發表于 05-06 11:48 ?4次下載
    電機<b class='flag-5'>PID</b><b class='flag-5'>控制</b>和<b class='flag-5'>閉環控制</b>

    PID回路控制閉環控制原理

    PID控制器是應用最廣泛的閉環控制器,它根據給定值與被控實測值之間的偏差;按照PID算法計算出控制
    發表于 05-17 13:03 ?4945次閱讀
    <b class='flag-5'>PID</b>回路<b class='flag-5'>控制</b>及<b class='flag-5'>閉環控制</b>原理
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>