编写公式时的常用的通式

常用通式

一、放量、缩量(成交量函数为VOL)
1、放量:
(1).今天成交量较昨天增加了1倍,表示如下:
 
VOL/REF(VOL,1)>2

(2).今天成交量较10个交易日平均成交量放大了1倍,表示如下:
  
VOL/MA(VOL,10)>2;

(3).今日的5日均量较10个交易日平均成交量放大了1倍,表示如下:
   
MA(VOL,10)/MA(VOL,5)>2;

(4).今日的成交量超过了整个流通盘的5%,表示如下:
   
VOL/CAPITAL>0.05;

其中CAPITAL代表流通股。

2、缩量
(1).今日成交量较昨日减少了一半,表示如下:
     
VOL/REF(VOL,1)<0.5;

(2).今日成交量较10个交易日平均成交量减少一倍,表示如下:
   
VOL/MA(VOL,10)<2; 

(3).今日的5日均量较10个交易日平均成交量减少1倍,表示如下:
   
a:=MA(VOL,10);
b:=REF(a,5);
a/b<2;

(4).今日的成交量低于了整个流通盘的5%,表示如下:
     
VOL/CAPITAL<0.05;

二、上涨、下跌
1、上涨:
(1).今天的涨幅达到5%以上,表示如下:
    
CLOSE/REF(CLOSE,1)>1.05;

(2).5日均价连续上涨,表示如下:
    
a:=MA(CLOSE,5);
b:=REF(a,1);
a>b;

2、下跌:
(1).今天的跌幅达到5%以上,表示如下:
      
CLOSE/REF(CLOSE,1)<0.95;

(2).5日均价连续下跌,表示如下:
    
a:=MA(CLOSE,5);
b:=REF(a,1);
a<b;

(3)、K线的描述
      
CLOSE>OPEN;阳线
CLOSE<OPEN;阴线
OPEN>REF(CLOSE,1);高开
OPEN<REF(CLOSE,1);低开
OPEN>REF(HIGH,1);跳空高开(HIGH为最高价)
OPEN<REF(LOW,1);跳空低开(LOW为最低价)


三、走势特征选股公式的编制
(1)、n日内创新高
  
HHV(HIGH,n)=HHV(HIGH,0) AND BARSCOUNT(CLOSE)>=n;

注:n为指标参数,可在参数设定范围内设定参数范围。HHV(x,n),求n周期内x最高值,n=0则从第一个有效值开始;barscount(x),第一个有效数据到到当前的天数,例如,BARSCOUNT(CLOSE)以日线数据取得上市以来总交易日数。
(2)、n日内创新低
  
LLV(LOW,n)=LLV(LOW,0) AND BARSCOUNT(CLOSE)>=n;

注:n为指标参数,可在参数设定范围内设定参数范围。LLV(x,n),求n周期内x最低值,n=0则从第一个有效值开始。
(3)、n日内阴线多于阳线
  
COUNT(OPEN>CLOSE,n)/n>0.5;

注:n为指标参数,可在参数设定范围内设定参数范围。同时可以自由编辑里面的数值(如0.5等 ,达到确定阴线占全部K线个数的比例)。
(4)、n日内阳线多于阴线
   
COUNT(OPEN<CLOSE,n)/n>0.5;

(5)、n日内上涨多于下跌
   
COUNT(CLOSE>REF(CLOSE,1),n)/n>0.5;

注:n为指标参数,可在参数设定范围内设定参数范围。同时可以自由编辑里面的数值(如0.5等 ,达到确定其中比例)。
(6)、n日内上涨少于下跌
  
COUNT(CLOSE>REF(CLOSE,1),n)/n<0.5;

(7)、连续n日收阳线
   
COUNT(CLOSE>OPEN,n)=n;

(8)、连续n日内收阴线
  
COUNT(CLOSE<OPEN,n)=n;

(9)、连续n天上涨
  
COUNT(CLOSE>REF(CLOSE,1),n)=n;

(10)、连续n天下跌
  
COUNT(CLOSE<REF(CLOSE,1),n)=n;

(11)、首次创新高
   
BARSSINCE(C>HHV(IF(BARSCOUNT(C)=1,HIGH,0),0))+1=1;

(12)、创历史新高
    
HHV(CLOSE,0)=CLOSE;

(13)、创历史新低
      
LLV(CLOSE,0)=CLOSE;

(14)、单日放量
       
A1=MA(VOL,5);
A2=REF(A1,1);
VOL/A2>N AND VOL/SHGZG*100>M


功能:选出单日换手率大于N%,且是较5日均量放大了M倍的股票
解释:MA求简单移动平均,MA(X,N)求X的N日移动平均值,算法:(x1+x2+...+xn)/N;MA(VOL,5)指求5日均量;
(15)、阶段缩量
  
SUM(VOL,n1)/CAPITAL<=n2;

注:n1为要统计的阶段时间,n2为缩量比例,可在参数设定范围内设定参数范围。
(16)、阶段放量
  
SUM(VOL,n1)/CAPITAL>=n2;

注:n1为要统计的阶段时间,n2为y放量比例,可在参数设定范围内设定参数范围。
(17)、持续放量
  
a:=VOL>REF(VOL,1);
COUNT(a,n)=n;

注:其中条件a的含义为成交量较上一交易日放大,n为要统计的阶段时间,可在参数设定范围内设定参数范围。
(18)、持续缩量
  
a:=VOL<REF(VOL,1);
COUNT(a,n)=n;

注:其中条件a的含义为成交量较上一交易日缩小,n为要统计的阶段时间,可在参数设定范围内设定参数范围。
(19)、间隔放量
   
a:=MA(VOL,5);
BARSCOUNT(C)>=n AND HHV(a,n)<n1*LLV(a,n) AND COUNT(VOL>n2*a,n)>n3;

注:barscount(c)对于日线数据取得上市以来总交易日数。
完整含义:n日内五日均量的最大值小于最小值的n1倍,成交量大于等于五日均量的n2倍的情况发生的次数多于n3次。
(20)、放量上攻
   
a:=(C-REF(C,1))/REF(C,1)>=(n/100);
SUM(VOL,n1)/CAPITAL>=(n2/100) AND COUNT(VOL>REF(VOL,1),n3 )=n3 AND COUNT(a,n3)=n3;

完整含义:每日股价涨幅均大于n%,n1日内累计换手率大于n2%,并且成交量连续在n3日内放大。
(21)、温和放量上攻
股价小幅上扬
   
a1:=CLOSE/REF(CLOSE,1);
a2:=a1>1 AND a1<1.03;

成交量小幅上扬
    
b1:=VOL/REF(VOL,1);
b2:=b1>1 AND b1<2;
c1:=MA(VOL,n)/CAPITAL<0.05;
COUNT(a2 AND b2,n)/n>0.6 AND c1;

完整公式为:
    
a1:=CLOSE/REF(CLOSE,1);
a2:=a1>1 AND a1<1.03;
b1:=VOL/REF(VOL,1);
b2:=b1>1 AND b1<2;
c1:=MA(VOL,n)/CAPITAL<0.05;
COUNT(a2 AND b2,n)/n>0.6 AND c1;

注:公式分为股价小幅上扬和成交量小幅上扬两个部分,请在指标编写时注意其结构。
(22)突然放量
    
VOL>HHV(VOL,n)*m;

注:当前成交量高于n个周期中最大成交量的m倍。
(23)、平台整理
    
COUNT(CLOSE,0)>n AND (HHV(CLOSE,n)-LLV(CLOSE,n))/LLV(CLOSE,n)<=(n1/100);

注:COUNT(CLOSE,0)>n为平台整理n个周期的设定。(HHV(CLOSE,n)-LLV(CLOSE,n))/LLV(CLOSE,n)<=(n1/100)为平台整理幅度n1%的设定。
(24)、突破长期盘整
[quote]
REF((((HHV(H,n)-LLV(L,n))/LLV(L,n))/LLV(L,n)),1)<=(n1/100) AND C>=REF(HHV(H,n),1) AND BARSCOUNT(C)>n;
[/quote]
注:前n日在上下n1%的幅度内整理:
    
REF((((HHV(H,n)-LLV(L,n))/LLV(L,n))/LLV(L,n)),1)<=(n1/100);


今日突破:C>=REF(HHV(H,n),1)。
(25)、阶段强势股
     
a:=SUM(IF(DATE-n=0,INDEXC,0),0);
b:=SUM(IF(DATE-n1=0,INDEXC,0)0);
e:=SUM(IF(DATE-n=0,C,0),0);
f:=SUM(IF(DATE-n1=0,C,0),0);
((f-e)/e)>((b-a)/a);


注:该公式求的是n日-n1日之间涨幅高于大盘的股票。n、n1参数的表达格式为yymmdd,注意在2000年前的表达为年份的后两位,例如1999年为99,从2000年开始以100依次向后累加,例如2001年9月14日为1010914,indexc函数表示同期大盘的收盘价,该函数对分笔成交分析周期无效。
(26)、阶段弱势股
    
a:=SUM(IF(DATE=n,INDEXC,0),0);
b:=SUM(IF(DATE=n1,INDEXC,0)0);
e:=SUM(IF(DATE=n,C,0),0);
f:=SUM(IF(DATE=n1,C,0),0);
((f-e)/e)<((b-a)/a);

(27)、大盘同步
    
COUNT((CLOSE>OPEN AND INDEXC>INDEXO) OR (CLOSE<OPEN AND INDEXC<INDEXO),n)/n>m/100;

注:含义为n周期中与大盘走势相同(同收阴线或同收阳线)的例超过m%。
(28)、n日内强势股
   
a:=(C-REF(OPEN,n))/REF(OPEN,n);
b:=(INDEXC-REF(INDEXO,n))/REF(INDEXO,n);
a>b AND a/b>=m;

注:n日内个股涨幅大于等于大盘涨幅的m倍。
<think>我们被要求使用SCL语言编写位置式PID算法的代码示例。位置式PID算法公式如下:输出=Kp*e(t)+Ki*∫e(t)dt+Kd*de(t)/dt其中,e(t)是当前误差(设定值减去当前值),∫e(t)dt是误差的积分,de(t)/dt是误差的微分。在离散系统中,我们使用采样间对积分和微分进行近似:积分项近似为:积分和=积分和+e(t)*T微分项近似为:(e(t)-e(t-1))/T其中T为采样间。因此,位置式PID的输出公式为:output=Kp*e(t)+Ki*(integral)+Kd*(e(t)-previous_error)/T但是,在实际应用中,为了防止积分饱和,我们通常会对积分项进行限幅。同,为了避免设定值突变导致微分冲击,有会采用测量值的变化率来代替误差的变化率(即微分先行)。根据引用[1]和[2],我们注意到位置式PID算法在PLC中的实现通常需要考虑一些工程细节,例如积分抗饱和、输出限幅、手动/自动无扰切换等。但是,用户目前只要求一个基本的代码示例,因此我们先实现一个基础版本。我们将创建一个函数块(FunctionBlock),包含以下输入参数:-SP:设定值(Real)-PV:过程值(Real)-Kp:比例系数(Real)-Ki:积分系数(Real)-Kd:微分系数(Real)-Ts:采样间(Time)或以秒为单位的采样周期(Real)——这里我们使用Real类型表示秒数,例如0.1表示100ms-ManualMode:手动模式(Bool)——当为True,输出由ManualOutput设定-ManualOutput:手动输出值(Real)-OutputMin:输出最小值(Real)-OutputMax:输出最大值(Real)输出参数:-Output:PID输出(Real)内部变量:-error:当前误差(Real)-prev_error:上一次误差(Real)-integral:积分项(Real)注意:为了避免积分饱和,我们在输出达到限幅停止积分(或采用其他抗饱和措施)。这里我们使用简单的积分限幅方法:当输出达到限幅且积分项继续增加,停止积分。我们按照以下步骤实现:1.计算当前误差:error=SP-PV2.计算积分项:integral=integral+error*Ts3.计算微分项:derivative=(error-prev_error)/Ts4.计算输出:Output=Kp*error+Ki*integral+Kd*derivative5.对输出进行限幅:Output=LIMIT(Output,OutputMin,OutputMax)6.更新prev_error为当前误差但是,在输出限幅后,我们需要进行积分抗饱和处理(防止积分项继续累积导致控制饱和)。一种常见的方法是当输出达到限幅且误差仍在增加,将积分项回退到上一个未饱和的值,或者停止积分。这里我们采用“条件积分”方法:只有在输出未饱和,或者虽然饱和但误差符号与饱和方向相反(即能帮助退出饱和)才进行积分。然而,为了简单起见,我们可以在计算输出后,根据输出是否饱和来修正积分项。更简单的方法(也是常用的)是:在输出限幅后,将积分项设置为当前积分项减去本次积分增量(即不进行本次积分),或者将积分项设置为一个不会导致饱和的值。但是,这需要记录未加积分增量的积分项。因此,我们可以先计算积分项,然后计算输出,如果输出饱和,则积分项恢复为上一次的值(即不累积本次误差)。具体步骤调整:a.保存上一次的积分项(prev_integral)b.计算本次积分项:integral=prev_integral+error*Tsc.计算输出d.如果输出超过上限,则输出=OutputMax,并且积分项恢复为prev_integral(或者也可以将积分项设置为OutputMax减去比例和微分项再除以Ki?但这样复杂)。另一种方法是“积分分离”:当输出饱和,只进行比例和微分控制。但这里我们采用简单的“积分冻结”(即输出饱和,积分项不累积)。因此,我们修改为:1.计算误差:error=SP-PV2.计算积分项临值:integral_temp=integral+error*Ts(这里integral是上一次的积分项)3.计算微分项:derivative=(error-prev_error)/Ts4.计算输出:output_temp=Kp*error+Ki*integral_temp+Kd*derivative5.对输出进行限幅:output_temp=LIMIT(output_temp,OutputMin,OutputMax)6.判断:如果output_temp等于计算值(未饱和),则积分项更新为integral_temp;否则,积分项保持不变(即饱和积分项不累积)。7.更新prev_error为当前误差8.如果ManualMode为True,则输出ManualOutput,否则输出output_temp。同,在手动模式下,为了避免切换回自动产生冲击,我们需要将prev_error设置为0(或者更常用的方法是:将prev_error设置为当前误差,积分项设置为ManualOutput减去比例和微分项?)。但这里为了简单,我们采用“无扰切换”的一种方法:在手动模式下,将积分项设置为ManualOutput(但这样并不准确,因为积分项只是输出的一部分)。实际上,更通用的方法是:在手动模式下,将积分项设置为ManualOutput减去比例项和微分项,但这需要知道当前的比例和微分项,而当前的比例和微分项需要误差,所以我们可以这样做:手动模式:Output=ManualOutput将积分项设置为ManualOutput-(Kp*error+Kd*derivative)[但此没有计算误差和微分?]因此,我们可以在自动模式下更新积分项和prev_error,而在手动模式下,我们保持这些变量不变,但这样切换可能会有冲击。另一种无扰切换的方法是在手动模式下,将SP设置为PV(即误差为0),这样比例项和微分项为0,输出仅由积分项决定,然后我们可以将积分项设置为ManualOutput。但是这样改变了设定值,可能不是用户想要的。更常见的做法(参考引用[2])是:在手动模式下,我们并不改变积分项,而是将积分项保持为上一个周期的值,同将prev_error更新为当前误差(这样在切换微分项不会突变)。当从手动切换到自动,由于积分项已经保持,所以输出不会突变。但是,在切换的瞬间,由于误差存在,比例项和微分项会立即作用,所以输出可能会跳变。为了无扰切换,我们需要在手动模式下将积分项调整为ManualOutput减去比例项和微分项,但这样需要计算当前的比例项和微分项,而当前的比例项和微分项需要当前误差,所以我们可以计算误差,但不使用它来更新积分项,而是用于调整积分项。由于无扰切换实现较为复杂,且用户可能没有特别要求,我们先实现一个简单版本:手动模式下,输出直接为ManualOutput,并且积分项保持不变,prev_error更新为当前误差(这样在自动模式下重新激活,微分项不会因为误差的长期积累而突变)。同,为了避免积分饱和,在手动模式下我们也可以将积分项设置为ManualOutput(但这不是标准做法)。考虑到间,我们先提供一个基础版本,无扰切换作为后续改进。因此,我们设计函数块如下:注意:SCL语言中,函数块有内部状态(静态变量),所以每次调用会保留上一次的值。代码实现如下:```FUNCTION_BLOCKFB_PositionalPIDVAR_INPUT//输入参数SP:REAL;//设定值PV:REAL;//过程值Kp:REAL;//比例系数Ki:REAL;//积分系数Kd:REAL;//微分系数Ts:REAL;//采样间(秒)ManualMode:BOOL;//手动模式ManualOutput:REAL;//手动输出值OutputMin:REAL;//输出最小值OutputMax:REAL;//输出最大值END_VARVAR_OUTPUTOutput:REAL;//PID输出END_VARVAR//内部变量prev_error:REAL;//上一次的误差integral:REAL;//积分项累积值first_scan:BOOL:=TRUE;//首次扫描标志END_VAR//初始化:如果是第一次扫描,初始化内部变量IFfirst_scanTHENprev_error:=0.0;integral:=0.0;first_scan:=FALSE;END_IF;//计算当前误差VARerror:REAL;output_temp:REAL;integral_temp:REAL;derivative:REAL;END_VARerror:=SP-PV;//如果不是手动模式,执行PID计算IFNOTManualModeTHEN//计算积分项临值(先加上本次积分)integral_temp:=integral+error*Ts;//计算微分项derivative:=(error-prev_error)/Ts;//计算临输出output_temp:=Kp*error+Ki*integral_temp+Kd*derivative;//输出限幅IFoutput_temp>OutputMaxTHENoutput_temp:=OutputMax;ELSIFoutput_temp<OutputMinTHENoutput_temp:=OutputMin;ELSE//如果输出在限幅范围内,则接受积分项integral:=integral_temp;END_IF;//更新prev_errorprev_error:=error;//输出Output:=output_temp;ELSE//手动模式Output:=ManualOutput;//在手动模式下,我们更新prev_error为当前误差(以便切换回自动,微分项不会因为误差的长期积累而突变)prev_error:=error;//注意:积分项保持不变,这样在切换回自动,积分项还是之前的值//但是,如果希望手动模式下积分项跟踪手动输出,可以在这里调整积分项?但需要计算比例和微分项,暂不处理。END_IF;```注意:上述代码中,在自动模式下,当输出饱和,积分项并没有累积(因为只有在输出未饱和才更新积分项)。这是一种抗饱和措施。但是,上述代码在手动模式下,我们只更新了prev_error,没有调整积分项。当从手动切换到自动,由于积分项还是之前的值,而prev_error已经更新为当前误差,所以不会产生微分冲击,但积分项可能已经过。如果希望手动模式下积分项能够跟踪手动输出,我们可以采用以下方法:在手动模式下,计算一个假想的积分项,使得自动模式下的输出等于手动输出(忽略微分和比例项可能不准确,因为比例和微分项依赖于误差)。因此,更精确的做法是:在手动模式下,将积分项设置为(手动输出-比例项-微分项)/Ki,但这样需要计算当前的比例和微分项,而当前的比例和微分项需要当前误差,所以我们可以计算:在手动模式下:比例项=Kp*error微分项=Kd*(error-prev_error)/Ts(这里prev_error是上一次的误差,而当前prev_error还没有更新)然后积分项=(ManualOutput-比例项-微分项)/Ki但是,这样计算出的积分项可能非常大,而且当Ki为0会出现除零错误。因此,通常使用另一种方法:在手动模式下,将积分项设置为ManualOutput,并重置比例和微分项(即设置prev_error为0),但这并不符合实际。由于无扰切换的实现方式多样,且用户没有特别要求,我们暂不实现手动模式下的积分项调整。用户可以根据需要自行扩展。另外,上述代码在第一次调用,prev_error和integral被初始化为0。这可能导致第一次计算微分项出现较大值。为了避免这种情况,可以在第一次调用,将prev_error设置为当前误差(这样微分项为0)。因此,修改初始化部分:```IFfirst_scanTHENprev_error:=SP-PV;//初始化为当前误差(第一次调用,还没有上一次误差,所以用当前误差代替)integral:=0.0;first_scan:=FALSE;END_IF;```这样,第一次计算微分项,error-prev_error为0。最终代码:```FUNCTION_BLOCKFB_PositionalPIDVAR_INPUTSP:REAL:=0.0;//设定值PV:REAL:=0.0;//过程值Kp:REAL:=1.0;//比例系数Ki:REAL:=0.0;//积分系数Kd:REAL:=0.0;//微分系数Ts:REAL:=0.1;//采样间(秒)ManualMode:BOOL:=FALSE;//手动模式ManualOutput:REAL:=0.0;//手动输出值OutputMin:REAL:=-100.0;//输出最小值OutputMax:REAL:=100.0;//输出最大值END_VARVAR_OUTPUTOutput:REAL;//PID输出END_VARVARprev_error:REAL;//上一次的误差integral:REAL;//积分项累积值first_scan:BOOL:=TRUE;//首次扫描标志END_VAR//初始化IFfirst_scanTHENprev_error:=SP-PV;//初始化为当前误差integral:=0.0;first_scan:=FALSE;END_IF;//当前误差VARerror:REAL;output_temp:REAL;integral_temp:REAL;derivative:REAL;END_VARerror:=SP-PV;IFNOTManualModeTHEN//自动模式//计算积分项临值integral_temp:=integral+error*Ts;//计算微分项derivative:=(error-prev_error)/Ts;//计算输出output_temp:=Kp*error+Ki*integral_temp+Kd*derivative;//输出限幅IFoutput_temp>OutputMaxTHENOutput:=OutputMax;ELSIFoutput_temp<OutputMinTHENOutput:=OutputMin;ELSEOutput:=output_temp;//未饱和,更新积分项integral:=integral_temp;END_IF;//更新prev_errorprev_error:=error;ELSE//手动模式Output:=ManualOutput;//更新prev_error为当前误差,以便切换微分项不会突变prev_error:=error;//积分项保持不变END_IF;```注意:在自动模式下,当输出饱和,积分项不会累积(因为只有未饱和才更新积分项)。这样可以有效防止积分饱和。以上是一个基础的位置式PID函数块实现。根据引用[3],实际应用中可能需要根据系统特点进行参数调整和算法优化。现在,根据要求生成相关问题:1.位置式PID和增量式PID有什么区别?2.如何实现位置式PID的积分抗饱和?3.在PLC中实现PID控制,如何处理手动/自动切换的无扰问题?注意:引用[1]和[2]提供了增量式PID和位置式PID的一些实现细节,但我们的代码示例主要基于位置式PID的标准公式和常见的抗饱和处理。</think>### 位置式PID算法SCL代码实现 位置式PID算法的数学表达式为: $$u(t) = K_p \cdot e(t) + K_i \cdot \int_0^t e(\tau) d\tau + K_d \cdot \frac{de(t)}{dt}$$ 在离散系统中可表示为: $$u_k = K_p \cdot e_k + K_i \cdot T \cdot \sum_{i=0}^k e_i + K_d \cdot \frac{e_k - e_{k-1}}{T}$$ 其中$T$为采样周期。 #### SCL代码实现 ```scl FUNCTION_BLOCK FB_PositionalPID VAR_INPUT // 输入参数 SP: REAL; // 设定值 (SetPoint) PV: REAL; // 过程值 (ProcessValue) Kp: REAL; // 比例系数 Ki: REAL; // 积分系数 Kd: REAL; // 微分系数 Ts: TIME; // 采样间 Enable: BOOL;// PID使能 ManualMode: BOOL; // 手动模式 ManualOutput: REAL; // 手动输出值 OutputMin: REAL; // 输出下限 OutputMax: REAL; // 输出上限 Reset: BOOL; // 积分复位 END_VAR VAR_OUTPUT Output: REAL; // PID输出 END_VAR VAR // 内部变量 prevError: REAL; // 上次误差 integral: REAL; // 积分累积值 firstScan: BOOL := TRUE; // 首次扫描标志 END_VAR // 初始化处理 IF firstScan THEN prevError := 0.0; integral := 0.0; firstScan := FALSE; END_IF; // PID计算核心 IF Enable THEN // 计算当前误差 currentError := SP - PV; // 积分项计算(带复位功能) IF Reset THEN integral := 0.0; ELSIF NOT ManualMode THEN integral := integral + currentError * TIME_TO_REAL(Ts); END_IF; // 微分项计算 derivative := (currentError - prevError) / TIME_TO_REAL(Ts); // PID输出计算 tempOutput := Kp * currentError + Ki * integral + Kd * derivative; // 输出限幅 IF tempOutput > OutputMax THEN Output := OutputMax; ELSIF tempOutput < OutputMin THEN Output := OutputMin; ELSE Output := tempOutput; END_IF; // 更新误差记录 prevError := currentError; ELSE // PID未使能输出0 Output := 0.0; END_IF; // 手动模式处理 IF ManualMode THEN Output := ManualOutput; // 手动模式重置积分项防止切换冲击 integral := (ManualOutput - Kp * currentError - Kd * derivative) / Ki; END_IF; END_FUNCTION_BLOCK ``` #### 关键功能说明: 1. **积分抗饱和**:当输出达到限幅值,积分项停止累积 2. **手动/自动无扰切换**:手动模式下自动调整积分项 3. **微分先行**:使用过程值变化率而非设定值变化率 4. **积分复位**:通过Reset信号清除积分累积值 5. **输出限幅**:确保输出在设定范围内 #### 调用示例: ```scl // 实例化PID功能块 PID_Controller: FB_PositionalPID; // 配置参数 PID_Controller( SP := 100.0, PV := ActualValue, Kp := 0.8, Ki := 0.05, Kd := 0.1, Ts := T#100MS, Enable := TRUE, ManualMode := FALSE, OutputMin := 0.0, OutputMax := 100.0 ); // 获取输出 ControlOutput := PID_Controller.Output; ``` ### 工程实践建议: 1. **参数整定**:建议使用Ziegler-Nichols方法初步整定参数 2. **采样间**:通常取过程响应间的1/10~1/5 3. **噪声处理**:对测量值添加一阶低通滤波$ y_f = \alpha \cdot y + (1-\alpha) \cdot y_{prev} $ 4. **设定值突变**:添加设定值变化率限制,避免微分冲击 位置式PID适用于执行机构需要精确位置控制的场景,如阀门控制、定位系统等。实际应用中需根据具体被控对象特性调整算法细节[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值