Detailed introduction of PID algorithm

1 Introduction

1.1 Overview

Proportion (Proportion) Integral (Integral) Differential (Differential) controller (PID controller or three-term controller) is a control loop mechanism using feedback, widely used in industrial control systems and various other applications requiring continuous modulation control . The PID controller continuously calculates the error value e ( t ) e(t)e ( t ) as the difference between the desired set point (SP) and the measured process variable (PV), and applying corrections based on proportional, integral, and derivative terms (denoted P, I, and D, respectively), so that name.
insert image description here
insert image description here
r ( t ) r(t)r ( t ) is the desired process value or set point(SP) (SP)(SP) y ( t ) y(t) y ( t ) is the measured process value(PV) (PV)(PV)

1.2 Historical development

  • In 1911, the first PID controller was developed by Elmer Sperry.
  • It was not until 1922 that the Russian-American engineer Nicolas Minorsky first used theoretical analysis to formulate a formal control law for what we now call PID, or three-term control. Minorsky was researching and designing automatic ship steering systems for the U.S. Navy at the time, and his analysis was based on observations of helmsmen. He pointed out that the helmsman steered the ship not only based on the current heading error, but also on past errors and the current rate of change; Minorsky then did the math on this. His goal is stability, not general control, which greatly simplifies the problem.
  • In 1933, TIC (Taylor Instrument Company) implemented a fully adjustable front pneumatic controller. A few years later, control engineers eliminated the steady-state error found in proportional controllers by returning the end to some false value until the error was non-zero. This return includes the error, which is called a proportional-integral controller.
  • In 1940, the first pneumatic PID controller was developed with derivative action to reduce overshoot problems.
  • In 1942, Ziegler & Nichols introduced tuning rules, where engineers find and set suitable parameters for PID controllers.
  • In the mid-1950s, automatic PID controllers were widely used in industry. Most modern PID controls in industry are implemented as DCS, PLC or microcontroller programs.

1.3 Application

  • rocket attitude control
  • UAV hovering control, etc.
  • camera stabilizer, camera gimbal
  • balance car
  • Automobile cruise control, steering control
  • engine speed control
  • Temperature controller on 3D printer
  • In the field of industrial automation, about 95% of closed-loop operations use PID controllers.

1.4 Advantages and disadvantages

1.5 Comparison with ON/OFF type controller

Closed loop systems like PID controllers include a feedback control system. The system uses a fixed point to evaluate the feedback variable to generate an error signal. Based on this, it changes the system output. This process will continue until the error reaches zero, otherwise the value of the feedback variable is equal to a fixed point.

This controller provides good results compared to ON/OFF type controllers. In an on/off type controller, only two conditions are required to manage the system. Most HVAC systems, refrigerators use this method. For example, in a refrigerator, it cools the interior until it reaches the desired temperature, then turns off the cooler until it reaches a set point above the desired temperature. Turns on once the process value is below the fixed point. Similarly, once the value is above a fixed value, it will be turned off. The output of this controller is unstable and oscillates frequently in the region of the fixed point. However, compared with ON/OFF type controllers, PID controllers are more stable and accurate.
insert image description here

1.6 Response Types

Introduction to PID

Systems driven by PID controllers typically have three types of responses: underdamped, overdamped, and critically damped.
insert image description here
insert image description here

  • An underdamped response oscillates around a reference value before stabilizing.
  • The overdamped response rises slowly and does not exceed the reference value.
  • A critically damped response has the fastest rise time without exceeding the reference value.

2 official

2.1 PID system definition and formula

insert image description here

r ( t ) r(t) r ( t ) setpoint, reference, is the desired process value or setpoint( SP ) (SP)(SP)
y ( t ) y(t) y ( t ) output, process variable, is the measured process value, output value( PV ) (PV)(PV)
e ( t ) e(t) e ( t ) error, is the deviation;
u ( t ) u(t)u ( t ) control effort, is the control amount;

The remarkable feature of the PID controller is that it can use the influence of the three control items of proportional, integral and differential on the output of the controller to carry out precise and optimal control.

PID controller, continuously calculates the error value e ( t ) e(t)e ( t ) as the difference between desired set pointsSP = r(t) SP=r(t)SP=r ( t ) and the measured process variablePV = y ( t ) : e ( t ) = r ( t ) − y ( t ) PV=y(t):e(t)=r(t)-y(t )PV=y(t):e(t)=r(t)y ( t ) , and apply corrections based on proportional, integral, and derivative terms. The controller tries to minimize the time-varying erroru ( t ) u(t)u(t)。manipulated variable (MV)。

u ( t ) = M V ( t ) = K p e ( t ) + K i ∫ 0 t e ( τ ) d τ + K d d e ( t ) d t (1-1) u(t)=MV(t)=K_pe(t)+K_i \int_{0}^{t}e(τ)dτ+K_d \dfrac{de(t)}{dt}\tag{1-1} u(t)=M V ( t )=Kpe(t)+Ki0tand ( τ ) d τ+Kddtd e ( t )( 1-1 )
u ( t ) = P ∗ Deviation + I ∗ Area + D ∗ Slope u(t)=P*Deviation+ I*Area+ D*Slopeu(t)=Pdeviation+Iarea+Dslope

K p K_p Kpis the proportional gain, this parameter can produce large changes, speed up the response of the system, and may cause the system to overshoot and oscillate;
K i K_iKiis the integral gain, which accelerates the movement of the process towards the set point;
K d K_dKdis the derivative gain, which helps to reduce the overshoot amplitude and oscillation times of the system;
t is time or instantaneous time (now);
τ \tauτ is the integral variable (takes values ​​from time 0 to present t).

K p K_p Kp, K i K_i Ki, K d K_d Kdare non-negative numbers representing the coefficients (sometimes denoted P, I, and D) of the proportional, integral, and derivative terms, respectively.

From PID Controllers:Theory, Design and Tuning

u ( t ) = M V ( t ) = K p ( e ( t ) + 1 T i ∫ 0 t e ( τ ) d τ + T d d e ( t ) d t ) (1-2) u(t)=MV(t)=K_p \Bigl(e(t)+ \dfrac1{T_i} \int_{0}^{t}e(τ)dτ + T_d \dfrac{de(t)}{dt} \Bigl) \tag{1-2} u(t)=M V ( t )=Kp(e(t)+Ti10tand ( τ ) d τ+Tddtd e ( t ))(1-2)

In the standard form of the equation, K i K_iKiand K d K_dKdRespectively replaced by K p T i \dfrac{K_p}{T_i}TiKpand K p T d K_pT_dKpTd;The advantage of this is that T i , T d T_i, T_dTi,Tdhas some understandable physical meaning, since they represent integral time and differential time, respectively. K p T i \dfrac{K_p}{T_i}TiKpDetermine how long the controller can tolerate the output staying above or below the set point. K p T d K_pT_dKpTdis the time constant over which the controller tries to approach the setpoint.

2.2 PID digital formula

Since computer control is a kind of sampling control, it can only calculate the control quantity according to the deviation at the sampling time, but cannot continuously output the control quantity like analog control for continuous control. Due to this feature, the integral term and differential term in (Equation 1-1) cannot be used directly and must be discretized.
The method of discretization is: with τ \tauτ is the sampling period, k is the sampling number, then the discrete sampling timek τ k\tauk τ corresponds to the continuous time t, the integral is approximated by the rectangular method, and the differential is approximated by the first-order backward difference. The following approximate transformation can be made:
t ≈ k τ ( k = 0 , 1 , 2 , . . . ) u ( t ) ≈ u ( k ) e ( t ) ≈ e ( k ) ∫ 0 te ( τ ) d τ ≈ τ ∑ j = 0 ke ( j τ ) = τ ∑ j = 0 kejde ( t ) dt ≈ e ( k τ ) − e ( ( k − 1 ) τ ) τ = ek − ek − 1 τ \begin{align} t & ≈ k \tau (k=0,1,2,...) \notag\\ u(t) & ≈ u(k) \notag\\ e(t) & ≈ e(k) \notag\\ \int_{0}^{t}e(τ)dτ & ≈ \tau \sum_{j =0}^ke(j \tau) = \tau \sum_{j=0}^k e_j \tag{2-1}\\ \dfrac{de(t)}{dt} & ≈ \dfrac{e( k\tau)-e((k-1)\tau)}{\tau} = \dfrac{e_k-e_{k-1}}{\tau} \notag \end{align}tu(t)e(t)0tand ( τ ) d τdtd e ( t )k τ ( k=0,1,2,...)u(k)e(k)tj=0ke ( ) _=tj=0kejte ( k t )e((k1 ) t )=tekek1(2-1)

deviation e ( i τ ) e(i\tau)e ( i τ ) , abbreviated ase ( i ) e(i)e ( i ) orei e_iei;
control quantity u ( i τ ) u(i\tau)u ( i τ ) , abbreviated asu ( i ) u(i)u ( i ) orui u_iui;

2.3 Positional PID Algorithm

Substituting (Formula 2-1) into (Formula 1-1), the discrete PID expression can be obtained as
u ( k ) = K pe ( k ) + K i τ ∑ j = 0 ke ( j ) + K de ( k ) − e ( k − 1 ) τ (2-2) u(k)=K_pe(k)+K_i \tau \sum_{j=0}^{k}e(j) + K_d \dfrac{e( k)-e(k-1)}{\tau}\tag{2-2}u(k)=Kpe(k)+Kitj=0ke ( j )+Kdte(k)e(k1)( 2-2 )
Substituting (Formula 2-1) into (Formula 1-2), the discrete PID expression can be obtained as
u ( k ) = K p ( e ( k ) + τ T i ∑ j = 0 ke ( j ) + T de ( k ) − e ( k − 1 ) τ ) (2-3) u(k)=K_p \Bigl(e(k)+ \dfrac{\tau}{T_i} \sum_{j =0}^{k}e(j) + T_d \dfrac{e(k)-e(k-1)}{\tau} \Bigl) \tag{2-3}u(k)=Kp(e(k)+Titj=0ke ( j )+Tdte(k)e(k1))(2-3)

The integral coefficient and differential coefficient are replaced as follows: Note: τ \tau
must be usedτ is a fixed value, or the change is small enough to be ignored, so that P, I, and D are fixed constants, and it is possible to adjust
K i = K p T i K d = K p T d KI = K p ∗ τ T i = K i τ KD = K p T d τ = KD τ \begin{align} K_i & = \dfrac{K_p}{T_i} \notag\\ K_d & = K_pT_d \notag\\ K_I & = \dfrac{K_p*\tau }{T_i} = K_i \tau \tag{2-4}\\ K_D & = K_p\dfrac{T_d}{\tau} = \dfrac{K_D}{\tau} \notag\\ \end{align}KiKdKIKD=TiKp=KpTd=TiKpt=Kit=KptTd=tKD(2-4)

The advantage of this is that T i , T d T_i, T_dTi,Tdhas some understandable physical meaning.
T i T_iTiRepresents the integral time constant;
T d T_dTdstands for the differential time constant.

K I K_I KIand KD K_DKDSubstituting into (Formula 2-2), you can get the discrete PID expression as
u ( k ) = K pe ( k ) + KI ∑ j = 0 ke ( j ) + KD [ e ( k ) − e ( k − 1 ) ] (2-5) u(k) = K_pe(k)+K_I \sum_{j=0}^{k}e(j) + K_D [e(k)-e(k-1)]\tag {2-5}u(k)=Kpe(k)+KIj=0ke ( j )+KD[e(k)e(k1)](2-5)

k k k is the sampling sequence number,k = 0 , 1 , 2 , . . . k=0,1,2,...k=0,1,2,...
u k u_k ukis the computer output value at the kth sampling moment;
ek e_kekis the bias value input at the kth sampling time;
ek − 1 e_{k-1}ek1The bias value input for the k-1th sampling time;

2.4 Incremental PID algorithm

The so-called incremental PID means that the output of the digital controller is only the increment of the control quantity Δ uk \Delta u_ku _k. When the control quantity required by the actuator is incremental rather than the absolute value of the position quantity, the incremental PID control algorithm can be used for control.

Incremental PID control algorithm can be deduced by (2-2). From (Formula 2-2), the output value of the controller at the k-1th sampling moment can be obtained as:

u ( k − 1 ) = K pe ( k − 1 ) + K i τ ∑ j = 0 k − 1 e ( j ) + K de ( k − 1 ) − e ( k − 2 ) τ (2-6) u(k-1) = K_pe(k-1)+K_i \tau \sum_{j=0}^{k-1}e(j) + K_d \dfrac{e(k-1)-e(k- 2)}{\year}\tag{2-6}u(k1)=Kpe(k1)+Kitj=0k1e ( j )+Kdte(k1)e(k2)(2-6)

From (Formula 2-3), the output value of the controller at the k-1th sampling moment can be obtained:
u ( k − 1 ) = K p ( e ( k − 1 ) + τ T i ∑ j = 0 k − 1 e ( j ) + T de ( k − 1 ) − e ( k − 2 ) τ ) (2-7) u(k-1)=K_p \Bigl(e(k-1)+ \dfrac{\tau }{T_i} \sum_{j=0}^{k-1}e(j) + T_d \dfrac{e(k-1)-e(k-2)}{\tau} \Bigl) \tag{ 2-7}u(k1)=Kp(e(k1)+Titj=0k1e ( j )+Tdte(k1)e(k2))(2-7)

Figure (Fig. 2-3) and (Fig. 2-7) show that the inverse cycle of the PID cycle:
Δ uk = u ( k ) − u ( k − 1 ) = K p ( e ( k ) − e ( k − 1 ) + τ Tie ( k ) + T de ( k ) − 2 e ( k − 1 ) + e ( k − 2 ) τ ) = K p ( 1 + τ T i + T d τ ) e ( k ) − K p ( 1 + 2 T d τ ) e ( k − 1 ) + K p T d τ e ( k − 2 ) = A e ( k ) + B e ( k − ) + C e ( k − 2 ) \begin{align} \Delta u_k = u(k) - u(k-1) & = K_p \Bigl(e(k)-e(k-1)+ \dfrac{ \tau}{T_i} e(k) + T_d \dfrac{e(k)-2e(k-1)+e(k-2)}{\tau}\Bigl) \notag \\ & = K_p(1 +\dfraction{\tau}{T_i}+\dfraction{T_d}{\tau})e(k) - K_p(1+\dfraction{2T_d}{\tau})e(k-1)+K_p\dfraction {T_d}{\tau}e(k-2) \tag{2-8} \\ & = Ae(k) + Be(k-1) + Ce(k-2) \notag \end{align}u _k=u(k)u(k1)=Kp(e(k)e(k1)+Tite(k)+Tdte(k)2e ( k _1)+e(k2))=Kp(1+Tit+tTd)e(k)Kp(1+t2T _d)e(k1)+KptTde(k2)=A e ( k )+Be(k1)+C e ( k2)(2-8)

It can be seen from (Formula 2-8) that if the computer control system adopts a constant sampling period τ \tauτ , once A, B, C are determined, as long as the deviation values ​​of the three measurements before and after are used, the control quantity can be obtained by (Formula 2-8).

Compared with the positional PID algorithm (Formula 2-3), the incremental PID control algorithm only needs to keep the deviation value of the three moments before the current moment, the cumulative error is small, and the amount of calculation is much smaller, so in practice be widely used.

The positional PID control algorithm can also derive the recursive calculation formula through the incremental control algorithm:
u ( k ) = u ( k − 1 ) + Δ u ( k ) (2-9) u(k) = u(k -1) + \Delta u(k) \tag{2-9}u(k)=u(k1)+Δu ( k ) _( 2-9 )
(Formula 2-9) is the digital recursive PID control algorithm widely used in computer control at present.

3 Debugging Tips

insert image description here

4 code implementation

python

From Implementing PID control algorithm using python simulation

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)

insert image description here

c/c++

From PID super detailed tutorial - PID principle + cascade PID + C code + online simulation parameter adjustment

//首先定义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);//等待一定时间再开始下一次循环
    }
}

single ring effect
insert image description here
insert image description here

C language code of cascade PID

//此处需要插入上面的单级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);//延时一段时间
    }
}

double ring effect
insert image description here

5 Double loop control

in series

From PID closed-loop control principle of embedded software algorithm

If the motor control needs to control both speed and position, because the speed and position are related, it needs to be connected in series.
insert image description here

in parallel

From PID closed-loop control principle of embedded software algorithm

There is no correlation between the attitude angle and the speed, and each is counted as a single-way control
insert image description here

6 examples

Tracking car

Understand the PID control algorithm in one article

The tracking effect of the car can be seen.

Double-loop control of stepping motor position and speed in wildfire

11. Realization of double-loop control of stepping motor position and speed

9. Realization of speed loop control of stepping motor and 10. Realization of position loop control of stepping motor Introduced that single loop control can improve the performance of the motor very well, but it still has its limitations.

The speed loop is used to precisely control the speed of the motor, but it is difficult to accurately control the stop position; the
position loop is used to precisely control the angle of the motor, but the speed has to be artificially limited to prevent stalling.

The double-loop control of the position loop and the speed loop realizes the precise adjustment of the position and the automatic control of the speed.
insert image description here

Under this control, the encoder not only plays the role of feedback position, but also plays the role of feedback speed.

Parameter tuning skills : When setting PID parameters, adopt the method of inner loop first and then outer loop, that is, first use the speed loop alone to control, after getting satisfactory parameters, then put the position loop outside, set the parameters of the position loop, and finally according to The overall effect fine-tunes the speed loop parameters.

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-incremental PID algorithm implementation-incremental 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 - double closed-loop control of stepper motor position and speed

 /**
   * @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\r\n", 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("欢迎使用野火 电机开发板 步进电机位置速度双环控制 例程\r\n");
   printf("按下按键3启动和停止电机\r\n");
   /* 初始化时间戳 */
   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
     }
   }
 }

other

Supplementary knowledge points

Analog digitization

In actual digital applications, the integral and differential terms in the PID system need to be discretized. A similar typical application is a digital oscilloscope. For digital oscilloscopes, it cannot directly quantify analog signals. The alternative is to continue periodic sampling, and then display the obtained series of sampling points. When the sampling rate is higher, the displayed image is more realistic. This is the limit in mathematics. with differential thinking.
insert image description here

Shannon's Law of Sampling

  • Sampling
    Continuous variable function f(x) cannot be processed directly by computer, choose f ( x ) f(x)The value of f ( x ) at a discrete pointf ( xn ) f(x_n)f(xn) , this process is called sampling.
  • Theorem content
    Shannon sampling theorem is for finite bandwidth functions.
    In order to restore the analog signal without distortion, the sampling frequency should not be less than twice the highest frequency in the analog signal spectrum.

reference

1. wiki–PID controller
2. What is a PID Controller : Working & Its Applications
3. PID Controllers: Theory, Design and Tuning
4. 11. Realization of double-loop control of stepping motor position and speed
5. PID closed-loop control of embedded software algorithm Principle
6. Detailed explanation of PID control algorithm
7. Xiaoyuan Gungun-mathematical derivation of PID algorithm
8. What is PID? Story + animation, easy to understand! Wonderful explanation!
9. PID Control
10. PID Algorithm Derivation and Analysis
11. PID Control
12. Proportional Integral Derivative (PID)
13. Lectures: Control Theory: PID Control (Classical Control Theory)
14. PID Control Algorithm
https://blog.csdn .net/kilotwo/article/details/79828201
https://blog.csdn.net/kilotwo/article/details/79829669
https://blog.csdn.net/kilotwo/article/details/79952530
15. Introduction to PID
16. PID control principle and incremental PID algorithm
17. PID super detailed tutorial - PID principle + cascade PID + C code + Online simulation tuning
18, Going Straight with PID
19, Build a PID Controller with Python 2019
20, PID algorithm principle, one picture to understand the three parameters of PID
21, one article to understand the PID control algorithm
22, PID control (four) ( Single-loop and double-loop PID)
23. PID control principle, after reading the beginning, you will see the end!
24. PID algorithm and robotic arm application (with simple Python implementation)
25. Popular understanding of PID
formula 26. Using python simulation to realize PID control algorithm
27. Implementation of PID controller in Python
28. Controlling Physical Systems
29. PID control

Guess you like

Origin blog.csdn.net/qq_38880380/article/details/131585006