【编程与算法基础】算法——PID算法

1. 常规位式算法

1.1 位式控制系统基本思想

位式控制系统基本结构图如下:
在这里插入图片描述
以温度为例说明二位式控制系统。

  • 期待温度SV与实际温度PV比较: 期待温度SV是期望达到的目标温度,实际温度PV是通过温度传感器测量得到的当前温度值。将实际温度PV与期待温度SV进行比较,得到误差信号,表示实际温度与设定温度之间的差距。
  • 控制器根据误差信号生成控制信号OUT: 控制器接收误差信号,并根据预设的控制策略(位式控制算法)生成相应的控制信号OUT。
  • 控制信号OUT驱动执行器件:控制信号OUT驱动执行器件,该执行器件一般是开关型部件,如MOS管,继电器之类。 当控制信号OUT满足某个设定阈值时,执行器处于开启状态,允许热量或冷量进入或离开系统。当控制信号OUT不满足设定阈值时,执行器处于关闭状态,阻止热量或冷量进入或离开系统。
  • 反馈机制监测温度变化:控制系统持续监测温度变化,通过温度传感器实时获取温度数据。 控制器根据实际温度PV与期待温度SV的差距,调整控制信号OUT以保持温度稳定。

通过以上步骤,位式控制系统能够根据实际温度PV与期待温度SV之间的差异,驱动执行器件来调整温度,并通过反馈机制持续监测和调整,以实现温度控制的目标。

1.2 位式控制系统特点

位式控制系统(On/Off Control System)是一种简单且常用的控制系统,具有以下特点:

  • 二值控制:位式控制系统的输出是二值的,通常是开或关的状态。当控制信号满足设定的阈值时,执行器处于开启状态,允许能量进入或离开系统;当控制信号不满足设定的阈值时,执行器处于关闭状态,阻止能量的流动。
  • 离散控制:位式控制系统采用离散的控制策略,即在设定阈值上下进行开关操作。当测量值超过设定的阈值时,控制系统将执行器切换到开启状态;当测量值低于设定的阈值时,控制系统将执行器切换到关闭状态。这种离散的控制方式简化了系统的设计和实施。
  • 快速响应:由于位式控制系统是基于阈值的开关操作,它具有很快的响应速度。一旦测量值超过或低于设定的阈值,控制系统会立即进行切换,以改变执行器的状态。这使得位式控制系统在某些快速反应要求的应用中表现良好。
  • 开关延迟:位式控制系统存在开关延迟的问题。当测量值接近设定阈值时,控制系统可能会在阈值附近进行开关切换,导致系统的输出产生振荡或不稳定的情况。这种开关延迟可能会引入过冲和震荡,特别是在控制信号的变化速率较高时。
  • 非精确控制:位式控制系统无法实现精确的连续调节,因为它只能在设定阈值上下进行切换。这导致控制量(如温度)在设定阈值范围内可能会有一定的波动。因此,位式控制系统适用于对控制精度要求相对宽松的应用。
  • 简单和经济:位式控制系统设计和实施相对简单,通常只需要一个开关和一个传感器。它不需要复杂的控制算法和调节器件,使得它成为一种经济实用的控制方法。

1.3 位式控制系统不足

位式控制系统存在一些不足之处:

  • 非精确性:位式控制系统无法实现精确的连续调节,因为它只能在设定阈值上下进行切换。这导致控制量在设定阈值范围内可能会有一定的波动,无法实现精确的控制。
  • 开关延迟:由于位式控制系统的离散性质,存在开关延迟的问题。当测量值接近设定阈值时,控制系统可能会在阈值附近进行开关切换,导致系统的输出产生振荡或不稳定的情况。这种开关延迟可能会影响系统的响应速度和稳定性。
  • 振荡和过冲:由于开关延迟和非精确性的存在,位式控制系统容易引起振荡和过冲现象。当控制信号在设定阈值附近波动时,执行器可能频繁切换状态,导致系统输出的不稳定性和过度调节。
  • 限制控制精度:由于位式控制系统只能在设定阈值上下进行切换,无法进行连续调节,因此控制精度受到限制。在一些对控制精度要求较高的应用中,位式控制系统可能无法满足需求。
  • 不适用于复杂系统:位式控制系统适用于简单的开关控制,但对于复杂系统的控制则显得不够灵活和精确。复杂的动态系统往往需要更为精细的控制方法以实现更好的控制性能。

基于位式控制系统种种不足之处,因此诞生了更为精细的控制方法——PID控制算法

2. PID算法基本原理

PID控制系统基本结构图如下:
在这里插入图片描述

PID算法(Proportional-Integral-Derivative Algorithm)是一种经典的控制算法,广泛应用于工业自动化领域。它基于对系统误差的比例、积分和微分进行控制,以实现精确的动态控制。PID包含三方面的控制,即比例控制(P)、积分控制(I)和微分控制(D)

  • 比例控制(Proportional Control):比例控制是PID算法的基本组成部分。它根据当前系统的误差(偏差)与设定值之间的差异,生成一个与误差成比例的控制输出。比例控制的作用是根据误差的大小来提供快速而稳定的响应,使得控制器输出与误差成正比。比例增益参数Kp决定了比例控制的灵敏度,即控制器输出的变化程度。
  • 积分控制(Integral Control):积分控制是为了消除系统的静态误差而引入的。它对误差的累积进行控制,并生成一个与误差累积值成比例的控制输出。积分控制的作用是在长时间内消除系统的偏差,使得系统能够精确地跟踪设定值。积分增益参数Ki决定了积分控制的影响程度,即控制器输出与误差累积值的关系。
  • 微分控制(Derivative Control):微分控制是为了预测系统的未来变化趋势而引入的。它根据当前误差的变化率生成一个与变化率成比例的控制输出。微分控制的作用是提供对误差变化率的快速响应,使得系统能够更好地调节自身的行为。微分增益参数Kd决定了微分控制的灵敏度,即控制器输出与误差变化率的关系。

PID控制器根据上述比例、积分和微分控制的组合生成最终的控制输出。具体而言,PID控制器的输出值由以下公式计算:

OUT = Kp * Ek + Ki * Sk + Kd * Dk

其中,Ek表示当前的误差,Sk表示误差的累积值,Dk表示误差的变化。Kp、Ki和Kd分别是比例增益、积分增益和微分增益参数。

PID控制器周期性地计算误差的比例、积分和微分部分,并将它们相加得到最终控制信号OUT的输出。

下面详细介绍比例控制(P)、积分控制(I)和微分控制(D)。

3. 比例控制(P)

3.1 比例控制的概念和作用

比例控制是基于误差大小的控制策略,它利用误差的比例关系来生成控制输出。具体而言,比例控制器根据当前的误差值,将其乘以一个比例增益参数Kp,得到比例部分的输出。

其作用如下所示:

  • 快速响应:比例控制的主要作用是根据误差的大小提供快速而稳定的响应。当误差增大时,比例控制器会增加控制输出,使执行器件或系统做出更大的调整,以减小误差。这种快速响应有助于系统尽快接近设定值,减少稳态误差。
  • 控制增益调节:比例增益参数Kp决定了比例控制的灵敏度,即控制器输出的变化程度。通过调节比例增益,可以改变控制器对误差的敏感程度。较大的比例增益会使控制器对误差更敏感,产生更大的控制输出,但可能会引入过度调节或振荡。较小的比例增益则会减小控制输出的变化幅度,可能导致系统的响应较慢。
  • 稳定性控制:比例控制可以帮助控制系统维持稳定的运行状态。当系统达到设定值时,比例控制器会使控制输出趋于零,避免过度调节。通过适当的比例增益参数选择,可以使系统在稳态下保持平衡,减小波动和振荡。

说明:比例控制具有一定的局限性。过大的比例增益可能导致系统振荡、不稳定或过度调节,而过小的比例增益可能导致系统响应较慢、稳态误差较大。因此,在实际应用中需要根据具体系统的特性和控制要求,通过实验或调整来确定合适的比例增益参数。

3.2 比例增益对系统响应的影响

比例增益是PID控制算法中比例控制部分的参数,它对系统响应具有重要影响。下面是比例增益对系统响应的影响:

  • 灵敏度:
    比例增益决定了控制器对于误差的敏感程度。较大的比例增益会使控制器更敏感地对待误差,产生更大的控制输出。这意味着系统会更迅速地对误差进行校正,以减小偏差。因此,较大的比例增益可以提高系统的灵敏度,使其更快速地响应变化。
  • 快速响应:
    较大的比例增益可以加快系统的响应速度。当系统受到扰动或误差变大时,比例控制会生成更大的输出信号,以快速调整系统状态。这有助于系统尽快接近设定值,并减小稳态误差。
  • 稳定性:
    尽管较大的比例增益可以提高系统的响应速度,但过大的比例增益可能导致系统不稳定。如果比例增益设置过大,控制器的输出信号可能会引起过度调节或振荡,导致系统无法达到稳定状态。因此,在选择比例增益时需要权衡响应速度和稳定性之间的平衡,以确保系统的稳定运行。
  • 振荡和超调:
    过大的比例增益可能引起系统的振荡和超调现象。当比例增益设置过高时,系统会出现周期性的振荡,导致控制输出的快速变化。这会导致系统偏离设定值,并可能产生超调现象,即系统的输出超过设定值范围。因此,在设置比例增益时需要避免过度增加,以减小振荡和超调的风险。

3.3 比例控制的数学表达式和示例

比例控制的数学表达式可以表示为:

KOUT = Kp * Ek

其中,KOUT表示比例控制器的输出,Kp表示比例增益参数,Ek表示当前的误差或偏差。

举例:
假设有一个温度控制系统,目标是将温度维持在25°C。当前的温度测量值为22°C,因此存在一个误差(偏差)为3°C。现在假设设置比例增益参数Kp为2,根据比例控制的数学表达式,可以计算出比例控制的输出:

Output = Kp * Error = 2 * 3°C = 6

因此,根据当前的误差,比例控制的输出为6。这个输出可以用于控制执行器(例如加热器或冷却器),以调整系统的状态,使温度向目标值25°C靠近。

4. 积分控制(I)

4.1 积分控制的概念和作用

积分控制是基于误差的累积值对系统进行控制的一种方法。它通过对误差的积分累积,产生一个与误差累积值成比例的控制输出。积分控制的作用是在长时间内消除系统的稳态误差,使系统能够精确地跟踪设定值。

其作用如下所示:

  • 消除稳态误差:积分控制的主要作用是消除系统的稳态误差。稳态误差是系统在达到平衡状态后仍存在的误差。通过对误差的积分累积,积分控制可以逐渐增加控制输出,直到稳态误差被消除为止。积分控制可以补偿系统的静态偏差,使系统能够精确地跟踪设定值。
  • 提高系统的稳定性:积分控制可以增加系统的稳定性。当系统受到外部扰动或系统参数变化时,积分控制可以持续地对误差进行修正,使系统保持稳定。通过积分的作用,控制器可以对误差进行持续的补偿,使系统能够更好地抵抗干扰和变化,提高系统的稳定性。
  • 改善系统的动态响应:积分控制还可以改善系统的动态响应。在系统发生快速变化或突发扰动时,比例控制和微分控制往往无法立即响应,而积分控制可以积累误差并产生较大的修正作用。积分控制的积分累积效应可以使系统更快地恢复到设定值附近,减少过渡过程中的超调和震荡现象。

4.2 积分时间对系统稳定性和误差消除的影响

积分时间(或称为积分时间常数)是PID控制算法中积分部分的一个重要参数,它对系统稳定性和误差消除有着显著的影响。下面是积分时间对系统稳定性和误差消除的影响:

  • 系统稳定性:
    积分时间对系统稳定性有着重要的影响。较大的积分时间会使积分部分的响应较慢,导致控制器对误差的积分累积速度变慢。这意味着系统的稳定性较好,能够更好地抵抗外部干扰和参数变化。然而,如果积分时间设置过大,可能会导致系统的稳态误差无法及时消除,使系统不能达到预期的稳定状态。因此,积分时间需要根据系统的特性和要求进行合理的调整,以确保系统的稳定性。
  • 误差消除:
    积分时间决定了控制器对误差的积分累积速度。较小的积分时间可以使控制器更快地对误差进行积分累积,从而更快地消除稳态误差。这对于要求快速消除误差的应用非常重要,例如温度控制系统中需要快速达到设定温度。然而,如果积分时间设置过小,可能会引入过度积分的问题,导致系统出现振荡或不稳定的情况。因此,积分时间的选择需要平衡误差消除速度和系统稳定性之间的关系。

4.3 积分控制的数学表达式和示例

积分控制的数学表达式可以表示为:

IOUT = Ki * Sk

其中, IOUT表示控制输出,Ki表示积分增益参数,Sk=E1+E2+E3+……+Ek-2+Ek-1+Ek,表示误差和。

举例:
假设有一个温度控制系统,目标是将温度维持在某个设定值。控制器通过测量温度值和设定值之间的误差来进行调节。假设温度的设定值为SV,实际测量到的温度值为PV,误差定义为EK = SV-PV。现在假设一秒钟温度传感器测量了10次温度值,那么这10次误差和S10=EK1+EK2+EK3+…+EK10,根据积分控制的数学表达式,可以计算出积分控制的输出:

IOUT = Ki * S10

在实际应用中,控制器会周期性地计算误差的积分累积,并将其作为控制输出的一部分。控制器根据积分输出的大小来调整执行器的行为,以减小误差并使系统逐渐趋向于设定值。

5. 微分控制(D)

5.1 微分控制的概念和作用

微分控制是基于系统误差的变化率来调节控制输出。它通过测量误差的变化率,即误差的导数或微分,来预测系统的未来变化趋势。微分控制根据误差的变化速度提供快速的响应,并通过调整控制输出来稳定系统。

其作用如下所示:

  • 改善系统响应速度:微分控制对误差的变化率非常敏感,它可以快速检测到误差变化的趋势。当误差的变化率较大时,微分控制会提供更大的控制输出,以加快系统的响应速度。这有助于系统快速调整并逼近设定值。
  • 抑制振荡和过冲:微分控制通过抑制系统的快速变化来减小振荡和过冲的影响。当系统接近设定值时,微分控制可以减缓控制输出的变化率,避免系统产生剧烈的波动和不稳定的响应。这有助于提高系统的稳定性和平滑性。
  • 预测未来趋势:微分控制根据误差的变化率提供了对系统未来变化趋势的预测。通过观察误差的变化率,微分控制可以预测系统的行为,并采取相应的控制策略。这使得微分控制能够提前调整控制输出,以适应系统变化,并更好地满足控制要求。

5.2 微分时间对系统响应和抗干扰能力的影响

微分时间是PID控制算法中微分控制部分的一个重要参数,它对系统的响应速度和抗干扰能力具有重要影响。下面是微分时间对系统响应和抗干扰能力的影响:

  • 系统响应:
    微分时间决定了微分控制对误差变化率的敏感程度。较小的微分时间可以更快地响应误差的变化,因为它可以更频繁地计算误差的变化率。这有助于提高系统的响应速度和跟踪能力,使得系统能够更快地调整控制输出以逼近设定值。然而,如果微分时间过小,可能会引入噪声和测量误差的影响,导致不稳定的控制输出。因此,微分时间的选择需要考虑系统的实际噪声水平和测量误差情况。通常情况下,微分时间的选择需要进行实验和调试,以获得最佳的响应性能。
  • 抗干扰能力:
    微分控制具有抗干扰的能力,可以帮助系统抑制外部干扰对系统的影响。较小的微分时间可以更快地响应干扰的变化,因为它可以更敏感地检测干扰的变化率。这有助于减小干扰对系统的影响,并提高系统的抗干扰能力。然而,如果微分时间选择过小,可能会放大噪声和测量误差的影响,导致控制输出产生不稳定的振荡。因此,微分时间的选择需要平衡响应速度和抗干扰能力之间的关系,以确保系统的稳定性和性能。

5.3 微分控制的数学表达式和示例

微分控制的数学表达式可以表示为:

DOUT = Kd * Dk

其中,DOUT表示微分控制的输出,Kd为微分增益,Dk=Ek - Ek-1,表示误差的变化。

举例:
假设有一个温度控制系统,目标是将温度稳定在某个设定值。通过测量温度,可以得到当前温度PV和设定值SV之间的误差Ek。使用PID控制算法,可以根据比例、积分和微分控制来调整控制输出。在这个示例中,将关注微分控制部分。假设系统中存在干扰或突然的温度变化,希望通过微分控制来快速响应并抑制这些变化。
假设微分增益Kd设定为0.5,可以根据当前误差EK的变化Dk=Ek - Ek-1来计算微分控制的输出DOUT。如果Ek的变化Dk很大,表示温度正在迅速变化,那么微分控制会产生较大的调节输出。如果Ek的变化Dk较小,表示温度变化缓慢,那么微分控制会产生较小的调节输出。

例如,假设在某一时刻,温度的测量值PV为T = 25°C,设定值为SV= 30°C,误差Ek = SV - PV = 30 - 25 = 5°C。此时,还需要知道误差的变化Dk。如果在上一个时刻温度的测量值为PV-1= 27°C,误差为Ek-1 = SV - PV-1 = 30 - 27 = 3°C,则误差的变化可以计算为Dk = Ek-Ek-1 = 5 - 3) = 2°C/s。

根据微分控制的数学表达式,可以计算微分控制的输出:

DOUT = Kd * Dk = 0.5 * 2 = 1

这意味着微分控制会产生1调节输出,用于抑制温度变化。如果变化继续增大,微分控制的输出也会相应增大,以更快地调整系统。通过不断地测量温度和计算误差的变化,微分控制可以快速响应系统的动态变化,并提供相应的控制输出。

6. 基于单片机的位置式PID算法实现

6.1 比例处理

比例处理比较简单,单纯的比例因子乘以当前偏差值即可实现。
代码实现如下:

    pid.Ek=pid.Set_v-pid.Cur_v;     //pid当前偏差=期待值-当前采集值(比例算法依据)
    Pout=pid.Kp*pid.Ek;             //比例运算输出=比例因子*pid当前偏差

6.2 积分处理

积分处理中,主要是求和Sk的实现。
下面详细说明:

Sk=1/Ti * Sk * T

T为采样周期或称为控制周期也可称为计算周期,由于PID算法最终会输出一个信号去控制执行部件,输出控制信号的来源来自于单片机对传感器负载的状态值,PID算法算出一个数据后就要作用到负载上,作用效果即改变PWM高电平脉宽,用来改变负载的平均功率,若PID算法算的很快,例如100ms算一次,但PWM波的周期为1000ms,当PWM波作用到负载上必须要1000ms才会有一个结论,即控制周期为1000ms,但PID100ms得到一个结果,显然1000ms才能体现到负载上,这样最终导致PID不停的算数据,输出端还未加至负载上,新的结果又出现,所以PID算法不能一直不停做运算,要每过一段时间修正一下输出值,要保证上一次输出的结果已经实施到负载上,若不停的改变数据,则会造成上一次结果还未实施,新的结果又出现,这样得到的效果无意义。因此要根据PWM的周期设定PID的控制周期T。

Ti为积分常数,即积分时间,该值是针对比例积分(PI)控制的算法,与微分控制无关。
由于P算法体现的是传感器当前值与目标值相差的值,差得多则输出多,差的少则输出少;I算法体现的是过去相差值差的多少,过去差得多则输出多,过去差的少则输出少,二者配合起来对输出做控制则有两种情况,POUT认为没有达到要求,输出按照P算法应该输出一个信号控制输出,但有可能IOUT认为历史上那些数据说明原来已超标,或IOUT也可能认为过去那段时间确实也一直未达标,后者即说明P算法和I算法作用相同,都认为应该增大输出信号,当二者作用相同,则IOUT的加入相当于重复了一次POUT信号的作用,即IOUT帮助了POUT对输出产生控制作用,则将IOUT和POUT共同作用的时间称为积分时间常数,积分时间常数也是人为而定的,其数值在分母上,数值太大,Sk就小,则输出就小,即该数值越大,会削弱输出信号;数值太小,Sk就大,则输出就大,即该数值越小,会增强输出信号。此值不能太大也不能太小,工作中要根据情况来调整该值。

积分项最大的缺陷是在第一次到达目标前会产生错误,产生超调,称为过冲现象
举例:
因为若历史上未达标,则会产生输出,假设某设备要控制到100度,早上来的时候室内较冷仅有15度,过一段时间后变为20度,温度逐渐升高,离100度越来越近,直到某一时刻,温度到达了100度,该时刻为第一次到达100度的时刻,但是因为积分项只考虑历史数据,即在到达100度前历史数据都是未达标的,差值都为正数,差值相加后为一个较大的正数,因此在到达100度后,还是会有一个较大的输出,在100度之后,逐渐升温,差值为负,各差值相加后会逐渐趋于0,然后再降温,再升温 ,最终温度变化曲线像Sa(X)函数一样,在温度趋于100度上下波动。
因此有些PID算法为了避免过充现象,会将积分时间常数Ti设定的无穷大,即积分项为0,忽略该作用,当当前值与误差值相差一般为70%——80%时,才将积分项加入进去,该方式称为积分分离法。

综上:可以理解为在未到达目标前积分项可协助比例项,回到正常值,到达正常值之后,比例项就不起作用了,由积分项对输出做控制,因此可见引入积分项的原因为避免在比例项失控的情况下,积分项能继续工作。

代码实现如下:

    pid.Sek+=pid.Ek;                //历史偏差累计求和(积分算法依据)
    ti=pid.T_cpt/pid.Ti;            //计算时间/积分时间
    ki=pid.Kp*ti;                   //积分因子
    Iout=pid.Sek*ki;                //积分算法输出=历史偏差和*积分因子

6.3 微分处理

微分处理中,主要是变化率Dk的实现。
下面详细说明:

Dk=Td * ((Ek-Ek-1) / T)

T与Sk中的T相同。

Td称为微分时间常数,是针对比例微分(PD)控制的算法,与积分控制无关。
由于P算法体现的是传感器当前值与目标值相差的值,有差值则输出,无差值则不工作,D算法体现的是最近有无偏差变化,有变化则开始控制,无变化则不控制,因此P算法和D算法配合起来,总有一个时间点,对输出的控制做用是相同的,该时间点即当前传感器采集的值确实未到达目标值,即P输出,同时发现控制对象的值的偏差值在向增大的趋势发展,即D输出,即DOUT帮助POUT修正输出,因此与比例积分(PI)控制算法相似,将二者共同作用的时间称为微分时间常数。
T的数值不能取得过大,若过大,当偏差变化较大时,微分值会变得很小,导致微分算法结果失效,微分时间常数也是由人为而定,Td越大意味着D算法能有更多时间的帮助P算法。

代码实现如下:

    Del_ek=pid.Ek-pid.Ek_1;         //本次偏差与上次偏差之差(微分算法依据)
    td=pid.Td/pid.T_cpt;            //微分时间/计算时间
    kd=pid.Kp*td;                   //微分因子
    Dout=kd*Del_ek;                 //微分算法输出=微分因子*偏差变化

6.4 完整代码

pid.h中代码如下:

#ifndef	_pid_h_
#define	_pid_h_

#include "stm32f1xx_hal.h"

typedef struct
{
    float Set_v;        //设定值
    float Cur_v;        //当前值
    
    float Kp;           //比例系数
    
    float T_cpt;        //pid计算周期(采样周期)
    float Ti;           //积分时间常数
    float Td;           //微分时间常数
    
    float Ek;           //本次偏差
    float Ek_1;         //上次偏差
    float Sek;          //历史偏差之和
    
    float out0;         //常数,计算值为0时可维持输出,不会暂停输出,一个较小值
    
    float OUT;          //通过以上PID计算应该得到的输出,控制PWM占空比
    
    uint16_t C10ms;
    
    uint16_t pwmcycle;   //pwm周期
}PID;


void Pid_Init(void);     //pid初始化函数(将上次pid各参数写入存储器)
void Pid_Calc(void);     //pid实现函数,最终通过pid算出一个数,控制PWM占空比
void Pid_Out(void);      //输出pid运算结果到负载
#endif 

pid.c中代码如下:

#include "pid.h"
#include "stm32f1xx_hal.h"

#define PWMOUT_H() HAL_GPIO_WritePin(pidout_GPIO_Port , pidout_Pin , GPIO_PIN_SET)      //输出高电平
#define PWMOUT_L() HAL_GPIO_WritePin(pidout_GPIO_Port , pidout_Pin , GPIO_PIN_RESET)    //输出低电平
#define pidout_Pin GPIO_PIN_5
#define pidout_GPIO_Port GPIOF

PID pid;        //PID结构体变量


void    Pid_Init()
{
    pid.Set_v=1.65;                 //电压设定值
    pid.Kp=600;                     //比例系数
    
    pid.T_cpt=1000;                 //pid计算周期1000ms
    pid.Ti=5000;                    //pid积分时间5000ms
    pid.Td=1000;                    //pid微分时间1200ms
    pid.pwmcycle=1000;              //pwm周期不能超过pid计算周期
    pid.out0=1;
}


void    Pid_Calc()                  //完成pid算法(核心)
{
    float ti,ki;                    //积分算法前的系数变量
    
    float Del_ek;                   //本次和上次偏差之差变量
    float td,kd;                    //微分算法前的系数变量
    
    float Pout;                     //比例运算的输出变量
    float Iout;                     //积分运算的输出变量 
    float Dout;                     //微分运算的输出变量
    
    float out;                      //pid运算输出中间变量,因为运算后的结果不一定符合控制要求
    
    if(pid.C10ms<pid.T_cpt/10)      
    {
        return;                     //说明计算周期未到,直接退出
    }

    pid.Ek=pid.Set_v-pid.Cur_v;     //pid当前偏差=期待值-当前采集值(比例算法依据)
    Pout=pid.Kp*pid.Ek;             //比例运算输出=比例因子*pid当前偏差
    
    pid.Sek+=pid.Ek;                //历史偏差累计求和(积分算法依据)
    ti=pid.T_cpt/pid.Ti;            //计算时间/积分时间
    ki=pid.Kp*ti;                   //积分因子
    Iout=pid.Sek*ki;                //积分算法输出=历史偏差和*积分因子
    
    Del_ek=pid.Ek-pid.Ek_1;         //本次偏差与上次偏差之差(微分算法依据)
    td=pid.Td/pid.T_cpt;            //微分时间/计算时间
    kd=pid.Kp*td;                   //微分因子
    Dout=kd*Del_ek;                 //微分算法输出=微分因子*偏差变化
    
    out=Pout+Iout+Dout+pid.out0;    //pid算法输出,理论上是PWM占空比的值 
    //如果pid.OUT(占空比)过大,超过了一个周期最大的占空比值,此时应保持最大占空比
    //如果pid.OUT(占空比)过小,小于0,此时应保持占空比为0
    if(out>pid.pwmcycle)            //如果pid运算最大值大于pwm占空比最大值
        pid.OUT=pid.pwmcycle;       //保持pid运算值为pwm占空比最大值
    if(out<0)                       //如果pid运算最大值小于0
        pid.OUT=0+pid.out0;         //保持pwm占空比为0
    if(out>=0&&out<=pid.pwmcycle)
        pid.OUT=out;                //否则pid运算值为pwm占空比
    
    pid.Ek_1=pid.Ek;                //运算一次后,将本次偏差变为上次偏差
    
    pid.C10ms=0;
}

void Pid_Out()
{
    static uint16_t pw;
    pw++;
    if(pw>=pid.pwmcycle)
        pw=0;
    if(pw<pid.OUT)
        PWMOUT_H();
    else
        PWMOUT_L();   
}

7. 增量式PID算法

位置式PID算法适用于没有记忆功能的执行器件,如继电器,双线可控硅,对于某些有记忆功能的执行器件,如步进电机,可调电位器,一般采用增量式PID算法
增量式PID:计算出的是控制量的增加值,用于控制系统本身具有记忆功能的情况,有记忆功能体现在只需在原来基础上增加(算出的结果为正数)或减少(算出的结果为负数)多少即可。

增量计算公式:∆OUT=OUTk - OUT (k-1)

说明:

OUTk=PIDOUTk=Kp*(Ek + T/Ti * ∑Ek + TD/T * (Ek - E(k-1)) + out0为本次PID输出的值。

OUT(k-1)=PIDOUT(k-1)=Kp*(E(k-1) + T/Ti * ∑E(k-1) + TD/T * (E(k-1)-E(k-2))+ out0为上次PID输出的值。

∆OUT=Kp*(Ek - E(k-1) + T/Ti * Ek + TD/T * (Ek - 2E(k-1) + E(k-2))为增量值。

Ek:当前的偏差值
E(k-1):上次的偏差值
E(k-2):上上次的偏差值
由此可得,只要将最近三次的偏差能够记录到计算机中即可,Kp,Ti,TD需要根据情况调节。

如果掌握了位置式PID算法的实现,那么增量式PID算法的实现比较简单,这里不做赘述。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值