西门子CONT_C(FB41)PID指令的SCL源码 点击:206 | 回复:4



散去的人潮

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 10回
  • 年度积分:1005
  • 历史总积分:1045
  • 注册:2019年1月07日
发表于:2020-05-20 21:34:57
楼主

西门子CONT_C PID指令 (FB41)功能块的SCL源码

以下是原版:

下面这个是我优化过后的版本:增加了联锁输出,增加了反作用开关,增加了手动/自动无扰动切换等。

下面是SCL源码:

03.png





幸福的小石头

  • 精华:0帖
  • 求助:0帖
  • 帖子:0帖 | 315回
  • 年度积分:909
  • 历史总积分:945
  • 注册:2015年5月27日
发表于:2020-05-21 08:15:50
1楼

楼主想表达什么呢?

yuanle

  • 精华:0帖
  • 求助:0帖
  • 帖子:11帖 | 9860回
  • 年度积分:0
  • 历史总积分:40836
  • 注册:2005年4月22日
发表于:2020-05-21 08:53:36
2楼


引用 幸福的小石头 的回复内容: 楼主想表达什么呢?

-------------------------

想表达的内容是他的程序和10多年前俄罗斯人发布的程序是何等相似,连临时变量名也相同的。


俄文版FB41,各位可以抄抄然后在博图中稍微修改一下就可以了。

FUNCTION_BLOCK FB41
TITLE ="Непрерывный PID регулятор"
AUTHOR : SIMATIC
FAMILY : ICONT
NAME : CONT_C
VERSION : " 1.5"
//reversed by komatic
VAR_INPUT
  COM_RST               : BOOL ;                    //;            //Ручной режим включить
  PVPER_ON              : BOOL ;                    //Чтение входной переменной с периферии включить
  P_SEL                 : BOOL   TRUE;            //Пропорциональную составляющую включить
  I_SEL                 : BOOL   TRUE;            //Интегральную составляющую включить
  INT_HOLD              : BOOL ;                    //Удержание интегральной составляющей
  I_ITL_ON              : BOOL ;                    //Инициализировать интегральную составляющую
  D_SEL                 : BOOL ;                    
  CYCLE                 : TIME   T#1S;            //Время выполнения блока
  SP_INT                : REAL ;                    //Внутреннее задание
  PV_IN                 : REAL ;                    //Входная переменная
  PV_PER                : WORD ;                    //Входная переменная (периферия)
  MAN                   : REAL ;                    //Ручной выход
  GAIN                  : REAL   2.000000e+000;   //Коэффициент пропорциональности
  TI                    : TIME   T#20S;           //Время интегрирования
  TD                    : TIME   T#10S;           //Время дифференцирования
  TM_LAG                : TIME   T#2S;            //Время действия дифференциальной составляющей
  DEADB_W               : REAL ;                    //Ширина зоны нечувствительности
  LMN_HLM               : REAL   1.000000e+002;   //Верхний предел выходного сигнала
  LMN_LLM               : REAL ;                    //Нижний предел выходного сигнала
  PV_FAC                : REAL   1.000000e+000;   //Коэффициент для корректировки входной переменной (умножение)
  PV_OFF                : REAL ;                    //Коэффициент для корректировки входной переменной (сложение)
  LMN_FAC               : REAL   1.000000e+000;   //Коэффициент для корректировки выходной переменной (умножение)
  LMN_OFF               : REAL ;                    //Коэффициент для корректировки входной переменной (сложение)
  I_ITLVAL              : REAL ;                    //Начальное значение интегральной составляющей
  DISV                  : REAL ;                    //Возмущающая переменная
END_VAR
VAR_OUTPUT
  LMN                   : REAL ;                    //Выходное значение
  LMN_PER               : WORD ;                    //Выходное значение (переферия)
  QLMN_HLM              : BOOL ;                    //Верхний предел выхода достигнут
  QLMN_LLM              : BOOL ;                    //Нижний предел выхода достигнут
  LMN_P                 : REAL ;                    //Пропорциональная составляющая
  LMN_I                 : REAL ;                    //Интегральная составляющая
  LMN_D                 : REAL ;                    //Дифференциальная составляющая
  PV                    : REAL ;                    //Входная переменная
  ER                    : REAL ;                    //Сигнал рассогласования
END_VAR
VAR
  sInvAlt               : REAL ;   
  sIanteilAlt           : REAL ;   
  sRestInt              : REAL ;   
  sRestDif              : REAL ;   
  sRueck                : REAL ;   
  sLmn                  : REAL ;   
  sbArwHLmOn            : BOOL ;                    //Выход достиг максимального значения 
  sbArwLLmOn            : BOOL ;                    //Выход достиг минимального значения
  sbILimOn              : BOOL  := ;   
END_VAR
VAR_TEMP
  Hvar                  : REAL ;                    //Hilfsvariable
  rCycle                : REAL ;                    //Abtastzeit in real
  Diff                  : REAL ;                    //0.0;                                       //Выходное значение
    QLMN_HLM:=0;                                    //Верхний предел выхода достигнут
    QLMN_LLM:=0;                                    //Нижний предел выхода достигнут
    LMN_P:=0.0;                                     //Пропорциональная составляющая
    LMN_I:=0.0;                                     //Интегральная составляющая
    LMN_D:=0.0;                                     //Дифференциальная составляющая
    LMN_PER:=0;        //Выходное значение (периферия)
    PV:=0.0;                                        //Входная переменная
    ER:=0.0;                                        //Сигнал рассогласования
    sInvAlt0.0;
    sRestInt:=;
    sRestDif:=;
    sRueck:=;
    sLmn:=;
    sbArwHLmOn:=;
    sbArwLLmOn:=;
ELSE
    rCycle:= (TIME_TO_DINT(CYCLE)) / 1000.0;            //Время выполненияINT_TO_REAL(
    IF NOT PVPER_ON THEN IstwertPV_IN; END_IF;                    // Если периферийный вход отключен берем переменную из PV_IN
    PV:= Istwert;                                                   
    ErKp:=SP_INT - PV;                                              // Получили рассогласование между заданием и входом
    IF     ErKp < (-DEADB_W)     THEN ER:=ErKp+DEADB_W;             // Если рассогласование больше зоны нечувствительности
    ELSIF  ErKp >   DEADB_W      THEN ERErKp-DEADB_W;             // уменьшаем рассогласование на величину зоны нечуств.
    ELSE                              ER0.0;                      // иначе принимаем рассогласование равным нулю.
    END_IF;
    ErKp:=ER * GAIN;                                                // Рассогласование, умноженное на кфт пропорциональности
    rTiDINT_TO_REAL((TIME_TO_DINT(TD)) / 1000.0;                   // Время дифференцирования(TIME_TO_DINT(TM_LAG)) / 1000.0;            // Время действия 0.5)         rTi:=rCycle * 0.5;      END_IF//  rCycle             THEN    rTd:=rCycle;            //  rCycle * 
    THEN
        IF I_ITL_ON             
        THEN
            Ianteil:=I_ITLVAL;
            sRestInt:=;
        ELSE
            IF MAN_ON           //;
            ELSE                //Автоматический sInvAlt) *  AND sbArwLLmOn) THEN Diff;       
                Ianteil:=sIanteilAlt + Diff;
                sRestInt:=sIanteilAlt - Ianteil + Diff;
            END_IF;
        END_IF;
    ELSE
        Ianteil:=;
        sRestInt:=;
    END_IF;
    //---------------------------------------------------------------------------------------------
    //Формирование дифференциальной составляющей
    //---------------------------------------------------------------------------------------------   
    Diff:=ErKp;
    IF ( MAN_ON) AND D_SEL
    THEN
        Verstaerk:= rTd  (rCycle *  sRueck) * Verstaerk;
        RueckAlt:= sRueck;
        RueckDiff:= rCycle  rTd * Danteil  RueckAlt;
        sRestDif:=RueckAlt  sRueck + RueckDiff;
    ELSE
        Danteil:=;   
        sRestDif:=;
        sRueck:=Diff;
    END_IF;
    //---------------------------------------------------------------------------------------------
    // Ianteil + Danteil + DISV;
    IF MAN_ON           // Если ручной режим
    THEN
        dLmn:=MAN;      Ручной  I_ITL_ON) AND I_SEL
        THEN
            IF (Ianteil > (LMN_HLM - DISV)) AND (dLmn  LMN_HLM) AND ((dLmn - LMN_D)> LMN_HLM)
            THEN
                rVal:=LMN_HLM - DISV;
                gf:=  dLmn  LMN_HLM;
                rVal:=Ianteil - rVal;
                IF  rVal > gf THEN rVal:=gf; END_IF;
                Ianteil:=Ianteil - rVal;
            ELSE
                IF (Ianteil < (LMN_LLM - DISV)) AND (dLmn  LMN_LLM) AND ((dLmn - LMN_D) < LMN_LLM)
                THEN
                    rVal:=LMN_LLM - DISV;
                    gf:=dLmn - LMN_LLM;
                    rVal:=Ianteil - rVal;
                    IF rVal < gf  THEN rVal:=gf; END_IF;
                    Ianteil:=Ianteil - rVal;
                END_IF;   
             END_IF;      
        END_IF;
    END_IF;
    LMN_P:=Panteil;
    LMN_I:=Ianteil;
    LMN_D:=Danteil;
    sInvAlt:=ErKp;
    sIanteilAlt:=Ianteil;
    sbArwHLmOn:=;
    sbArwLLmOn:=;
    IF (dLmn  LMN_HLM)
    THEN
        QLMN_HLM:=;
        QLMN_LLM:=;
        dLmn:=LMN_HLM;
        sbArwHLmOn:=;
    ELSE
        QLMN_HLM:=;
        IF (dLmn  LMN_LLM)
        THEN
            QLMN_LLM:=;
            dLmn:=LMN_LLM;
            sbArwLLmOn:=;
        ELSE
            QLMN_LLM:=
        END_IF;
    END_IF;
    sLmn:=dLmn;
    dLmn:=sLmn  LMN_FAC + LMN_OFF;  
    LMN:=dLmn;
    dLmn:=LMN  2.764800e+002;
    IF dLmn  3.251100e+004
    THEN
        dLmn:=;
    ELSE
        IF dLmn  -;
        END_IF;
    END_IF;
    LMN_PER:= (REAL_TO_INT(dLmn));
END_IF;   
END_FUNCTION_BLOCK



HAVE  FUN!

幸福的小石头

  • 精华:0帖
  • 求助:0帖
  • 帖子:0帖 | 315回
  • 年度积分:909
  • 历史总积分:945
  • 注册:2015年5月27日
发表于:2020-05-21 10:26:15
3楼


回复内容:

对: yuanle 引用 幸福的小石头 的回复内容: 楼主想表达什么呢?-... 内容的回复!

-------------------------

哈哈哈,伙计,你这有点砸摊子了

那谁

  • 精华:0帖
  • 求助:0帖
  • 帖子:1帖 | 14回
  • 年度积分:11
  • 历史总积分:31
  • 注册:2016年6月30日
发表于:2021-01-11 20:59:15
4楼

回复内容:

对:yuanle 引用 幸福的小石头 的回复内容: 楼主想表达什么呢?-------------------------想表达的内容是他的程序和10多年前俄罗斯人发布的程序是何等相似,连临时变量名也相同的。俄文版FB41,各位可以抄抄然后在博图中稍微修改一下就可以了。FUNCTION_BLOCK FB41TITLE ="Непрерывный PID регулятор"AUTHOR : SIMATICFAMILY : ICONTNAME : CONT_CVERSION : " 1.5"//reversed by komaticVAR_INPUT  COM_RST               : BOOL ;                    //;            //Ручной режим включить  PVPER_ON              : BOOL ;                    //Чтение входной переменной с периферии включить  P_SEL                 : BOOL   TRUE;            //Пропорциональную составляющую включить  I_SEL                 : BOOL   TRUE;            //Интегральную составляющую включить  INT_HOLD              : BOOL ;                    //Удержание интегральной составляющей  I_ITL_ON              : BOOL ;                    //Инициализировать интегральную составляющую  D_SEL                 : BOOL ;                      CYCLE                 : TIME   T#1S;            //Время выполнения блока  SP_INT                : REAL ;                    //Внутреннее задание  PV_IN                 : REAL ;                    //Входная переменная  PV_PER                : WORD ;                    //Входная переменная (периферия)  MAN                   : REAL ;                    //Ручной выход  GAIN                  : REAL   2.000000e+000;   //Коэффициент пропорциональности  TI                    : TIME   T#20S;           //Время интегрирования  TD                    : TIME   T#10S;           //Время дифференцирования  TM_LAG                : TIME   T#2S;            //Время действия дифференциальной составляющей  DEADB_W               : REAL ;                    //Ширина зоны нечувствительности  LMN_HLM               : REAL   1.000000e+002;   //Верхний предел выходного сигнала  LMN_LLM               : REAL ;                    //Нижний предел выходного сигнала  PV_FAC                : REAL   1.000000e+000;   //Коэффициент для корректировки входной переменной (умножение)  PV_OFF                : REAL ;                    //Коэффициент для корректировки входной переменной (сложение)  LMN_FAC               : REAL   1.000000e+000;   //Коэффициент для корректировки выходной переменной (умножение)  LMN_OFF               : REAL ;                    //Коэффициент для корректировки входной переменной (сложение)  I_ITLVAL              : REAL ;                    //Начальное значение интегральной составляющей  DISV                  : REAL ;                    //Возмущающая переменнаяEND_VARVAR_OUTPUT  LMN                   : REAL ;                    //Выходное значение  LMN_PER               : WORD ;                    //Выходное значение (переферия)  QLMN_HLM              : BOOL ;                    //Верхний предел выхода достигнут  QLMN_LLM              : BOOL ;                    //Нижний предел выхода достигнут  LMN_P                 : REAL ;                    //Пропорциональная составляющая  LMN_I                 : REAL ;                    //Интегральная составляющая  LMN_D                 : REAL ;                    //Дифференциальная составляющая  PV                    : REAL ;                    //Входная переменная  ER                    : REAL ;                    //Сигнал рассогласованияEND_VARVAR  sInvAlt               : REAL ;     sIanteilAlt           : REAL ;     sRestInt              : REAL ;     sRestDif              : REAL ;     sRueck                : REAL ;     sLmn                  : REAL ;     sbArwHLmOn            : BOOL ;                    //Выход достиг максимального значения   sbArwLLmOn            : BOOL ;                    //Выход достиг минимального значения  sbILimOn              : BOOL  := ;   END_VARVAR_TEMP  Hvar                  : REAL ;                    //Hilfsvariable  rCycle                : REAL ;                    //Abtastzeit in real  Diff                  : REAL ;                    //0.0;                                       //Выходное значение    QLMN_HLM:=0;                                    //Верхний предел выхода достигнут    QLMN_LLM:=0;                                    //Нижний предел выхода достигнут    LMN_P:=0.0;                                     //Пропорциональная составляющая    LMN_I:=0.0;                                     //Интегральная составляющая    LMN_D:=0.0;                                     //Дифференциальная составляющая    LMN_PER:=0;        //Выходное значение (периферия)    PV:=0.0;                                        //Входная переменная    ER:=0.0;                                        //Сигнал рассогласования    sInvAlt0.0;    sRestInt:=;    sRestDif:=;    sRueck:=;    sLmn:=;    sbArwHLmOn:=;    sbArwLLmOn:=;ELSE    rCycle:= (TIME_TO_DINT(CYCLE)) / 1000.0;            //Время выполненияINT_TO_REAL(    IF NOT PVPER_ON THEN IstwertPV_IN; END_IF;                    // Если периферийный вход отключен берем переменную из PV_IN    PV:= Istwert;                                                       ErKp:=SP_INT - PV;                                              // Получили рассогласование между заданием и входом    IF     ErKp < (-DEADB_W)     THEN ER:=ErKp+DEADB_W;             // Если рассогласование больше зоны нечувствительности    ELSIF  ErKp >   DEADB_W      THEN ERErKp-DEADB_W;             // уменьшаем рассогласование на величину зоны нечуств.    ELSE                              ER0.0;                      // иначе принимаем рассогласование равным нулю.    END_IF;    ErKp:=ER * GAIN;                                                // Рассогласование, умноженное на кфт пропорциональности    rTiDINT_TO_REAL((TIME_TO_DINT(TD)) / 1000.0;                   // Время дифференцирования(TIME_TO_DINT(TM_LAG)) / 1000.0;            // Время действия 0.5)         rTi:=rCycle * 0.5;      END_IF; //  rCycle             THEN    rTd:=rCycle;            ; //  rCycle *     THEN        IF I_ITL_ON                     THEN            Ianteil:=I_ITLVAL;            sRestInt:=;        ELSE            IF MAN_ON           //;            ELSE                //Автоматический sInvAlt) *  ) AND sbArwLLmOn) THEN Diff;                       Ianteil:=sIanteilAlt + Diff;                sRestInt:=sIanteilAlt - Ianteil + Diff;            END_IF;        END_IF;    ELSE        Ianteil:=;        sRestInt:=;    END_IF;    //---------------------------------------------------------------------------------------------    //Формирование дифференциальной составляющей    //---------------------------------------------------------------------------------------------       Diff:=ErKp;    IF ( MAN_ON) AND D_SEL    THEN        Verstaerk:= rTd  (rCycle *  sRueck) * Verstaerk;        RueckAlt:= sRueck;        RueckDiff:= rCycle  rTd * Danteil  RueckAlt;        sRestDif:=RueckAlt  sRueck + RueckDiff;    ELSE        Danteil:=;           sRestDif:=;        sRueck:=Diff;    END_IF;    //---------------------------------------------------------------------------------------------    // Ianteil + Danteil + DISV;    IF MAN_ON           // Если ручной режим    THEN        dLmn:=MAN;      Ручной  I_ITL_ON) AND I_SEL        THEN            IF (Ianteil > (LMN_HLM - DISV)) AND (dLmn  LMN_HLM) AND ((dLmn - LMN_D)> LMN_HLM)            THEN                rVal:=LMN_HLM - DISV;                gf:=  dLmn  LMN_HLM;                rVal:=Ianteil - rVal;                IF  rVal > gf THEN rVal:=gf; END_IF;                Ianteil:=Ianteil - rVal;            ELSE                IF (Ianteil < (LMN_LLM - DISV)) AND (dLmn  LMN_LLM) AND ((dLmn - LMN_D) < LMN_LLM)                THEN                    rVal:=LMN_LLM - DISV;                    gf:=dLmn - LMN_LLM;                    rVal:=Ianteil - rVal;                    IF rVal < gf  THEN rVal:=gf; END_IF;                    Ianteil:=Ianteil - rVal;                END_IF;                END_IF;              END_IF;    END_IF;    LMN_P:=Panteil;    LMN_I:=Ianteil;    LMN_D:=Danteil;    sInvAlt:=ErKp;    sIanteilAlt:=Ianteil;    sbArwHLmOn:=;    sbArwLLmOn:=;    IF (dLmn  LMN_HLM)    THEN        QLMN_HLM:=;        QLMN_LLM:=;        dLmn:=LMN_HLM;        sbArwHLmOn:=;    ELSE        QLMN_HLM:=;        IF (dLmn  LMN_LLM)        THEN            QLMN_LLM:=;            dLmn:=LMN_LLM;            sbArwLLmOn:=;        ELSE            QLMN_LLM:=;         END_IF;    END_IF;    sLmn:=dLmn;    dLmn:=sLmn  LMN_FAC + LMN_OFF;      LMN:=dLmn;    dLmn:=LMN  2.764800e+002;    IF dLmn  3.251100e+004    THEN        dLmn:=;    ELSE        IF dLmn  -;        END_IF;    END_IF;    LMN_PER:= (REAL_TO_INT(dLmn));END_IF;   END_FUNCTION_BLOCKHAVE  FUN!     内容的回复:

请问您有FB58 scl的源码吗?可以分享一下吗


相关主题

官方公众号

智造工程师