作者 | 主题 |
---|---|
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
楼主 2022-11-04 08:11:20
主题:Modbus设备FB接口设计背后的理念 类似下图这样的,以前在多个帖子中曾展示过,今天来聊一下接口背后的设计思考。 这张图片描述的案例场景是:5个同一品牌温控器连接到一个CB1241的485端口上。 Port485:这个参数不需多说,任何与本地485口编程有关的都会用到。对于本帖案例它指的是一个CB1241模块。
MBCommLoad和MBMaster:我是一直把通信当作IO来看待的。普通常见的IO都是单一、固定和孤立的。通信则是I和O的组合,而且I和O之间存在异步、跨扫描周期的行为关联。究其本质,通信就是因协议而关联到一起的IO复合体。 通信和普通IO区别就在于:普通IO上是不存在双向交互协议的。普通IO都是单向信息。 通信= I + O + 协议 协议是工控和IT的灵魂。一个程序员是否可以自己搭建通信协议,是个分水岭。 所以对通信的IO操作,与普通IO不同,实际上是对协议执行指令的操作,而非直接操作底层硬件。所以对于本帖案例中温控器而言的IO,就是MBCommLoad和MBMaster这两个指令。
对于本帖案例而言,Port485、MBCommLoad和MBMaster,三者共同构成了直接走PLC本体485模块的modbus底层IO资源。
换言之,对于其它物理通道方式的Modbus通信,IO资源组合是不一样的。 下图是走UDP的Modbus通信的IO资源 下图是走TCP的Modbus通信的IO资源 这些协议操作的基础指令,都需要数据块实例。随便拖拽生成一个即可。
有的时候官方的基础指令未必够用或好使,可以自己另做。比如MB_Master_PtP和ModbusUDP (Master only),这两个我在其它帖子中提供过SCL源码供大家下载。 本例中的5个温控器的各自IO资源参数设定完全一样。 都是连在一个物理端口上,也都使用同一对MBCommLoad和MBMaster实例。既然是唯一公共IO资源,就没必要给每个温控器单独预备和独占。 也就是说,如果你有多个与PLC本体直连的485串口模块,就需要给每个端口,预备一对MBCommLoad和MBMaster实例,供连接在该端口的所有设备竞争和轮流使用。
注意:本帖案例中,因为用的是PLC本体上的串口模块,所以使用的是低版本的官方Modbus指令,指令执行速度会更快一点。如果是分布式应用,需要用高版本的。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
2楼 2022-11-04 08:52:39
主题:回复:Modbus设备FB接口设计背后的理念 品牌通信任务表
我拿到一个工厂品牌的温控器之后,会仔细看厂家提供的Modbus通信手册,并根据手册中的地址信息,列出一个通信任务清单。 这个列表清单是个任务全集。它包含未来我可能,在任何工作模式下,对这个温控器进行任何操作,所需的读写任务配置的全部信息。 本帖案例中的这个管脚参数,是个UDT类型的数组。这个数组包含了很多单个任务。每个modbus任务,是读是写,开始地址,读写长度,都在UDT中做了数值预设。每个任务有自己的数据区。
为什么要采用这样一个参数形式呢?因为任何modbus设备,不管是变频器或者现场的任何仪表,他们在应用上都要由程序员形成并面对这样一个通信任务表。
设备FB的界面功能解析为底层IO操作,或者底层IO信息还原为FB的界面功能,都要根据这个任务表中的具体任务配置来实施。包括FB内部的工艺关联,都要联系到这个任务表。
所以把这样一个具有共性的通信任务清单,单独封装起来,便于日后的调整和扩展。
比如,一开始某个任务不被需要,或忘记了,后期添加即可。
或者遇到另一种modbus设备,复制一下,把任务队列的内容改一下就可以了。 总之,这个参数就是定义了具体的IO空间范围。 Modbus协议是个标准化的基准空间。在这个基准空间中,由程序员规划出的一个具体特定的小空间范围的描述,就对应了一个现实中落地的功能集合,也就是正在被你使用的,这个具体设备的功能愿景。 这世上无尽的Modbus设备,每一个设备都对应了属于自己的一个独特的小空间。所有这些小空间,合并在一起,形成的大空间,它的基本共性就叫Modbus协议。 每一个具体的,被特征数值填写了的品牌通信任务表,就是一个独特的个例对象。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
3楼 2022-11-04 09:26:22
主题:回复:Modbus设备FB接口设计背后的理念 设备对象
这也是个UDT类型数据。 一个设备FB的功能,是从它的界面到底层IO,和从底层IO到它的界面,两者之间的双向数据流动。 外部与这个设备FB之间的功能交互,都是在它的界面上进行。也就是说,界面上需要某种数据形式来承载和集中,该设备与外界的功能交互。 设备对象,就是内外功能交互的封装体。 本帖案例中,这个设备对象是个温控器。如果是其它设备,需要定义不同的UDT类型。 这个对象中,所有的设备操作,所有的设备功能状态,包括对Modbus通信本身的管控,和Modbus通信的实时监控数据,都包含其中。 对于不同的modbus设备,它们的功能和状态信息都是各不相同。但是它们的Modbus通信执行的控制,和Modbus通信的实时状态信息反馈,完全可以采用相同的结构。也就是,这一部分,应该单独定义为UDT,加入到设备对象UDT之中,成为设备对象的通信子集。 本帖案例图片中,可以看到管脚上连接的设备对象,是个数组形式。这也是这5个温控器的所有管脚参数中,唯一不同之处,就是不同的数组元素。 是不是必须采用数组呢?不一定。这里的PLC程序不需要它必须是数组元素。只是因为采用了西门子触摸屏,为了便于使用多路复用,连接到HMI上的设备面板,而采用了数组。 总之,这个管脚就是交互载体。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
5楼 2022-11-04 10:45:48
主题:回复:Modbus设备FB接口设计背后的理念 PortArray
这也是个以数组为主体的UDT类型的管脚参数,但这个名称起的不好。准确说,它是连接到一条modus通路的所有设备FB实例之间的公共数据展示和交互区。是个全局数据。
这和人类在社会生活实践中的经验和道理是一样的。
一个公共的工具或者叫资源,如果被众多人使用,一定会存在竞争与协调的问题。
事情总有先来后到,也总有轻重缓急。这就像行车的红绿灯,讲究先来后到,可是警车与救护车也可以优先通行。
这样的协同工作,需要知道:当前这个工具,都有哪些人想要参与使用而正在排队?目前正在被谁使用?当前使用者的使用状态?占用是否结束了?是否有人提出了要优先使用,需要加塞儿?等等。
这样的信息在本质上是属于公共信息,而非私有。
也就是:因为自己要参与竞争使用公共资源,这是要获得一种权利。那么相应的,自己就要承担义务,也就是对外公开自己的使用信息。同时自己还要公平对待自己和别人的需求。 这也是通信作为公共IO资源,与普通IO的不同之处。普通IO都是固定独占的,没有竞争。
这是权利和义务之间的对等公平原则,也是法制的基础。这是每个人对其他人负责的方式。公平需要公示为基础。
那么这些公开信息,应该由谁来掌控呢?有两种方式。
1、如果公共资源的管理和分配是由某个管理者来掌控,那么这些信息就应该由这个管理者掌握,而每个参与竞争者并不知道。管理者之所以能合理调配资源,也是基于它掌握了这些公共信息。
2、如果每个参与的竞争者,都是能按照公平规则执行办事的主体,那么道理上讲,这些人不需要管理者,他们完全可以作为独立的自由主体,彼此按照规则协调。这种情况下,这些公开信息,就是应该由所有参与者都公平知晓。也就是行为规则体系和公共过程信息,都是公开透明的。
我采用的是这第二种策略:公示公开透明,自主协调。 落到程序中,就是所说的各个Modbus设备实例之间的平行调用。它们没有上级管理者,就是拖拽几个并行实例,连接好公共参数即可。 把这个公共数据区,连接到所有参与该端口竞争的设备实例的PortArray管脚。这样彼此间就可以共享信息和通知了。 而且因为是全局数据,它们可以被显示在HMI界面上,给现场做参考。
这个UDT内部包含了以下信息:每一个参与的设备实例,都有属于自己的一个记录区。因为有多个竞争者存在,所以这是个记录区的数组。每个记录区之内,显示了该设备的从站号、波特率、是否允许在线,是否被临时淘汰出通信等。 这个UDT还包含了:当前正在使用者的数组下标;提出需要优先使用的设备的数组下标。 这样的公共数据区,每个公共通信的IO通路,都需要且只需要一个。不管它是PLC直连的485串口,或者以太网的TCP管道,或是以太网的UDP连接。 因为这些物理方式的不同,只是底层IO,也就是通信指令,也就是前述的IO资源,它们内部解决的问题。并不影响顶层的设备之间,在功能层面的,调度机制。 上述这些表明了,每个设备内部都需要封装公共的行为规则。当然不排除,因为工艺的使用差别,每个设备对自己的规则做出调整。 不管当前的资源由谁在使用,使用者都会随时按照规则来判定,这个IO资源在当下是应该由自己使用,还是转让给下一个排队的或者需要优先使用的人。 这就是使用公共IO的代价。时刻不能忘记自己的义务,实时需要考虑别人的情况。 每一个参与者的情况都是在随时变动的。有可能随时就不符合使用条件失去资格了,或者它虽获得使用机会但是随时有可能自己就状态不佳了。 资源总是要高效运转,避免无效占据浪费。 总之,通过上面的叙述可以看出:这个公共数据区的存在,仅仅是因为多个设备要竞争性使用一个公共IO资源。多主体竞争,就需要通知和公示,就这么简单。 如果没有竞争关系,都是独占IO使用,那么本例中的FB就会退化为和普通任何种类的设备FB的结构设计,没有任何区别。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
6楼 2022-11-04 11:09:19
主题:回复:Modbus设备FB接口设计背后的理念 为什么没有把从站号作为FB接口参数?
从站号的作用,仅仅是用来填充到Modbus报文的第一个字节中,为了在线路上找到物理设备。与设备轮询的次序,没有任何必然的关系。 不是说1号站之后才是2号站,这样固化的次序。 前面讲过,设备对象是设备功能的交互载体,它里面包含了Modbus通信的控制功能。 设备的从站号,是设备对象的属性之一,当然应该包含在对象之内来设定。 我采用的就是:从触摸屏设备界面上,由操作人员根据设备在现场的设定情况,来随时输入或更改从站号和波特率。 整个Modbus程序架构中,只有每个设备实例的设备对象,可以被用在UI或其它控制边界上。 所以,关于每个设备的控制和交互,都是通过设备对象进行的。这和其它任何种类设备FB的交互边界设计是一致的。 通道公共数据公示区(PortArray)中的信息,都是从设备对象中,实时动态更新过来的。 因此,公共区的数据不需要任何的初始默认值设定,不需要掉电保存。完全是看每个设备对象的动态设置。公共数据交互区只是起到不同设备间的通知作用。 如果没有任何设备对象的参数被设置过,只是初次使用的默认0值状态,那么任何设备实例都只是空转而不会进行通信。模块灯不会闪动。 如果设备对象的参数设置是错误的,该设备实例会被踢出轮询,界面报警,可以重试或强制召回。 总之就是:设备对象中的通信参数(从站号和波特率),设置对了一个,就上线一个,不设或不对就不上。动态随时根据用户的设定变化。 这就为随时通过界面,在现场根据工艺,来更改增减modbus设备的在线数量提供了途径。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
8楼 2022-11-05 11:48:08
主题:回复:Modbus设备FB接口设计背后的理念 我是把每个从站的整套通信参数,当作一个虚拟的通道。每个通道留给一个实体设备。 操作人员在现场,从屏幕上输入从站号和波特率。配置一个,上线轮询一个。没有配置的通道不参与轮询。参数错了,踢出轮询并报警。 例1:程序预留5个通道,只有一个配置了从站号,上线轮询。本案例可以自动匹配波特率变化 。还有4个设备可以未来加入。 图2:5个预留通道都配置了设备参数,5个从站都可以参与轮询。但有2个设备的参数错误或物理设备不在线,被踢出轮询。 关于通道的配置,原本打算开放给现场操作人员的灵活性,可以自由调整设备轮询次序。后来考虑到这些人会胡乱设置,把多个从站挤到一个通道(如下图),还要费事给他们解释通道是什么。就禁止了,程序加载后自动分配通道占位。 程序中要对不同种类的modbus设备,事先预留出足够数量的通道和空设备实例。界面上配置了通信参数和工艺选择及参数后,这些空的通道和实例就和现实的物理设备匹配上了。 就和游戏的不同副本一样道理。没有玩家的副本都是一样的空副本。有了玩家,每个空副本才开始运转,被玩家数据填充为一个独特的实例。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
9楼 2022-11-05 12:46:59
主题:回复:Modbus设备FB接口设计背后的理念 一个Modbus任务执行结束后,下一个任务应该是什么? 各种各样的多个Modbus设备,每个设备都有各自不相同的任务集,再加上各种动态的实时工艺变化带来的任务数量和次序的随时无规律变化,导致这个问题并不容易回答。 前面讲到的品牌通信任务表,它里面的任务数组,只是个包含本品牌设备的各种工艺可能性的静态任务全集。 这个数组中的任务次序并不能代表它们的实际执行次序,只是存储位置的序号而已。当然有的时候,它们会按照这个次序执行。位置次序代表了默认的先来后到的执行次序。 但更多时候,执行次序会前后或四处乱跳。 这种无规律窜动,既发生在一个设备的任务表之内,也发生在不同设备的任务表之间。 这些规律和跳跃,本质上都源自设备FB实例的界面功能的变化,也就是设备对象中的命令和参数的变化。 外界功能的变化是没有规律的。或者说,至少程序员是不能一厢情愿的指望外界功能变化是有规律的。 因为程序员面对的是这世上所有的各种Modbus设备,这样一个大基准空间。眼前案例只是这个大空间中一个很小的子集。 面对如此复杂的多样性,如何用一种相同的FB设计思想,来包容所有的可能?存在这样一种万能的,能在界面功能和底层IO之间,在任何业务场景下,都能任意来回转换的固定调度方式吗? 很显然,单一固化的调度策略是不可能做到的。 我的答案是:在设备FB内部,采用分层解耦的多层架构来解决这个问题。 这个架构是稳定的。可以通过增减层,或在每一次层中增减元素,把各种可能的调度元素分配到它应该属于的层中去。 程序员的核心是:把过程场景原子化,元素化分解,然后按照场景细节的真相,把这些不同元素各自所需的处理手法,摆放到它们应该去往的层中去。 说到这,可能会意识到:在本质上,这不仅是个编程的问题。它涉及到你如何看待和理解眼前发生的任何事情,甚至如何把你的工作和生活中的事情,分解为纯净的元素,这样的洞察能力。 到最后,这个结构的内容,实际上就是你自身在代码中的投影而已。 这就是观察的本质。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
12楼 2022-11-05 14:57:20
主题:回复:Modbus设备FB接口设计背后的理念 就当做真的好像是有一个单独的0号从站设备实际存在一样,去写操作。 广播这个概念就等效理解为“对0号站的写操作,而0号站是合法单独存在的一个设备“。 这和对其它站号的单个从站的写操作是一样的结构。 设备对象中的Modbus地址设定就是0。它的品牌任务通信表中都是写任务设定。 或者可以说:根本不存在广播这件事,0号站是个单独的实际存在站点。这个站点在哪里呢?它就是连接到该端口的所有从站的集合。从站集合就是一个0号从站。集合是个单独的设备。 说到底,通信的本质是协议。而存在于协议中的设备模型,首先都是虚拟的数据结构的定义。只不过碰巧,它们有时候可以和现实设备对应上。 也就是说:从站,首先是存在于协议中的一个抽象概念。只不过,我们总是在观念上习惯把他们直接不假思索理解为物理实物。 |
yming 至圣 经验值:132147 发帖数:22526 精华帖:854 |
13楼 2022-11-05 18:31:05
主题:回复:Modbus设备FB接口设计背后的理念 对于驱动来讲,在总线结构通讯中,对一个驱动从站顺利发送/应答完成,可能需要30 ms(115200 ),若对接近10台的轮询,可能就需要300ms(实际会更长)。这对于产线来说,已经是有“前后不同步”的问题了。(更别提9600了) 其实,在驱动从站侧,是有不同通讯响应机制的。 1、配置报文。一旦配置好报文,(数字化)从站将时刻更新主站要读写的数据。随时做出响应。 2、非配置的读写; 从站将在通讯处理段分次处理。对于RAM写快/读慢。而要写入ROM是最慢的(正确写入后,才给予通讯完成响应。) 3、立即执行,无响应。(总线形式的都有这种命令。) 第三种,就是广播。MB是地址0、USS是地址31。当写入所有驱动统一(转速)设定值/启动命令时,所有驱动同时动作、同时变化,且不返回数据。 实际运行中,驱动侧由于设定值有比例系数,所以,仍是按不同比例在运行。 现在的问题是,一般都不提供这种广播程序快。需要自己写。 所以好奇。
学而时习之,不亦说乎?温故而知新,不亦乐乎?
|
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
14楼 2022-11-05 20:03:10
主题:回复:Modbus设备FB接口设计背后的理念 这样的场景,用前面提到的调度结构理念,优先权抢断广播(写0站),肯定可以。 不管从站挂接有多少,优先执行都是非常快的,仅受限于扫描周期的长短。 但UDP会更好,毕竟MB慢,易干扰。MB根本上不适合要求非常快的场景。 我理解的通信设计,还是要首先从案例需求的根本出发,扩大考量范围。不首先限定于串口还是以太网的某种技术手段。这也就是ElonMask嘴里说的第一性原则。 特别高速的通信需求,PLC就已经有些不适合了。因为一般的PLC编程无法运用多线程,反正我是没见过,CPU资源利用率低。扫描周期的存在,就是个固定的单线程,这是瓶颈。 当然,PLC本身就像面向易用的编程产品,底层的深挖掘和细化定制能力肯定锁死或受限,这是平台的天生局限。 高速通信要求,程序员必须能驾驭每个独立的静态线程,和上位机开发中的策略一样。针对多个设备节点的多个独立静态通信线程,常驻内存,实时的,在平行监听和运转。那个反应速度,PLC根本比不了。我在上位机实测过,TCP传输就比S7快50倍速度。UDP没测过,但肯定更快。 现在上位机开发,目前最好的还是.Net平台。鸿蒙的仓颉语言一直没出来,用Types cript,但是其生态已经有2000多家支持。且已经有了十几二十款开发板了,主流SoC都逐渐开始支持。但这个如果不是专业弄,根本干不了,也没这精力和资源。 鸿蒙的软总线,是在操作系统的最底层,解决掉设备自动发现和自动互联的问题。煤矿应用中,30%丢包率的场景下,能做到端到端10ms传输,其中主要就是UDP。软总线把7层模型的底下四层给精简合并了。 我个人非常看好鸿蒙OpenHarmony的潜力,它具备颠覆性的工业潜力。目前我知道的国内PLC厂家,只有汇川在2021年加入支持研发,但不知道他们具体会干啥。 前不久,华为发布了一个硬实时操作系统(RTOS)的内核UniProton。它不采用时间片,完全是按照优先级调度,有三种不同的调度速度快慢的选项。目前它可以同时驾驭多个ARM架构的芯片。实时的面向底层,非实时的面向UI。这就是给未来预备的。 闲扯一堆没用了。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
16楼 2022-11-06 13:56:14
主题:回复:Modbus设备FB接口设计背后的理念 调度是什么?
对于任何一个任务,凡是能影响它是否会执行的做法,都是调度。调度是为应对场景细节,而设计的处理手段的集合。场景是多变的,所以调度一定是个开放集合。 场景是由什么决定的?项目需求,或者叫客户需求。还有自己的选择,或者叫追求。 设备FB有一个重要的方面需要维护:确保设备的UI体验,与FB内部的调度状态保持一致。 一个设备FB实例与一个物理设备之间的信息是闭环的。双方的信息应该是实时双向同步一致的。设备UI的任何操作都会同步到物理设备,物理设备的任何变化也会同步到设备UI,不管这变化是不是因UI产生的(比如:直接用手去按设备的物理按钮)。 |
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
17楼 2022-11-07 13:21:52
主题:回复:Modbus设备FB接口设计背后的理念 485波特率自动匹配功能的调度特点
这个功能需要每个设备实例内部,具备485端口初始化能力,用西门子的11种波特率去反复初始化端口。 每次端口初始化之后,发送的测试任务,可能是品牌通信任务表中的任何一个。测试任务自身,它的工艺属性,是持续任务,定期任务,偶发任务,或是不同优先级任务,这些都与波特率自动匹配无关。它们依然要服从工艺的动态调度,只不过是执行期间碰巧遇到了自动匹配模式。每个任务依然是执行自己的工艺功能,而自动匹配获得的是波特率的验证。各取所需,互不干扰。这是不同层的行为。 从上图的两次波特率自动匹配中可以看到:每次的11个任务中,都是第6个任务的波峰最窄,那是9600下的测试任务,也就是唯一成功的那一个。因为真实波特率就是9600。 稍改进,让每个测试任务分隔的清楚一点 通常的设备,在获得公共IO执行权后,执行自己的多个任务期间,不需要反复初始化485端口。波特率自动匹配,只不过是在每个任务执行前,换一种波特率再次初始化端口而已。 匹配期间,至少会遇到10次通信错误。本帖案例中的温控器实例,任务超过3次错误就要被禁止获得公共IO占用权的。所以在自动匹配期间,故障调度机制需要被暂时禁用。 在自动匹配期间,如果其它设备实例,发出了优先任务申请,不予理睬。这种非常见模式下,中断是无意义的。所以自动匹配模式具有更高优先级。这和中断的道理一样,彼此间是优先级的安排和较量。 485波特率自动匹配,作为设备对象的一个功能,是通过分散在4个层中的6个元素,协作出来的叠加效果。
|
宝冬 至圣 经验值:10562 发帖数:1734 精华帖:26 |
21楼 2022-11-08 20:29:02
主题:回复:Modbus设备FB接口设计背后的理念 如果多个站点之间,需要的时候可以互相写入,实现对称的事件通知。这样的机制需要站点可以动态更换Master身份。 诸多站点当中,首先应该设置某个站点惯常做为默认Master。其它临时Master完成事件写入任务后,要切换回Slave身份。 这需要每个站点都同时具有两个功能模块,一个是负责Master,一个负责slave功能。 Master和slave功能的切换,依赖几个标识变量的数值变化。所以这些标识变量数据,都是来自别的站点,它们的即时性和可靠性就至关重要。为此需要一个标识位,它能够表明本次轮询中,当前这个读或写任务是成功还是失败。以此确认数据的可靠性。在此通信数据可靠的基础上,双方的沟通确认机制才能成立。 每个希望成为临时Master的Slave,需要向默认Master发出请求(就是把自身的请求标识变量设置成特定数值,等待主站读取)。并等待默认Master的同意。 默认Master需要在调度每个站点通信完毕后,检查一次当前Slave的请求标识变量。这样可以回避多个从站都想成为临时主站的冲突问题,默认Master只对当前轮询到的站点应答这种需求。其余的请求阻塞。 如果确认是某个Slave的请求,且当前用户操作策略允许这样做,则通知该Slave同意(向该slave写入数值到特定的同意标识位,这需要在调度模块中加入一个优先级判断的调度等级)。同意写入成功后,停止站点调度,Master功能的调度现状被悬挂中止。并把485端口初始化为Slave模式,站点切换到Slave功能模式运行,等待临时Master的完成通知的写入到自己的特定标识变量中。 此时的485网络中没有Master。 在确认默认Master的同意后(这个确认的过程最好要稍加等待),这个Slave切换至Master模式并发送写入。写入成功后,给默认Master发出完成通知,并把自己切换回slave功能。 此时的485网络中也没有Master。 默认Master收到完成通知后(这个确认的过程最好也要稍加等待),把自己从Slave切换回Master模式,并在之前的停止悬挂位置开始继续站点轮询调度。 这和TCP建立连接一样,也需要三次握手。请求、同意、完成通知。三次握手的意义在于需要两次确认。任何需要考虑特定对方的通信方式,都要有三次握手。UDP没有这个问题就不需要。 超时情况,默认slave会自复位为slave身份,默认Master会自复位为Master身份。 很重要的是,modbus通信过程的细节,每一次读写成败记录和计数,都要呈现在HMI画面上,让操作员在现场就可以知道底层发生了什么。有助于现场诊断和修复。 通信的切换可能会产生冲突和反射。只要传输和确认机制可靠,站点的身份转换可以很快完成,冲突状况持续很短。有错误没问题,逐渐减少,直至消除就可以了。 默认主站和临时主站,都可以在切换操作的3秒钟之后,强制恢复之前的身份。不管标识位变化正确与否。 最差的状况也就是:在故障情形下,每个站点都把自己切换至slave状态,在几秒钟之间,没有主站,让全网恢复寂静,之后再启动某个主站。这需要完善的站点淘汰机制做为基础,本帖的实例中就已经具备了这个功能。 其实,这个需求的modbusRTU实现,并不具备多大现实价值,只是做为玩法讨论和编程策略推演。其它通信有很好的方式,比如UDP。 上述这套机制的本质就是:在Modbus协议报文的纯粹数据部分中,封装另一个通信协议。这和以太网的协议嵌套的做法一样。 |