N年之前,用S7-300做一个小型DCS项目,选用wincc为人机界面。项目中电机、泵、风机类比较多,于是下功夫研究编写这个电机块。功能确实强大,在wincc中自动生成图标,拽出来直接用就可。
FUNCTION_BLOCK MOTOR1DIR_300
NAME:MOTOR1DIR
FAMILY:S7-300 BLOCK
AUTHOR:SDZYG2000
//VERSION:'1.01'
//FB620
// Typical-Attribute
{
S7_tasklist:='OB100';
S7_m_c:='true';
S7_blockview:='big'
}
// Parameterattribute
// S7_visible visible/unvisible (default='true')
// S7_m_c WinCC - Tag (default='false')
// S7_dynamic testmode (default='false')
VAR_INPUT
LOCK {S7_dynamic:='true'} : BOOL := FALSE; // Interlock
ERR_EXTERN {S7_dynamic:='true'} : BOOL := FALSE; // External Error
LIOP_SEL {S7_dynamic:='true'} : BOOL := FALSE; // 0=Operator 1=Linking
L_AUT {S7_dynamic:='true'} : BOOL := FALSE; // 0=Manual 1=Automatic
L_REMOTE {S7_dynamic:='true'} : BOOL := FALSE; // 0=Lokal 1=Remote
L_SIM {S7_dynamic:='true'} : BOOL := FALSE; // 0=Normal 1=Simulation
L_RESET {S7_dynamic:='true'} : BOOL := FALSE; // 1=Reset Error Peripherie
AUT_ON {S7_dynamic:='true'} : BOOL := FALSE; // 1=CMD ON Automatic
MAN_ON {S7_dynamic:='true'} : BOOL := FALSE; // 1=CMD ON Manual
SIM_ON {S7_dynamic:='true'} : BOOL := FALSE; // 1=CMD ON Simulation
FB_ON {S7_dynamic:='true'} : BOOL := FALSE; // Feedback Motor
L_MON {S7_dynamic:='true'} : BOOL := TRUE; // 1=Monitoring ON
MON_T {S7_dynamic:='true'; S7_m_c := 'true'} : REAL := 10.0; // Monitoring Time
MPS {S7_dynamic:='true'} : BOOL := FALSE; // 1=Motor Protecting Switch ON
L_FLOW_MON {S7_dynamic:='true'} : BOOL := FALSE; // 1=Monitoring Flow
FLOW {S7_dynamic:='true'} : REAL := 0.0; // Current Flow
FLOW_LL {S7_dynamic:='true'} : REAL := 5.0; // Low Level Flow
FLOW_MT {S7_dynamic:='true'; S7_m_c := 'true'} : REAL := 10.0; // Monitoring Time Flow
SAMPLE_T {S7_sampletime:='true'} : REAL := 0.0; // Sample Time
END_VAR
VAR_IN_OUT
OP_dwCmd {S7_dynamic := 'true'; S7_m_c := 'true'} : DWORD :=0; // control word wincc
END_VAR
VAR_OUTPUT
QdwState {S7_dynamic:='true'; S7_m_c:='true'}: DWORD:=0; // status wincc
QabyState AT QdwState : ARRAY [0..3] OF BYTE; // look at state byte-wise
QwState {S7_dynamic:='true'}: WORD:= 0; //0=off, 1=starting, 2=on, 3=stopping
QSTOPPING {S7_dynamic:='true'} : BOOL := FALSE; // 1=Stopping
QSTOP {S7_dynamic:='true'} : BOOL := FALSE; // 1=Stop
QSTARTING {S7_dynamic:='true'} : BOOL := FALSE; // 1=Starting
QRUN {S7_dynamic:='true'} : BOOL := FALSE; // 1=Run
QCMD_ON {S7_dynamic:='true'} : BOOL := FALSE; // 0=Stop 1=Start
QMON {S7_dynamic:='true'} : BOOL := FALSE; // 1=Monitoring Feedback
QMON_ERR {S7_dynamic:='true'} : BOOL := FALSE; // 1=Monitoring Error
QMON_T {S7_dynamic:='true'; S7_m_c := 'true'} : REAL := 0.0; // Current Monitoring Time Feedback
QFLOW_MON {S7_dynamic:='true'} : BOOL := FALSE; // 1=Monitoring Flow
QFLOW_MT {S7_dynamic:='true'; S7_m_c := 'true'} : REAL := 0.0; // Current Monitoring Time Flow
QFLOW_ERR {S7_dynamic:='true'} : BOOL := FALSE; // 1=Error Flow
QMPS {S7_dynamic:='true'} : BOOL := FALSE; // 1=Motor Protecting Switch
QERR {S7_dynamic:='true'} : BOOL := FALSE; // 1=ERROR
QMAN_AUT {S7_dynamic:='true'} : BOOL := FALSE; // 0=Hand 1=Automatic
QREMOTE {S7_dynamic:='true'} : BOOL := FALSE; // 0=Local 1=Remote
QSIM {S7_dynamic:='true'} : BOOL := FALSE; // Simulaition is active
QLOCK {S7_dynamic:='true'} : BOOL := FALSE; // Interlock is active
QERR_EXT {S7_dynamic:='true'} : BOOL := FALSE; // External ERROR
//Alarm
QwAlarm {S7_dynamic:='true'; S7_m_c := 'true'} : WORD := 16#0; // Bit Alarm Procedure
QabyAlarm AT QwAlarm : ARRAY [0..1] OF BYTE; // look at QwAlarm byte-wise
END_VAR
VAR
OPdwCmdHMI : DWORD := 16#0; // Operator Commands in HMI format
OPabyCmdHMI AT OPdwCmdHMI : ARRAY [0..3] OF BYTE; // look at HMI command byte-wise
OPdwCmdPLC : DWORD := 16#0; // Operator Commands in PLC format
OPabyCmdPLC AT OPdwCmdPLC : ARRAY [0..3] OF BYTE; // look at plc command byte-wise
OPabCmdPLC AT OPdwCmdPLC : ARRAY [0..31] OF BOOL; // look at plc command bit-wise
QdwStatePLC : DWORD := 16#0; // State word in PLC format
QabyStatePLC AT QdwStatePLC : ARRAY [0..3] OF BYTE; // look at state byte-wise
QabStatePLC AT QdwStatePLC : ARRAY [0..31] OF BOOL; // look at state bit-wise
QwAlarmPLC : WORD := 16#0; // Alarm Tag PLC Format
QabyAlarmPLC AT QwAlarmPLC : ARRAY [0..1] OF BYTE; // look at Alarm byte-wise
QabAlarmPLC AT QwAlarmPLC : ARRAY [0..15] OF BOOL; // look at Alarm bit-wise
// TAGS for Simulation
FB_SIM : BOOL := FALSE;
SIM_T : REAL := 5.0;
QCMD_SIM : BOOL := FALSE;
// TAGS for Operation
OP_RESET : BOOL := FALSE;
// TAGS for Edge detect
L_RESET_OLD : BOOL := FALSE;
AUT_ON_OLD : BOOL := FALSE;
MAN_ON_OLD : BOOL := FALSE;
QSTARTING_OLD : BOOL := FALSE;
QSTOPPING_OLD : BOOL := FALSE;
END_VAR
VAR_TEMP
TOP_SI: STRUCT
EV_CLASS : BYTE;
EV_NUM : BYTE;
PRIORITY : BYTE;
NUM : BYTE;
TYP2_3 : BYTE;
TYP1 : BYTE;
ZI1 : WORD;
ZI2_3 : DWORD;
END_STRUCT;
START_UP_SI: STRUCT
EV_CLASS : BYTE;
EV_NUM : BYTE;
PRIORITY : BYTE;
NUM : BYTE;
TYP2_3 : BYTE;
TYP1 : BYTE;
ZI1 : WORD;
ZI2_3 : DWORD;
END_STRUCT;
iRet : INT;
END_VAR
BEGIN
// START UP =====================================================================
iRet := SFC6 (TOP_SI:= TOP_SI, START_UP_SI:= START_UP_SI);
IF (TOP_SI.NUM = 100) THEN
QCMD_ON := FALSE;
QSTOP := TRUE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := FALSE;
QwState := 0;
iRet := 0;
END_IF;
// END STARTUP ==================================================================
// Change lowbyte to highbyte for HMI command word =====================
OPdwCmdHMI := OP_dwCmd;
OPabyCmdPLC[0] := OPabyCmdHMI[3];
OPabyCmdPLC[1] := OPabyCmdHMI[2];
OPabyCmdPLC[2] := OPabyCmdHMI[1];
OPabyCmdPLC[3] := OPabyCmdHMI[0];
// ******************************************************************************
// Begin: Operation functions ***************************************************
// MANUAL / AUTOMATIC Operation =======================================
IF (LIOP_SEL AND NOT L_AUT) OR (OPabCmdPLC[16] AND NOT LIOP_SEL) THEN
QMAN_AUT := FALSE;
ELSIF (LIOP_SEL AND L_AUT) OR (OPabCmdPLC[17] AND NOT LIOP_SEL) THEN
QMAN_AUT := TRUE;
END_IF;
// LOCAL / REMOTE Operation =========================================
IF (LIOP_SEL AND NOT L_REMOTE) OR (OPabCmdPLC[18] AND NOT LIOP_SEL) THEN
QREMOTE := FALSE;
ELSIF (LIOP_SEL AND L_REMOTE) OR (OPabCmdPLC[19] AND NOT LIOP_SEL) THEN
QREMOTE := TRUE;
END_IF;
// SIMULATION ON / OFF ==============================================
IF (LIOP_SEL AND NOT L_SIM) OR (OPabCmdPLC[20] AND NOT LIOP_SEL) THEN
QSIM := FALSE;
ELSIF (LIOP_SEL AND L_SIM) OR (OPabCmdPLC[21] AND NOT LIOP_SEL) THEN
QSIM := TRUE;
QCMD_ON := FALSE;
END_IF;
// RESET Operation ==================================================
IF (LIOP_SEL AND L_RESET AND NOT L_RESET_OLD) OR (OPabCmdPLC[24] AND NOT LIOP_SEL) THEN
OP_RESET := TRUE;
ELSE
OP_RESET := FALSE;
END_IF;
// MONITORING FEEDBACK ON / OFF =====================================
IF (LIOP_SEL AND L_MON) OR (OPabCmdPLC[8] AND NOT LIOP_SEL) THEN
QMON := TRUE;
ELSIF (LIOP_SEL AND NOT L_MON) OR (OPabCmdPLC[9] AND NOT LIOP_SEL) THEN
QMON := FALSE;
END_IF;
// MONITORING FLOW ON / OFF =========================================
IF (LIOP_SEL AND L_FLOW_MON) OR (OPabCmdPLC[10] AND NOT LIOP_SEL) THEN
QFLOW_MON := TRUE;
ELSIF (LIOP_SEL AND NOT L_FLOW_MON) OR (OPabCmdPLC[11] AND NOT LIOP_SEL) THEN
QFLOW_MON := FALSE;
END_IF;
// START / STOP Motor (AUTOMATIC)====================================
IF (QMAN_AUT AND AUT_ON AND NOT AUT_ON_OLD AND NOT QSIM) THEN
QCMD_ON := TRUE;
ELSIF (QMAN_AUT AND NOT AUT_ON AND NOT QSIM) THEN
QCMD_ON := FALSE;
END_IF;
// START / STOP Motor (MANUAL)=======================================
IF (NOT QMAN_AUT AND NOT QREMOTE AND MAN_ON AND NOT MAN_ON_OLD AND NOT QSIM) OR (OPabCmdPLC[1] AND NOT QMAN_AUT AND QREMOTE AND NOT QSIM) THEN
QCMD_ON := TRUE;
ELSIF (NOT QMAN_AUT AND NOT QREMOTE AND NOT MAN_ON AND NOT QSIM) OR (OPabCmdPLC[0] AND NOT QMAN_AUT AND QREMOTE AND NOT QSIM) THEN
QCMD_ON := FALSE;
END_IF;
// START / STOP Motor (SIMULATION)===================================
IF (QSIM AND NOT QREMOTE AND SIM_ON) OR (OPabCmdPLC[1] AND QREMOTE AND QSIM) THEN
QCMD_SIM := TRUE;
ELSIF (QSIM AND NOT QREMOTE AND NOT SIM_ON) OR (OPabCmdPLC[0] AND QREMOTE AND QSIM) THEN
QCMD_SIM := FALSE;
END_IF;
// END: Operation functions *****************************************************
// ******************************************************************************
//=================================
// QwState
//0 = Stop
//1 = Starting
//2 = Run
//3 = Stopping
//=================================
//--------------------------
//QwState = 0; Stop
//--------------------------
IF NOT QSIM THEN // *** Process Mode ***
IF
(NOT QCMD_ON AND QwState=3 AND NOT QMON_ERR AND NOT FB_ON) OR
(NOT QCMD_ON AND QwState=3 AND NOT QMON)
THEN
QSTOP := TRUE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := FALSE;
QwState := 0;
END_IF;
ELSE // *** Simulation Mode ***
IF
(NOT QCMD_SIM AND QwState=3 AND NOT FB_SIM) OR
(NOT QCMD_SIM AND QwState=3 AND NOT QMON)
THEN
QSTOP := TRUE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := FALSE;
QwState := 0;
END_IF;
END_IF;
//--------------------------
//QwState = 1; Starting
//--------------------------
IF NOT QSIM THEN // *** Process Mode ***
IF (QCMD_ON AND QwState = 0) THEN
QSTOP := FALSE;
QSTARTING := TRUE;
QRUN := FALSE;
QSTOPPING := FALSE;
QwState := 1;
END_IF;
ELSE // *** Simulation Mode ***
IF (QCMD_SIM AND QwState = 0) THEN
QSTOP := FALSE;
QSTARTING := TRUE;
QRUN := FALSE;
QSTOPPING := FALSE;
QwState := 1;
END_IF;
END_IF;
//--------------------------
//QwState = 2; RUN
//--------------------------
IF NOT QSIM THEN // *** Process Mode ***
IF
(QCMD_ON AND QwState=1 AND NOT QMON_ERR AND FB_ON) OR
(QCMD_ON AND QwState=1 AND NOT QMON)
THEN
QSTOP := FALSE;
QSTARTING := FALSE;
QRUN := TRUE;
QSTOPPING := FALSE;
QwState := 2;
END_IF;
ELSE // *** Simulation Mode ***
IF
(QCMD_SIM AND QwState=1 AND FB_SIM) OR
(QCMD_SIM AND QwState=1 AND NOT QMON)
THEN
QSTOP := FALSE;
QSTARTING := FALSE;
QRUN := TRUE;
QSTOPPING := FALSE;
QwState := 2;
END_IF;
END_IF;
//--------------------------
//QwState = 3; Stopping
//--------------------------
IF NOT QSIM THEN // *** Process Mode ***
IF (NOT QCMD_ON AND (QwState = 1 OR QwState = 2)) THEN
QSTOP := FALSE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := TRUE;
QwState := 3;
END_IF;
ELSE // *** Simulation Mode ***
IF (NOT QCMD_SIM AND (QwState = 1 OR QwState = 2)) THEN
QSTOP := FALSE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := TRUE;
QwState := 3;
END_IF;
END_IF;
// Feedback Monitoring =================================================
IF QMON THEN
IF (QSTARTING AND NOT QSTARTING_OLD) OR (QSTOPPING AND NOT QSTOPPING_OLD) THEN
QMON_T := 0.0;
END_IF;
IF NOT QSIM THEN // *** Process Mode ****
IF (QSTARTING OR QSTOPPING) THEN
QMON_T := QMON_T + SAMPLE_T;
IF (QMON_T >= MON_T) THEN
QMON_ERR := TRUE;
END_IF;
ELSE
QMON_T := 0.0;
END_IF;
IF (QRUN AND NOT FB_ON) OR (QSTOP AND FB_ON) THEN
QMON_ERR := TRUE;
END_IF;
ELSE // *** Simulation Mode ***
IF (QSTARTING) THEN
QMON_T := QMON_T + SAMPLE_T;
IF (QMON_T >= SIM_T) THEN
FB_SIM := TRUE;
END_IF;
ELSIF (QSTOPPING) THEN
QMON_T := QMON_T + SAMPLE_T;
IF (QMON_T >= SIM_T) THEN
FB_SIM := FALSE;
END_IF;
ELSE
QMON_T := 0.0;
END_IF;
END_IF;
END_IF;
// END Monitoring ======================================================
// Check Errors ========================================================
QERR_EXT := ERR_EXTERN;
IF LOCK AND (QSTARTING OR QRUN) THEN
QLOCK := TRUE;
END_IF;
IF MPS THEN
QMPS := TRUE;
END_IF;
QERR := QERR_EXT OR QMON_ERR OR QFLOW_ERR OR QLOCK OR QMPS;
// RESET Errors ========================================================
IF OP_RESET THEN
QMON_ERR := FALSE;
QFLOW_ERR := FALSE;
QMPS := FALSE;
QLOCK := FALSE;
END_IF;
// If Error then Stop ==================================================
IF QERR THEN
QSTOP := TRUE;
QSTARTING := FALSE;
QRUN := FALSE;
QSTOPPING := FALSE;
QCMD_ON := FALSE;
QCMD_SIM := FALSE;
QwState := 0;
QMON_T := 0.0;
END_IF;
// Set State for HMI ===================================================
QabStatePLC[0] := QSTOP; // 1=Stop
QabStatePLC[1] := QSTARTING; // 1=Starting
QabStatePLC[2] := QRUN; // 1=Run
QabStatePLC[3] := QSTOPPING; // 1=Stopping
QabStatePLC[4] := 0;
QabStatePLC[5] := 0;
QabStatePLC[6] := 0;
QabStatePLC[7] := 0;
QabStatePLC[8] := QMON; // 1=Feedback Monitoring ON
QabStatePLC[9] := QMON_ERR; // 1=Error Feedback Monitoring
QabStatePLC[10] := QFLOW_MON; // 1=Flow Monitoring ON
QabStatePLC[11] := QFLOW_ERR; // 1=Error Flow Monitoring
QabStatePLC[12] := QMPS; // 1=Motor Protecting Switch
QabStatePLC[13] := 0;
QabStatePLC[14] := 0;
QabStatePLC[15] := 0;
QabStatePLC[16] := QMAN_AUT; // 0=Manual 1=Automatic
QabStatePLC[17] := QREMOTE; // 0=Local 1=Remote
QabStatePLC[18] := QSIM; // 0=Process 1=Simulation
QabStatePLC[19] := 0;
QabStatePLC[20] := 0;
QabStatePLC[21] := 0;
QabStatePLC[22] := 0;
QabStatePLC[23] := 0;
QabStatePLC[24] := QERR; // 1=Error
QabStatePLC[25] := QERR_EXT; // 1=External Error
QabStatePLC[26] := QLOCK; // 1=Motor Locked;
QabStatePLC[27] := LOCK; // 1=INTERLOCK
QabStatePLC[28] := 0;
QabStatePLC[29] := 0;
QabStatePLC[30] := 0;
QabStatePLC[31] := 0;
QabyState[0] :=QabyStatePLC[3];
QabyState[1] :=QabyStatePLC[2];
QabyState[2] :=QabyStatePLC[1];
QabyState[3] :=QabyStatePLC[0];
// Bit alarm procedure ================================================
QabAlarmPLC[0] :=QMON_ERR; // Feedback Error
QabAlarmPLC[1] :=QFLOW_ERR; // Flowing Error
QabAlarmPLC[2] :=QMPS; // Motor Protect
QabAlarmPLC[3] :=0;
QabAlarmPLC[4] :=QLOCK; // Interlock Error
QabAlarmPLC[5] :=0;
QabAlarmPLC[6] :=QERR_EXT; // External Error
QabAlarmPLC[7] :=QERR; // General Error
QabAlarmPLC[8] :=QSTOP; // Stop
QabAlarmPLC[9] :=QSTARTING; // Starting
QabAlarmPLC[10] :=QRUN; // Run
QabAlarmPLC[11] :=QSTOPPING; // Stopping
QabAlarmPLC[12] :=LOCK; // Interlock
QabAlarmPLC[13] :=QREMOTE; // Remote
QabAlarmPLC[14] :=QMAN_AUT; // Automatic
QabAlarmPLC[15] :=QSIM; // Simulation
QabyAlarm[0] := QabyAlarmPLC[1];
QabyAlarm[1] := QabyAlarmPLC[0];
// Set Tags for edge detect =====================================
L_RESET_OLD := L_RESET;
AUT_ON_OLD := AUT_ON;
MAN_ON_OLD := MAN_ON;
QSTARTING_OLD:= QSTARTING;
QSTOPPING_OLD:= QSTOPPING;
//reset commands ================================================
OP_dwCmd := 16#0;
END_FUNCTION_BLOCK