技术论坛

 一种不需要轮询的Modbus RTU通讯的方法

返回主题列表
作者 主题
zy5840
游士

经验值:264
发帖数:24
精华帖:0
楼主    2020-12-07 16:31:23
主题:一种不需要轮询的Modbus RTU通讯的方法 精编帖 

Modbus RTU是很常见的一种通讯方式,西门子200 SMART标准版的CPU都集成一个RS485的通讯端口,再加上有Modbus RTU的标准库,很方便的实现了Modbus RUT通讯。

但是,在实际使用中,西门子的标准Modbus RTU指令Mbus_msg的执行完成需要超过一个扫描周期,所以在程序的任何地方,只能有一个Mbus_msg指令在执行,如果有两个或者两个以上同时执行,则会立即报错,这就是资源的争夺。

西门子200 SMART的手册里给出了一个解决办法,就是:轮询。

轮询的效率不高:

    1.在多个写入的时候,因为有时候写入不是必须的,是根据需要写入,而这个需要又无法确定时间或者次序,轮询的效率就非常低;

    2.有大量需要写入/读取,轮询是没有优先级的,急需的写入/读取不能得到优先的响应;

对于以上两点,我找出一个办法,首先实现了“按需读取/写入”,优先级的问题有个思路,我就偷点懒,请大家想想怎么实现吧。


实现“按需读取/写入”的方法很简单,就是建立一个“通讯令牌”的“全局”的标志位,作为通讯状态的标志,如果“通讯令牌”为1,则表示通讯空闲,可以发起通讯,发起通讯后立即复位“通讯令牌”,这样就阻止了其他过程发起通讯,通讯完成后再置位“通讯令牌”标志,以便其他过程获得。

以上的思路基于“令牌环网”。


第二个问题

在通讯令牌发放完成后,第一个获取令牌的要先进堆栈,然后按照FIFO的规则出站,有优先级高的可以“插队”,需要的话也可以自定义优先级,总之方法也很多。




贤贤易色
奇侠

经验值:8060
发帖数:1305
精华帖:6
3楼    2020-12-07 22:31:20
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

感觉没啥特点。。。。。不如轮询来的要好一点,,,说真的这种优先级真的没必要。。。。你优先级高的先执行,,然后再执行优先级低的,,又不能实现当你需要的时候立马执行这个,(像中断一样),,,所以我觉得这种方法跟轮询也没啥区别。。。。。。。我个人看法还是轮询要好一点,,,因为这些数据要实时读取的啊,如果真的像那种有时候用有时候不用,在读取哪里加个使能就好了,,不接通就跳过那里了。。。。

养活一团春意思,撑起两根穷骨头
yanxiao
版主

经验值:26048
发帖数:11948
精华帖:43
6楼    2020-12-08 00:28:10
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

modbus协议是没法改变的。

modbus库帮你完成一次符合modbus协议规约的通讯过程。

前一次通讯完成后,下一次和谁通讯,传输什么内容,和modbus库无关,完全依照写程序人的意愿。


Zane
至圣

经验值:75765
发帖数:19245
精华帖:376
7楼    2020-12-08 00:48:58
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

换种方式轮询而已,MB-RTU实质是基于任务的轮询,关于读写的优先级,完全可以通过修改任务模式来实现,任务还是那个任务。


另外,轮询模式对于通信对象的控制度是均等的,过多的事件调度,导致与通信对象通信的时间间隔长短变化,对于可靠性也是有影响的。

Zane 注册自动化系统工程师 Always save before download
zy5840
游士

经验值:264
发帖数:24
精华帖:0
8楼    2020-12-08 10:03:02
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

这个方法不是改变协议啊

只是改变库的调用方式,我是觉得在使用的时候,库的调用使用轮询很不灵活;

这个方法的好处就是不用考虑上一次的过程是什么时候结束,只考虑本次过程,这样就非常方便了

zy5840
游士

经验值:264
发帖数:24
精华帖:0
9楼    2020-12-08 10:06:58
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

实现起来大致有几个步骤:

  1. 锁定当前状态;

  2. 检查令牌

  3. 获取令牌后,立即复位令牌,阻止其他过程获得令牌

  4. 完成通讯

  5. 置位令牌

芳季
至圣

经验值:66275
发帖数:14654
精华帖:100
10楼    2020-12-08 10:22:24
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

楼主

库的调用使用轮询很不灵活。

我就想聊一聊,什么为之轮询?

123三个站。要123 123 123 123……这样才叫轮询?

如果1213 1213 1213 1213 1213……叫不叫轮询?

如果无表面规律的1 1 1 3 1 1 1 2 3 1 1 1 1 2 1 1叫不叫轮询?

芳季
至圣

经验值:66275
发帖数:14654
精华帖:100
11楼    2020-12-08 10:38:30
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

站在modbus主站的角度。只要我做完这次通讯然后再做下一次通讯,不停地完成任务,外面什么事情你也别催。我已经没歇过了。你要我干什么你交单给我就是了。每次你给我一张单,我也不屯单。谁先谁后是你的事。

站在从站的角度。哦,主站偶尔会跟我聊两句,就好。我们常联系。别失联就是了。

站在编程者的角度,有一个站没多少通讯需求的,有修改才通讯一下。没必要没事都轮上它。浪费时间。

什么才算是轮询?

或许我们不要使用轮询这个字眼。反正调度的程序规定下来什么情况急就先干什么。没什么事的话就做完什么到什么。

通讯进行中,谁都别想占用。这个是铁定的了。那么任何通讯完成之后,都来到一个地方,在这个地方等候安排,下一个要联系的是什么任务。

楼主有没有这个意思?

Sykblue
侠圣

经验值:2826
发帖数:451
精华帖:2
12楼    2020-12-08 11:38:56
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

楼主这个就1个站不知道怎么说,就是一个站自循环。现在实际大多数人是需要多从站轮询,当数据不需要变化或者不需要更改其数据时或此站出现掉线等情况,通讯上可以及时判断,在以后的每次轮询中越过此站并输出报警。

我感觉楼主并没有解决这个问题,实际反而多此一举了。如果想实现楼主说的那种不需要轮询的环网应答结构,我感觉应当对通讯规约进行重编程,不能再使用MODBUS RTU库了。

利而不害,为而不争;专注暖通空调行业
zy5840
游士

经验值:264
发帖数:24
精华帖:0
13楼    2020-12-08 13:10:06
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

其实,我的意思不是指多站之间的通讯时不需要轮询;

而是,调用的库指令不需要轮询,是针对200 smart手册里资源争夺(mbus_msg指令不能同时调用)的一种解决办法的补充

或许大家对轮询的理解不同

对于多站之间的Modbus通讯,除了轮询还有什么办法呢?或者就像12楼说的需要对协议重新编写

我说的轮询仅仅是针对200 smart手册里的例子,如果这个不叫轮询,算我理解不对吧

贤贤易色
奇侠

经验值:8060
发帖数:1305
精华帖:6
14楼    2020-12-08 13:48:04
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

不知道你有没有看到  “zane”  的modbus 轮询总结,,,你看看这个或许有新的认识。


养活一团春意思,撑起两根穷骨头
芳季
至圣

经验值:66275
发帖数:14654
精华帖:100
15楼    2020-12-08 13:48:37
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

其实,是不是一个站没什么所谓的。要关注的是有多少个msg。

比如说。就一个变频器。要通讯的内容是:1.写正反停;2.写当前速度;3.读当前电流;4.读当前报警信息。

那么这几个需要通讯的内容,哪个的优先级感觉是最高的?(读电流要紧还是停电机要紧)哪个的使用频率最高?(读电流的使用频率高还是写正反停的使用频率高)

如果真的只有一条msg需求的话,就没必要。也不存在轮。

CCC@CCC
侠士

经验值:1746
发帖数:379
精华帖:0
16楼    2020-12-08 14:19:23
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

这个也是轮询的一种,只不过轮询的循序不是固定的,相对灵活点。

路漫漫其修远
zy5840
游士

经验值:264
发帖数:24
精华帖:0
17楼    2020-12-08 14:52:21
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

我觉得你的这个说法中肯,之所以提出这个方法就是因为msg指令需要一个接着一个,依靠done标志激活下一个,就算可以在前面加判断来决定是否调过,实际编程时也远远不如这个灵活。

另外,我也看了“zane”的文章http://www.ad.siemens.com.cn/club/bbs/post.aspx?a_id=1535757&b_id=64&s_id=83&num=23#anch

,思路有点接近,但是他是只用一个msg,调用的控制方式类似于堆栈,我是无所谓几个msg,并且保证使用的msg不会冲突,不用考虑其他的过程状态,在程序的任意位置都可以插入,如果你要较真,那么就在主程序和子程序的任意位置,不包括中断等不能插入的地方

优先级的问题,还是靠堆栈,我记得有个网友回复的,一个子程序实现入栈,一个子程序实现出站,优先级高的可以“置顶”,方法大致如此吧

虽然几乎用不着

yanxiao
版主

经验值:26048
发帖数:11948
精华帖:43
20楼    2020-12-08 19:21:40
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

我懂你的意思了。

通讯本来就是个跨多个扫描周期的慢过程,速度不仅仅由主站决定,还得看从站的响应速度。

你有多个通讯需求,得一个一个进行,不能抢(抢也没用),这是基本规则,无论你采用什么手段调度资源。


你所说的论询,是一种“机会均等”的通讯调度方式。

你提出的按优先级排队,不是“论询”。

只是个叫法不同,实质一样。

比较认同10楼、11楼的讲法。

zy5840
游士

经验值:264
发帖数:24
精华帖:0
21楼    2020-12-08 21:55:19
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

msg的done标志是“局部变量”,不同位置的msg指令都维护自己的done标志,“通讯令牌”是“全局变量”,任一过程都能访问(读写)

任一过程需要发起通讯时前都锁定当前状态,相当于开始排队,然后检查“通讯令牌”,如果通讯忙,只有等待下一次扫描再检查,如果有多个过程需要通讯,则按照过程在程序中的扫描顺序等待,多个过程在程序中的位置可以不连续,可以在主程序或子程序的任何地方;

只有通讯空闲时,也就是上个过程已经完成,无需关心上一个具体是哪一个过程,在主程序或者子程序的什么位置,本过程就会复位通讯令牌(使通讯处于忙的状态),然后发起通讯,并阻止其他过程发起通讯,因为没有了通讯令牌,或者说通讯已经处于忙的状态

通讯完成后再释放令牌,相当于令牌转移到下一个需要通讯的过程的手中

这个方法主要是对200 smart手册(V2.5 01/2020)里msg指令资源争夺解决方法的补充

题外话:上图程序段3有个bug,S  M2.0, 2  应该是S M2.0, 1  好几版手册了,都没改过来


程序在556页还有一部分,我就不贴了

最后说一句,或许这个帖子的名字不应该这么叫,如果叫做“一种西门子Modbus RTU指令库使用时解决资源争夺的方法”更合适一些

本来想给大伙分享一下我遇到的问题的解决方案的,没想到变成对“轮询”的争论,不是我的本意

到此为止吧

芳季
至圣

经验值:66275
发帖数:14654
精华帖:100
54楼    2020-12-11 17:14:19
精编帖  主题:回复:一种不需要轮询的Modbus RTU通讯的方法

回52楼Zaxife。

我是在保底的情况下观望。看见楼主,有意思,跟做过的人聊起来应该有劲。

在熟悉自己的程序的情况下插入优先功能,也是有头绪有眉目的。只是策略没有选择好而已,我一直都是惦记着这件事。在没有很好的策略之前就一直用可选择的轮训啦。

我觉得队列也不是不可能的。单纯谈队列,插队,不谈整体策略。我上面有楼层也说过,所有通讯完成之后,回到同一个状态。这个状态按照常规队列和优先队列提交的请求,分配接下来谁可以进行通讯。象银行叫号分一般号和vip号,两条队列同时工作。但是服务窗口只有一个。

您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。