我是专业做物流程序控制的,在我看来,目前国内很少有人把这个问题解决好,如果这个问题能够解决得好且很规范,我认为此人年薪在15万左右.楼主如果有意做好此事可以联系我,我这里可以提供完善的控制方案和标准程序.但是技术出让价格不会便宜的偶.欢迎大家拍砖!!!!!如果有合作意向可以联系我,我的邮箱是ritch_wang@sina.com
呵呵,楼上的, 按LZ的要求, 没必要用多个高速计数器吧,这样占用的资源也太多了吧!
想问一下楼主!
你曾提到一个问题:
还有。有的汽车的车窗升降开关。当短暂 点按 的时候,一直运动到极限,运动过程中按任意上或者下都可以立即停。稍长时间按的话是点动。这样可以用两个开关控制正反停。
这样的问题做成库,你给多少报酬!
我用S7-200软件 做了一个库文件,在仿真软件上测试过了!发你邮箱里了, 你可以在硬件上测试一下,不过是加密库文件,看不到程序!
我特别说明一下! 我用了两个定时器,T99,T100! 你调用的话,先添加库, 你的工程中最好不要再用了,以免冲突! 这两个计时器号了!
ORGANIZATION_BLOCK 主程序:OB1
TITLE=程序为临时从全局变量改为使用局部变量的,没及细检,可能有错误。
//
// 怎么做成库,我还不太会。不知怎么处理全局变量。
BEGIN
Network 1 // 网络标题
// 定义高速计数器与中断,
LD SM0.1
CALL SBR0
Network 2
// DIANYAN1、DIANYAN2、DIANYAN3分别为3个虚拟电眼的位置,电眼1为靠近入口的。该位置可在人机设定,达到移动电眼的目的。
//
// PIANCHA为检测区域的偏差,也就是检测区域为"该点到该点+上偏差"之间的距离。物体的位移长度在这个区域里时虚拟电眼有输出。
//
// XIANSHU为线数。ZHIJIN为直径。JIEJIN为入口入接近开关输入点。
//
// N为虚拟电眼数量,
//
// I0.0已定义为高速计数器的输入口,不得再用。
//
// 全局变量使用了V4800--V4898,不得再用。
//
// 中断时基为200ms,如果皮带线速过快或偏差值设定太小,可能会逃过设定的检测区域。这时要减小中断时基,或加大偏差。当偏差设定和物体的宽度一样时,虚拟电眼输出脉宽应和实际电眼一样了。
LD SM0.0
CALL SBR1, VW0, VW2, VW4, VW6, VW8, VW10, I0.1, 3, Q0.0, Q0.1, Q0.2
END_ORGANIZATION_BLOCK
SUBROUTINE_BLOCK 初始化:SBR0
TITLE=子程序注释
BEGIN
Network 1
// 定义高速计数器
LD SM0.0
MOVB 16#FC, SMB37
MOVD 0, SMD38
MOVD 999999, SMD42
HDEF 0, 0
HSC 0
Network 2
// 定义200毫秒定时中断
LD SM0.0
MOVB 200, SMB34
ATCH INT0, 10
ENI
END_SUBROUTINE_BLOCK
SUBROUTINE_BLOCK SBR_1:SBR1
TITLE=子程序注释
VAR_INPUT
DIANYAN1:WORD; // 虚拟电眼位置1,在人机上设定,为毫米
DIANYAN2:WORD; // 虚拟电眼位置2
DIANYAN3:WORD; // 虚拟电眼位置3
PIANCHA:WORD; // 每个位置检测的偏差区域
XIANSHU:WORD; // 编码器线数
ZHIJIN:WORD; // 被动轮直径
JIEJIN:BOOL; // 输入口电眼
N:BYTE; // 虚拟电眼数量1-3
END_VAR
VAR_OUTPUT
OUT1:BOOL; // 虚拟电眼输出1,
OUT2:BOOL; // 虚拟电眼输出2
OUT3:BOOL; // 虚拟电眼输出3
END_VAR
BEGIN
Network 1
// 首次扫描
LD SM0.1
S L14.6, 1
Network 2
LD L14.6
O L15.7
= L14.7
Network 3 // 网络标题
// 接近开关输入。为入口处的电眼。"8"为最大进入物体数。
LD L12.0
EU
SHRB L14.7, L15.0, 8
R L14.6, 1
Network 4
// 最多进入8个物体,V4898.0-----V4898.7分别对应这8个物体
LD L15.0
EU
S V4898.0, 1
Network 5
LD L15.1
EU
S V4898.1, 1
Network 6
LD L15.2
EU
S V4898.2, 1
Network 7
LD L15.3
EU
S V4898.3, 1
Network 8
LD L15.4
EU
S V4898.4, 1
Network 9
LD L15.5
EU
S V4898.5, 1
Network 10
LD L15.6
EU
S V4898.6, 1
Network 11
LD L15.7
EU
S V4898.7, 1
Network 12
// 计算每点的上偏差。第一点为靠近入口点,第三点为最后。
// 也就是检测区域为"该点到该点+上偏差"之间的距离。物体的位移长度在这个区域里时有输出。
LD SM0.0
MOVW LW0, LW20
+I LW6, LW20
MOVW LW2, LW22
+I LW6, LW22
MOVW LW4, LW24
+I LW6, LW24
Network 13
// 编码器线数与被动轮直径,并转换成实数
LD SM0.0
MOVW LW8, VW4800
MOVW LW10, VW4802
ITD VW4800, VD4804
DTR VD4804, VD4808
ITD VW4802, VD4812
DTR VD4812, VD4816
Network 14
// 第一个输出
LDW>= VW4850, LW0
AW<= VW4850, LW20
LDW>= VW4852, LW0
AW<= VW4852, LW20
OLD
LDW>= VW4854, LW0
AW<= VW4854, LW20
OLD
LDW>= VW4856, LW0
AW<= VW4856, LW20
OLD
LDW>= VW4858, LW0
AW<= VW4858, LW20
OLD
LDW>= VW4860, LW0
AW<= VW4860, LW20
OLD
LDW>= VW4862, LW0
AW<= VW4862, LW20
OLD
LDW>= VW4864, LW0
AW<= VW4864, LW20
OLD
= L26.0
Network 15
// 第二个输出
LDW>= VW4850, LW2
AW<= VW4850, LW22
LDW>= VW4852, LW2
AW<= VW4852, LW22
OLD
LDW>= VW4854, LW2
AW<= VW4854, LW22
OLD
LDW>= VW4856, LW2
AW<= VW4856, LW22
OLD
LDW>= VW4858, LW2
AW<= VW4858, LW22
OLD
LDW>= VW4860, LW2
AW<= VW4860, LW22
OLD
LDW>= VW4862, LW2
AW<= VW4862, LW22
OLD
LDW>= VW4864, LW2
AW<= VW4864, LW22
OLD
= L26.1
Network 16
// 第三个输出
LDW>= VW4850, LW4
AW<= VW4850, LW24
LDW>= VW4852, LW4
AW<= VW4852, LW24
OLD
LDW>= VW4854, LW4
AW<= VW4854, LW24
OLD
LDW>= VW4856, LW4
AW<= VW4856, LW24
OLD
LDW>= VW4858, LW4
AW<= VW4858, LW24
OLD
LDW>= VW4860, LW4
AW<= VW4860, LW24
OLD
LDW>= VW4862, LW4
AW<= VW4862, LW24
OLD
LDW>= VW4864, LW4
AW<= VW4864, LW24
OLD
= L26.2
Network 17
// 物体移出时,也就是大于第三个点的上限时将长度清零,以便下一个再用
LDW> VW4850, LW24
MOVW 0, VW4850
R V4898.0, 1
Network 18
// 移到最后点输出时将长度清零
LDW> VW4852, LW24
MOVW 0, VW4852
R V4898.1, 1
Network 19
// 移到最后点输出时将长度清零
LDW> VW4854, LW24
MOVW 0, VW4854
R V4898.2, 1
Network 20
// 移到最后点输出时将长度清零
LDW> VW4856, LW24
MOVW 0, VW4856
R V4898.3, 1
Network 21
// 移到最后点输出时将长度清零
LDW> VW4858, LW24
MOVW 0, VW4858
R V4898.4, 1
Network 22
// 移到最后点输出时将长度清零
LDW> VW4860, LW24
MOVW 0, VW4860
R V4898.5, 1
Network 23
// 移到最后点输出时将长度清零
LDW> VW4862, LW24
MOVW 0, VW4862
R V4898.6, 1
Network 24
// 移到最后点输出时将长度清零
LDW> VW4864, LW24
MOVW 0, VW4864
R V4898.7, 1
Network 25
// 最后实际输出,第一点,最靠近入口的,不论电眼数量设定为多少,或是非法的数据,第一点总是有输出的。
LD L26.0
= L14.0
Network 26
// 虚拟电眼数量为1时将第二个输出屏蔽
LDB= LB13, 2
OB= LB13, 3
A L26.1
= L14.1
Network 27
// 虚拟电眼数量为1、2时将第三个输出屏蔽
LDB= LB13, 3
A L26.2
= L14.2
END_SUBROUTINE_BLOCK
INTERRUPT_BLOCK INT_0:INT0
TITLE=中断程序注释
BEGIN
Network 1 // 网络标题
// vd4828里得到单位时间内编码器的转动圈数。
// vw4844里为单位时间内皮带移动的毫米数。
LD SM0.0
MOVD HC0, VD4820
DTR VD4820, VD4824
MOVR VD4824, VD4828
/R VD4808, VD4828
MOVR VD4816, VD4832
*R 3.14, VD4832
MOVR VD4828, VD4836
*R VD4832, VD4836
ROUND VD4836, VD4840
DTI VD4840, VW4844
Network 2
// 计数器清零
LD SM0.0
MOVD 0, SMD38
HSC 0
Network 3
// 第一个物体移动距离
LD V4898.0
+I VW4844, VW4850
Network 4
// 第二个物体移动距离
LD V4898.1
+I VW4844, VW4852
Network 5
// 第三个物体移动距离
LD V4898.2
+I VW4844, VW4854
Network 6
// 第四个物体移动距离
LD V4898.3
+I VW4844, VW4856
Network 7
// 第五个物体移动距离
LD V4898.4
+I VW4844, VW4858
Network 8
// 第六个物体移动距离
LD V4898.5
+I VW4844, VW4860
Network 9
// 第七个物体移动距离
LD V4898.6
+I VW4844, VW4862
Network 10
// 第八个物体移动距离
LD V4898.7
+I VW4844, VW4864
END_INTERRUPT_BLOCK
引用芳季 的回复内容:
还有.上上上上面的程序,你使用了T99T100那如果我的控制要求有两个(含)以上这样的控制对象.那么你的程序自己会跟自己冲突吗?
编译不会报错, 但我摘自MicroWin32 4.0Sp6 软件 帮助上的一段话说明这个问题:
// 如果子程序仅引用参数和局部内存,则可移动子程序。为了移动子程序,应避免使用任
// 何全局变量/符号(I、Q、M、SM、AI、AQ、V、T、C、S、AC
// 内存中的绝对地址)。如果子程序无调用参数(IN、OUT或IN_OUT)或仅在L内存中使用
// 局部变量,您就可以导出子程序并将其导入另一个项目。
上面的文字基本上回答了你得问题, 即 用了公用的 T 变量,所以一个工程中只能调用一次子程序! 否则运行结果不确定!
这也是S7-200系列子程序的 缺点,OMRON 的PLC功能块中设置了timer 变量,即可以定义定时器变量! 这样很方便!
二位。此言差矣。我不是说编译出错。(我当然知道重复使用定时器不会产生编译错误啦)
引用我自己的<那如果我的控制要求有两个(含)以上这样的控制对象.>
这样的话子程序我一定要调用多次。看来这个库程序不适合啊。
楼上上的 MI 现在的 224 V2.0以上版本已经有1毫秒是时钟指令位长32位。子程序内的定时器可以用这个指令代替。使用时就可以避免库中使用到全局(T)区。而且1毫秒的时基是后台硬件发生的。功能可以延展很广。有可能在子程序到中断里或者两个中断之间都可以读取这个计时仪传递时差信息。
我看以后库中要使用到定时性质的东西的话,无疑都要使用这个新功能了。
嘿。嘿。发现致命错误。
MI 你给我的那个程序,我发现一个重大错误。
我看局部变量表。发现只有IN和OUT。并没有IN/OUT量。这个是绝对不可能的。程序中有必须记忆的过程量,你没有用IN/OUT参数引出来进行保存。显然不合付逻辑的。因为局部变量退出程序后是不保留的。这个书上说的是这样,但是我认为没有那么简单。
实际上你的程序光做实验又是完美的。什么功能都达到了。那么为什么说我刚才说要记忆过程量呢?现在不明明是程序可以了吗?
没错。我认为没有这么简单。(我又重复说一遍了)。
你的程序一定违反了一条使用局部变量的重要原则:
先辅值,再使用。
无意中利用“局部变量退出程序后是不保留的。”里面的一个漏洞。(其实这句话是错的)完成了保存的工作。所以程序得以记忆当前过程量。
我想到了这一点。马上看“交叉引用”。果然。有太多的触点出现在线圈之前了。虽然子程序有密码保密。交叉引用中不显示具体的先后顺序。但是,我凭经验看他的格式,可以得知并肯定这一点。
然后我在主程序中紧跟你后面再加一子程序。来验证我的观点。
SBR0
LD SM0.0
FILL 0 30 LW0
RET
果然。你的程序彻底失效了。