今天继续我们的小白教程,老鸟就不要在这浪费时间了😊。
前面一期我们介绍了CODESYS的库管理器。这一期就来介绍一下CODESYS工程中“任务配置”的使用。看过前面教程的朋友可能记得,在工程的基本组成中有简单介绍过如何使用任务配置添加任务,这一期会详细介绍各种不同类型任务的特点、使用场景和执行时可能存在的问题,以及通过任务配置实现对Application中不同类型任务的设置和管理。
一、任务配置简介
任务配置用于定义和显示任务的基本设置。注意每个应用程序中只能包含一个任务配置对象。
1.监视
显示在线模式下各个任务的状态和相关统计信息。这里需要在登录控制器的模式下才能看到任务相关信息。
这些信息里面的平均周期时间、最大周期时间、抖动这几个数据可以帮助大家检查任务是否可能存在执行超时的情况。如果一个任务的平均周期时间大于周期循环时间,就说明该任务中执行的程序在给定的循环时间内无法执行完,这种情况需要对周期进行调整,避免出现不可预知的错误。
对于有实时性要求(实时性是指任务必须在指定的周期内执行完成,否则会出现问题)的任务,除了平均周期时间外,还要检查最大周期时间和抖动,看看是否满足实时性要求。实时性任务通常要求任务的平均周期时间和最大周期时间均小于任务循环周期,最大抖动越小越好。根据经验,如果一个有实时性任务的平均周期时间超过该任务周期循环时间的70%,说明执行时间非常紧张。建议要么调大该任务周期循环时间,要么调整执行内容,将占用时间的操作放到非实时任务中执行。
2.变量使用
变量使用显示任务配置下面所有任务中调用程序里面定义的变量,变量由哪个任务使用,以及使用的方式。对于多核系统,对变量的写操作应该只在某一个任务中进行,否则可能会导致结果不一致。在列表中点右键,可以选择要查看的一个或多个任务。从这里大家可以检查哪些变量被不同的任务使用了,方便查找不同任务读写同一变量造成的冲突问题。
3.属性
本页面显示当前使用的控制器支持的任务属性,包括任务的最大数量、循环任务的最大数量、自由任务的最大数量、状态任务的最大数量、当前CPU类型等信息。这项内容与使用的控制器有关,每个品牌的控制器显示会有差别。
二、任务特性
双击任务配置下面的任务名称,可以打开对应的任务配置页面。该页面中可以设置任务的优先级、类型、间隔以及任务中调用的程序。
1.优先级(Priority)
优先级用来确定一个任务执行的先后顺序。优先级高的任务先执行,优先级低的任务后执行。在低优先级任务运行过程中,如果高优先级任务满足条件,则会中断低优先级任务运行,先执行高优先级的任务,待其运行完成后在接着执行低优先级任务。
官方文档中优先级的范围从0到31,其中0代表最高优先级,31代表最低优先级。在任务的“配置”也没能够看到优先级的允许范围。
注意:(1)CODESYS的标准优先级范围为0-31,但是第三方厂家的控制器的具体设置有所不同,有些控制器的范围是0-10,有些是0-15。例如,我目前使用的控制器,其任务优先级是1到10。
2.任务类型
(1)循环(Cyclic)
按指定周期循环执行的任务。任务的循环周期由“间隔”来指定,单位可以设为ms或us。这是最常用的任务类型,任务周期通常根据执行的需要来设置,要求反应比较快的任务周期可以设的小一些,IO状态处理之类的任务周期可以设置为20~100ms。
循环类型任务里面有一个比较特殊的任务,EtherCAT总线通信任务,系统默认具有最高优先级,任务周期设置与所连接的伺服有关,常用值为1/2/4/8ms。
(2)状态(Status)
由指定的BOOL变量触发运行的任务。一旦输入字段Event中定义的全局变量值为TRUE,CODESYS就开始反复循环执行任务。
(3)惯性滑行(Freewheeling)
CODESYS在程序开始和完整过程结束时以连续循环的方式再次自动开始处理任务,可以设置任务优先级,但不存在循环时间设置问题。也就是执行完一次循环后会紧接着从头开始执行下一次循环,无限循环,没有停歇间隔。这类任务通常是作为后台任务来处理一些没有周期要求或者耗时很长的动作,比如将大量数据写入硬盘之类的。
(4)事件(Event)
在输入域Event中定义的全局变量出现上升沿时执行任务一次。
(5)外部事件(External)
输入字段Event中定义的事件出现时,系统立即开始执行任务。由目标系统提供所支持的事件列表。
注意事项:
(1)对于总线控制器,需要一个固定的周期性任务来保证总线的数据交换,因此对于总线任务不能使用“惯性滑行”类型。
(2)注意“状态”和“事件”类型任务的区别,前者是检查变量的状态,为TRUE则执行,而后者是检查变量的上升沿,即指定变量从FALSE到TRUE的切换。如果任务的周期与指定变量的变化频率不匹配,可能会导致无法检测到变化。
(3)更新总线伺服数据(EtherCAT、CAN等)的任务,其任务周期要与所使用伺服的任务周期一致。对于CAN总线之类的伺服,其心跳、节点保护和同步设置的时间必须是任务周期的倍数,否则可能会导致数据丢失。
(4)控制器允许的最大任务数量以及各种类型的任务数量与所使用的控制器有关。前面任务配置的属性页面显示的控制器的任务最大数量为13个,循环任务最大数量为10个,惯性滑行任务最大允许1个,状态任务最大允许建立2个。
(5)我使用过的几个控制器都只有前面三个类型的任务,事件和外部事件类型的任务我也没用过(主要是现在用的控制器也没见哪个支持这些类型☹)。
3.程序调用
在某个任务配置完成后,可以指定在该任务中运行的程序。任务中有多个程序时,程序调用的先后顺序与程序在任务中排列的先后顺序相同。
4.任务组
官方文档上还有一个任务组的功能,主要是针对多核控制器的,用于将任务分组并指定其运行在多核中的特定处理器核上。。
目前我使用过的控制器大多没有任务组这个功能,这里就不做详细介绍了(实际情况就是俺也不会,就不在这里丢人现眼~~跳过跳过……)。
三、任务的使用及陷阱
实际上,只要搞清楚了任务类型,以及要实现的目标,任务配置其实是很容易的。可能会影响到使用的主要是多个任务的执行顺序以及可能出现的一些错误。
1.任务执行顺序
多个任务的处理顺序是通过优先级和条件的组合实现的。
(1)如果多个任务同时满足处理条件,则CODESYS首先处理优先级最高的任务。
(2)如果具有相同优先级的多个任务同时满足处理条件,则CODESYS首先处理等待时间最长的任务。
(3)建立程序时不要与库或者设备树中的项目同名,在调用时有个默认的搜索顺序,同名可能导致调用到错误的程序。
(4)所有任务共享Application的内存,因此访问全局变量或块时有不少注意事项,后面会详细讲到。
2.多任务常见的错误
CODESYS的任务配置其实比直接用C或者C++进行多线程编程要容易得多,简单几个独立任务基本只要设置一下就可以用了。容易出问题的地方通常在多个任务的优先级分配和数据交互上面。
CODESY的任务配置的特点
(1)周期性任务有抢占,但是没有临界区保护。
抢占的意思就是高优先级的任务触发时,会优先执行,完成后再继续低优先级任务的执行。这个没有找到任何官方说明,完全是根据使用的经验判断的。高优先级任务会随时中断低优先级任务的执行,这个在很多情况下会导致低优先级任务中的程序没有执行完就被中断。由于没有临界区保护机制,在读写文件或者读写全局数据时,很容易造成数据不完整。
在多任务中读写同一个全局变量要小心分配任务时间和优先级,精心选择写数据和读数据的位置,读写数据的时间尽量短。其实最好的办法是别用这种方式,实在是要用就只能自求多福了,出不出错以及什么时候出错得看脸……
如果多任务在运行中不规律的出现超出你想象的数据,极有可能是这个导致的。至于我是怎么发现这个问题的,呵呵,说来话长,这里就不说了☹……
注意:最近在翻官方文档的时候突然看到某个页面里提到SysSem可以解决Runtime系统中多任务的数据同步性问题,搜索了一下,只找到如下图这一页,需要3.5.17及以上版本的库才行(我原来用3.5.16,所以前面也没说错,以前确实不支持😊)。
这个我也还没用过,有需要的朋友可以自己研究一下,……
(2)超时无报错。
这个错误在循环周期小的任务中比较容易,尤其是在控制器连接总线伺服时,在发送数据给伺服的任务中做复杂计算的情况。原因通常是任务中运行的程序执行时间过长,导致程序运行时间超出了所任务设定的周期导致的。CODESYS对于运行超时具体怎么处理帮助里面没有说明,首先系统不会报错,还是继续往下运行,所以具体造成的影响要看实际应用场景。但是按照接总线伺服运行的情况来看,超时会导致本周期数据发送失败,在运行速度高时电机振动会很明显。
四、示例
任务配置真的没有什么可以演示的~~
五、结论
写了这么多期教程了,如果你一定要问我怎么样能够学得更快,除了看我的教程以外,秘诀就是自己多实践几遍,让程序跑起来。编程是一个实践性非常强的东西,实践过程中所有不会和出错的地方,都是你需要学习的地方,个人觉得再没有比纠正错误更管用的学习方法了。
因为有其它事,这个小白教程中断了很长时间,博主也希望后面能够勤奋点😊。说实话,写着写着不知道写什么内容好了,大家有什么好的建议可以给我留言!另外觉得有问题或者不够小白的地方,欢迎留言吐槽~~
------------------
原创不易,感兴趣的多支持!