| 作者 | 主题 |
|---|---|
|
Auto_w 游民 经验值:131 发帖数:88 精华帖:1 |
楼主
主题:用最简单方法完成这道编程题
有7个二通阀,每个阀上有2个DC24V线圈,2个到位信号DC24V。工作原理:一个线圈得电后,阀动作,动作到位后到位信号反馈(DC24V),如线圈得电后3S,到位信号无反馈,则报警。
- -(T1)——/——(Alarm) 如每个这样做,算最笨的做法。。。请考虑。。 |
|
zhangli0 至圣 经验值:48087 发帖数:17127 精华帖:63 |
楼
主题:回复:用最简单方法完成这道编程题
做一个功能块,一个输入res,(反馈),两个输出out,alarm(控制输出和报警),静态变量bool:tag1,tag2,over;real:tag3_sp,tag3其它的我就不写了,只写关键部分。
a out fp tag1 s tag2 a tag2 jcn m1 l 0.5 l tag3 +r t tag3 l tag3_sp >=r s over a out a over an res =alarm an out r tag2 r over 这段程序写在fb块中,在中断中调用,中断周期0.5秒。使用的是中断计时,没有使用系统的计时器。
活到老,学到老!为了生活学习吧!
|
|
老兵veteran 至圣 经验值:59333 发帖数:9984 精华帖:505 |
楼
主题:回复:用最简单方法完成这道编程题
定义Q0.0-Q1.5分别对应14个电磁阀;I0.0-I1.5分别对应14个位置开关;Q2.0-Q3.5分别对应14个报警输出。
ORGANIZATION_BLOCK OB 1 TITLE = "Main Program Sweep (Cycle)" VERSION : 0.1 BEGIN NETWORK TITLE = L QW 0; L IW 0; XOW ; T MW 0; L MW 2; AW ; T QW 2; END_ORGANIZATION_BLOCK ORGANIZATION_BLOCK "CYC_INT5" TITLE = "Cyclic Interrupt" VERSION : 0.1 BEGIN NETWORK TITLE = CALL FC 1 ( sa := M 0.0, alarm := M 2.0, comparor := DB1.DBW 0); CALL FC 1 ( sa := M 0.1, alarm := M 2.1, comparor := DB1.DBW 2); CALL FC 1 ( sa := M 0.2, alarm := M 2.2, comparor := DB1.DBW 4); CALL FC 1 ( sa := M 0.3, alarm := M 2.3, comparor := DB1.DBW 6); CALL FC 1 ( sa := M 0.4, alarm := M 2.4, comparor := DB1.DBW 8); CALL FC 1 ( sa := M 0.5, alarm := M 2.5, comparor := DB1.DBW 10); CALL FC 1 ( sa := M 0.6, alarm := M 2.6, comparor := DB1.DBW 12); CALL FC 1 ( sa := M 0.7, alarm := M 2.7, comparor := DB1.DBW 14); CALL FC 1 ( sa := M 1.0, alarm := M 3.0, comparor := DB1.DBW 16); CALL FC 1 ( sa := M 1.1, alarm := M 3.1, comparor := DB1.DBW 16); CALL FC 1 ( sa := M 1.2, alarm := M 3.2, comparor := DB1.DBW 18); CALL FC 1 ( sa := M 1.3, alarm := M 3.3, comparor := DB1.DBW 20); CALL FC 1 ( sa := M 1.4, alarm := M 3.4, comparor := DB1.DBW 22); CALL FC 1 ( sa := M 1.5, alarm := M 3.5, comparor := DB1.DBW FUNCTION FC 1 : VOID TITLE = VERSION : 0.1 VAR_INPUT sa : BOOL ; END_VAR VAR_OUTPUT alarm : BOOL ; END_VAR VAR_IN_OUT comparor : INT ; END_VAR BEGIN NETWORK TITLE = AN #sa; JC M001; //如果有阀的动作而没有检测开关信号,则开始计时,否则就不报警。 L 1; L #comparor; +I ; T #comparor; L 40; //该数的取值等于4S/定时中断时间,本例为100ms. >=I ; JC M002; JU M003; M001: L 0; T #comparor; CLR = #alarm JU M003; M002: SET ; = #alarm; M003: NOP 0; END_FUNCTION 24); END_ORGANIZATION_BLOCK
天生不宜做胜利者,自来没有胜利的欲望,只是不甘失败,十分十分不甘心失败。木心
|
|
月夜水明楼 侠客 经验值:662 发帖数:402 精华帖:3 |
楼
主题:回复:用最简单方法完成这道编程题
七组阀,每个阀为双线圈,因而最多能同时工作的线圈个数为7个
I0.0-I0.7;I2.0-I2.7为阀的开关,I1.0-I1.7;I3.0-I3.7为返回信号 Q4.0-Q4.7;Q6.0-Q6.7对应十四个线圈 Q5.0-Q5.7;Q7.0-Q7.7对应十四个报警信号 DB1.DBX0.0为报警复归信号 可做如下类似控制(只做了三组,其它相同): //OB1 "Main Program Sweep (Cycle)" A( O I 0.0 O Q 0.0 ) AN I 0.1 = Q 4.0 A( O I 0.1 O Q 0.1 ) AN I 0.0 = Q 4.1 A( O I 0.2 O Q 0.2 ) AN I 0.3 = Q 4.2 A( O I 0.3 O Q 0.3 ) AN I 0.2 = Q 4.3 A( A Q 4.0 AN I 1.0 O A Q 4.1 AN I 1.1 O A Q 4.2 AN I 1.2 O A Q 4.3 AN I 1.3 ) FP M 20.0 S M 10.0 A M 10.0 JNB M001 CALL SFC 32 OB_NR :=20 DTIME :=T#3S SIGN :=MW0 RET_VAL:=MW2 M001: A BR R M 10.0 A DB1.DBX 0.0 FP M 20.2 S M 10.2 A M 10.2 JNB M002 CALL SFC 32 OB_NR :=20 DTIME :=T#1MS SIGN :=MW30 RET_VAL:=MW32 M002: A BR R M 10.2 A( O I 1.0 O I 1.1 O I 1.2 O I 1.3 ) FP M 20.1 S M 10.1 A M 10.1 JNB M003 CALL SFC 33 OB_NR :=20 RET_VAL:=MW4 M003: A BR R M 10.1 CALL SFC 34 OB_NR :=20 RET_VAL:=MW6 STATUS :=MW8 NOP 0 //OB20 "Time Delay Interrupt" SET = Q 5.0 = Q 5.1 = Q 5.2 = Q 5.3 A DB1.DBX 0.0 R Q 5.0 R Q 5.1 R Q 5.2 R Q 5.3 |
|
liwenqun 奇侠 经验值:6852 发帖数:5293 精华帖:25 |
楼
主题:回复:用最简单方法完成这道编程题
采用SFC64 只做了一个阀门的控制的FB 其他的一样就可以了
ORGANIZATION_BLOCK "main" TITLE = "Main Program Sweep (Cycle)" VERSION : 0.1 VAR_TEMP OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1) OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1) OB1_PRIORITY : BYTE ; //Priority of OB Execution OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1) OB1_RESERVED_1 : BYTE ; //Reserved for system OB1_RESERVED_2 : BYTE ; //Reserved for system OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds) OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds) OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds) OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started END_VAR BEGIN NETWORK TITLE = A M 0.0; //开阀给定信号 = L 20.0; BLD 103; A M 0.1; //关阀给定信号 = L 20.1; BLD 103; A I 0.0; //阀门开到位信号 = L 20.2; BLD 103; A I 0.1; //阀门关到位信号 = L 20.3; BLD 103; CALL "FMCtrl" , DB 1 ( Open := L 20.0, Close := L 20.1, OpenLimit := L 20.2, CloseLimit := L 20.3, QOpen := Q 0.0,//开阀 QClose := Q 0.1,//关阀 QOAlarm := Q 0.2,//开阀报警 QCAlarm := Q 0.3);//关阀报警 NOP 0; END_ORGANIZATION_BLOCK FUNCTION_BLOCK "FMCtrl" TITLE ="阀门开关+报警" VERSION : 0.1 VAR_INPUT Open : BOOL ; //开阀信号 Close : BOOL ; //关阀信号 OpenLimit : BOOL ; //阀门开到位信号 CloseLimit : BOOL ; //阀门关到位信号 END_VAR VAR_OUTPUT QOpen : BOOL ; //开阀输出 QClose : BOOL ; //关阀输出 QOAlarm : BOOL ; //开阀超时报警 QCAlarm : BOOL ; //关阀超时报警 END_VAR VAR OP1 : BOOL ; //中间变量1 OP2 : BOOL ; //中间变量2 P_1 : BOOL ; //中间脉冲变量1 P_2 : BOOL ; //中间脉冲变量2 Openretnow : TIME ; //开阀的现在时间 Openretstart : TIME ; //开阀的起始时间 Closeretnow : TIME ; //关阀的现在时间 Closeretstart : TIME ; //关阀的起始时间 END_VAR VAR_TEMP Opentempnow : DINT ; //转换后开阀的现在时间 Opentempstart : DINT ;//转换后开阀的起始时间 Opentempsub : DINT ; //转换后开阀输出的时间 Closetempnow : DINT ; //转换后关阀的现在时间 Closetempstart : DINT ;//转换后关阀的起始时间 Closetempsub : DINT ; //转换后关阀输出的时间 END_VAR BEGIN NETWORK TITLE =Temporary placeholder variable A #Open; AN #OpenLimit; = L 24.0; A L 24.0; = #OP1; A #OP1; = #QOpen; A L 24.0; FP #P_1; JNB _001; CALL "TIME_TCK" ( RET_VAL := #Openretstart); _001: NOP 0; NETWORK TITLE = A #OP1; = L 24.0; A L 24.0; JNB _002; CALL "TIME_TCK" ( RET_VAL := #Openretnow); _002: NOP 0; A L 24.0; JNB _003; L #Openretstart; T #Opentempstart; _003: NOP 0; A L 24.0; JNB _004; L #Openretnow; T #Opentempnow; _004: NOP 0; A L 24.0; JNB _005; L #Opentempnow; L #Opentempstart; -D ; T #Opentempsub; _005: NOP 0; A L 24.0; A( ; L #Opentempsub; L L#3000; >D ; ) ; = #QOAlarm; NETWORK TITLE =Temporary placeholder variable A #Close; AN #CloseLimit; = L 24.0; A L 24.0; = #OP2; A #OP2; = #QClose; A L 24.0; FP #P_2; JNB _006; CALL "TIME_TCK" ( RET_VAL := #Closeretstart); _006: NOP 0; NETWORK TITLE = A #OP2; = L 24.0; A L 24.0; JNB _007; CALL "TIME_TCK" ( RET_VAL := #Closeretnow); _007: NOP 0; A L 24.0; JNB _008; L #Closeretstart; T #Closetempstart; _008: NOP 0; A L 24.0; JNB _009; L #Closeretnow; T #Closetempnow; _009: NOP 0; A L 24.0; JNB _00a; L #Closetempnow; L #Closetempstart; -D ; T #Closetempsub; _00a: NOP 0; A L 24.0; A( ; L #Closetempsub; L L#3000; >D ; ) ; = #QCAlarm; END_FUNCTION_BLOCK
怎么论坛改成这样了??
|
|
老兵veteran 至圣 经验值:59333 发帖数:9984 精华帖:505 |
楼
主题:回复:用最简单方法完成这道编程题
以上程序在网吧中编制,没有经过调试,可能也有语法错误,见谅,就算抛砖引玉吧.
这段程序没用SFB/SFC/T/C,也没用中断,是读OB1的扫描时间并条件累加/清零的,而且不存在溢出问题.
天生不宜做胜利者,自来没有胜利的欲望,只是不甘失败,十分十分不甘心失败。木心
|
|
伊默 至圣 经验值:19234 发帖数:4258 精华帖:118 |
楼
主题:回复:用最简单方法完成这道编程题![]() 在OB1的局部变量中有一个"OB1_PREV_CYCLE"变量,就是用来记录上一扫描周期的时间, 拿这个变量不停的累加,就能粗略知道累积时间,这样就可以不用定时中断OB35,也不用SFB,也不用系统块内定义的定时脉冲,即可得到累积时间值了.
I can do it
|
|
scmyzq 游士 经验值:170 发帖数:122 精华帖:1 |
楼
主题:回复:用最简单方法完成这道编程题
煤造气好象也就要用出题老兄说的那种阀。
我做过类似的东西,约500个程控阀,只不过是每程控阀是1DO电磁阀加1DI阀检测,也是DO开或关时超过3~12s报警。 最早是用了“一个SFB4”的。后面看了大家的发言后觉得可以这样 用SCL写FB。 1、申明STA类型变量A:DINT、B:BOOL。将A:=A+OB1_PREV_CYCLE; 2、关键在于A的清零 IF DO <> B THEN(即A XOR B为真时,说明A有跳变) A:=0; B:=DO; END_IF; 3:IF(A>3000~12000)THEN IF DO AND NOT DI THEN 开报警; END_IF; IF NOT DO AND DI THEN 关报警; END_IF; END_IF; 其实就是用SFB4的多重背景也大不了多少。 |
|
Auto_w 游民 经验值:131 发帖数:88 精华帖:1 |
楼
主题:回复:用最简单方法完成这道编程题
很高兴看到这么多朋友在一起交流。其实这道题是我做工程中用的,我用的方法是利用中断做的:OB35(中断时间改为1000MS)调用做的FC。
这样可以节省资源和避免重复错用定时器和记数器(个人意见)。 这么多高手提供的方法,真叫人叫好,要努力学习啊,呵呵 |
|
游荡 侠客 经验值:828 发帖数:163 精华帖:7 |
楼
主题:回复:用最简单方法完成这道编程题
先写FB1:
VAR_INPUT Driver : BOOL ; FeedBack : BOOL ; nowPast : INT ; END_VAR VAR_OUTPUT Alarm : BOOL ; END_VAR VAR myTime : INT ; END_VAR BEGIN NETWORK TITLE = A #Driver; AN #FeedBack; A( ; L #myTime; L 3100; <=I ; ) ; JNB _001; L #myTime; L #nowPast; +I ; T #myTime; _001: A( ; ON #Driver; O #FeedBack; ) ; JNB _002; L 0; T #myTime; _002: L #myTime; L 3000; >=I ; = #Alarm; END_FUNCTION_BLOCK 然后在OB1中调用: CALL FB 1 , "Val1" Driver := ///驱动信号 FeedBack:= //反馈 nowPast :=#OB1_PREV_CYCLE /// Alarm := ///警告输出
SIEAUTO
|