Unstack Machine - 上位机和下位机通讯

这篇文章只作为工作记录和个人感悟。

作为刚入职的新人,第一个接到的项目就很有挑战性。项目要求是对一摞从高温烘烤箱里拿出来的磨片进行分拣,如下图所示:
Unstack Machine - 上位机和下位机通讯
可以看到,每个磨片之间有一层特氟龙片进行间隔,每隔十个磨片有一个铝合金片。项目的主要任务就是将特氟龙,铝合金片和磨片都分类放在不同的post上,之后会有图片解释什么是post.

第一个task是建立一个TCPsocket,实现上位机(机械臂和机器视觉)和下位机(PLC)的通讯。这里所使用的PLC是Delta的,使用的通讯协议是modbus,而机器视觉(Halcon)是基于C#运行的。机械臂本身虽然支持I/O串口通讯,但是只有16个input和16个output端口,略少。所以决定使用一个MCU作为信息交互的中转站,所有的信息处理都在MCU上运行。这里就要求基于C#写个程序,可以同时实现和机械臂,Halcon和PLC的通讯。具体的程序我发到Github上了,有需要的话可以去查看 TCP socket for Modbus. 这里就不再赘述关于代码的内容了,只来谈谈我遇到的困难和一些思考。
第一个遇到的困难是如何使用socket和PLC进行通讯,众所周知,PLC上有很多registers和coils,而我们每次运行的时候其实也是在不断读取和存储不同的数值。这里就有一个问题,我使用的PLC是基于Modbus通讯协议的,而这个协议要求将想发送的内容按照一定的结构用16进制代码封装。作为第一次接触modbus,它的frame格式确实对我相当不友好。首先,让我们看一下Modbus的封装格式:网上有很多介绍的文章,这里就随手找了一篇,截了张图,《今天讲一讲modbus - Orienfish》
Unstack Machine - 上位机和下位机通讯
可以看到,这里有个功能码,这个功能码的说明是这样的:
Unstack Machine - 上位机和下位机通讯
这也就是说,每次想要读取或者存储一个数值的时候,需要用不同的功能码,而且寄存器和coils的对应的功能码是不一样的,这点儿就和PC端的编程很不一样,而且作为一个C programmer, 使用C#实现modbus通讯在最开始真是折磨。

其次还有一点,也是让我吃了大亏的,就是modbus的数值返回顺序,因为他的读取顺序竟然是反的,通俗来说,就是你想知道寄存器编号1到4号上面都存了什么,你发送一个读取请求给PLC,然后它返回的竟然是4,3,2,1号寄存器对应的值,最恶心的是,在寄存器上,因为是16进制编码,所以返回的每两个字符对应一个值。举个简单的例子,你想获得数据(”12“,”34“,”56“),而modbus传回的会是(“56”,“34”,“12”)。极其蛋疼。

下一个遇到的难点是如何将数据发回机器人端,这里有个小tip一定要注意,可能每个机械臂的编程语言都不太一样,但是要注意的是,返回回去的一般都是一个string类型的值,但是要在末尾加上/r或者/n,我当时就是没注意这个点,卡了好半天。因为这个错误是隐式错误,不会报错。

剩下的到周末再继续更新吧。