借助PLC-Recorder,倍福TC3 PLC高速采集的方法(带时间戳采集)

发布于:2025-06-29 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、测试条件

二、测试结论

三、PLC的发送程序

1、报文数据结构

2、主程序的局部变量

3、PLC程序

4、时间戳计算

四、PLC-Recorder侧的通信设置

五、PLC-Recorder的通道配置

六、PLC-Recorder的变量配置

七、数据记录情况

八、小结


 

高速数据采集要保证速度,也要保证时刻的准确性。在Windows系统里,时间稳定性是个很难的问题。如果PLC发送的数据里带有时间信息,则可以由PLC来保证采样周期的稳定性。

从V2.12版本开始,PLC-Recorder软件可以处理发送电文里的时间戳(并有时钟校准等高级功能),有网友用0.24ms的速度外发,软件也能够稳定接收并精确确定数据的时刻。

本文向大家展示一下倍福TC3 PLC通过UDP快速通信的实现方法。

一、测试条件

测试条件如下:

  • 通信协议:UDP。
  • 编程软件和系统:TcXaeShell
  • PLC的IP地址:192.168.20.17
  • PLC-Recorder所在电脑的IP地址:192.168.20.20。
  • PLC的主任务设置成1ms的循环(最小可以设置为0.25ms,实际周期与平台有关,本文是用软PLC测试,实际周期是1ms左右,所以此处将周期设置为1ms)。

二、测试结论

本次测试采用了连续循环,每两个周期发送一次(上升沿触发)。理论发送周期:2ms

三、PLC的发送程序

1、报文数据结构

TYPE DUT_MSG :
STRUCT
	stamp:UDINT:=0;//时间戳,单位是微秒
	seq:UINT:=0;//电文序号
	sysWord:INT:=50;
	D_A:INT:=1;
	D_B:DINT:=2;
	D_C:REAL:=3.1;
	D_D:INT;
END_STRUCT
END_TYPE

2、主程序的局部变量

VAR
	fbSocketUdpCreate   	: FB_SocketUdpCreate;(*UDP建立连接的功能块*)
	fbSocketUdpSendTo      	: FB_SocketUdpSendTo;(* UDP发送功能块*)
	fbSocketUdpReceiveFrom   	: FB_SocketUdpReceiveFrom;(* UDP写入的功能块*)
	fbSocketClose     	: FB_SocketClose;(* UDP关闭建立连接的功能块*)
    bExecute          	: BOOL;(* UDP建立连接的执行位*)
	bSocketConnectBusy	: BOOL;
    hSocket           	: T_HSOCKET;(*UDP的句柄*)
	bSend				: BOOL;(*UDP发送的执行位*)
	bSocketSendbBusy	: BOOL;
	bRecieve          	: BOOL;(*UDP接收的执行位*)
	bSocketReceivebBusy	: BOOL;
	bSocketReceivenRecBytes	: UDINT;
	bClose            	: BOOL;(*UDP关闭连接的执行位*)
	
	fbSocketTcpCreate   	: FB_Socketconnect;(*TCP建立连接的功能块*)
	fbSocketTcpSendTo      	: FB_Socketsend;(* TCP发送功能块*)
	fbSocketTcpReceiveFrom   : FB_Socketreceive;(* TCP写入的功能块*)
	fbSocketClose_tcp     	: FB_SocketClose;(* TCP关闭建立连接的功能块*)
    bExecute_tcp          	: BOOL;(* TCP建立连接的执行位*)
	bSocketConnectBusy_tcp	: BOOL;
    hSocket_tcp           	: T_HSOCKET;(*TCP的句柄*)
	bSend_tcp				: BOOL;(*TCP发送的执行位*)
	bSocketSendbBusy_tcp	: BOOL;
	bRecieve_tcp          	: BOOL;(*TCP接收的执行位*)
	bSocketReceivebBusy_tcp	: BOOL;
	bSocketReceivenRecBytes_tcp	: UDINT;
	bClose_tcp            	: BOOL;(*TCP关闭连接的执行位*)
	
	TON1:TON;
	send_trig: BOOL;
	
	getsystemTime:NT_GetTime;
	startGet:BOOL;
	getTimeBusy:BOOL;
	getTimeError:BOOL;
	getTimeErrorInfor:UDINT;
	gvl1: INT;
	localtime: INT;
	cyclecounter: INT;
	sendPluse: BOOL;
	b_tcp_creadt_error: UDINT;
	
	stamp:UDINT;
	
	
	sendPluse_tcp: BOOL;
	arrSendData: DUT_MSG;
	
	fbCpuCounter : FW_GetCpuCounter;
    lowTime : UDINT;
    highTime : UDINT;
	
	
	fbSystemTime : GETSYSTEMTIME;
    fileTime : T_FILETIME;
    dtTime : DT;  // DATE_AND_TIME 格式
	
	getTime : NT_GetTime;
    timeStruct : TIMESTRUCT;
    startTrigger : BOOL := FALSE;
    err : BOOL;
	
	bFirstScanDone : BOOL := FALSE;
    bIsFirstScan : BOOL;
	startStamp:UDINT;
	
	timeNowULIntStart:UDINT;
	timeNowULIntDif:UDINT;
	bSend1: BOOL:=TRUE;//启动发送
END_VAR

3、PLC程序

cyclecounter:=cyclecounter+1;
IF
	cyclecounter>1 AND bSend1 //每2个周期发送一次报文。bSend1是启动变量,如果需要上电自动启动通信,则初始值设置为TRUE
	THEN 
		sendPluse:=TRUE;
		cyclecounter:=0;
		bExecute:=TRUE;//启动通信
	ELSE
		sendPluse:=FALSE;
END_IF

arrSendData.D_A:=arrSendData.D_A+1;  //数据循环累加

bIsFirstScan := NOT bFirstScanDone;  // 首次扫描时为 TRUE
bFirstScanDone := TRUE;              // 第一次执行后永久置为 TRUE

IF bIsFirstScan THEN
    STARTSTAMP:=Lowtime;
// 第一个扫描周期执行的代码
END_IF

fbCpuCounter(
    dwCpuCntLo => lowTime,   // 低 32 位 
    dwCpuCntHi => highTime   // 高 32 位
);
IF sendPluse THEN
	arrSendData.seq:=arrSendData.seq+1;//电文序号+1
	timeNowULIntDif:=(lowTime-STARTSTAMP)/10;//时间戳单位转换成微秒,并计算出时间偏差
	arrSendData.stamp:=timeNowULIntDif;
END_IF

fbSocketUdpCreate(
	sSrvNetId:= , 
	sLocalHost:='192.168.20.17' , 
	nLocalPort:=5011, 
	bExecute:= bExecute, 	
	tTimeout:= , 
	bBusy=> bSocketConnectBusy, 
	bError=> , 
	nErrId=> , 
	hSocket=>hSocket );

fbSocketUdpSendTo(
	sSrvNetId:= , 
	hSocket:=hSocket , 
	sRemoteHost:='192.168.20.20' , //PLC-Recorder所在的电脑IP地址。
	nRemotePort:=5011 , 
	cbLen:=SIZEOF(arrSendData) , //发送的长度
	pSrc:=ADR (arrSendData) ,  
	bExecute:=sendpluse,
	tTimeout:= , 
	bBusy=>bSocketSendbBusy , 
	bError=> , 
	nErrId=> );

4、时间戳计算

读取PLC的CPU脉冲计数,单位是0.1微秒,转换成微秒。

定义:

fbCpuCounter : FW_GetCpuCounter;

计算:

fbCpuCounter(
    dwCpuCntLo => lowTime,   // 低 32 位 
    dwCpuCntHi => highTime   // 高 32 位
);
IF sendPluse THEN
	arrSendData.seq:=arrSendData.seq+1;//电文序号+1
	timeNowULIntDif:=(lowTime-STARTSTAMP)/10;//时间戳单位转换成微秒,并计算出时间偏差
	arrSendData.stamp:=timeNowULIntDif;
END_IF

四、PLC-Recorder侧的通信设置

请用收听通道,并选择时间戳单位为us。需要配置来源的IP地址及本机收听的端口号。

五、PLC-Recorder的通道配置

此处虽然配置了采集周期,但在高速模式下不再使用该周期,以收到信息的时刻为准。

六、PLC-Recorder的变量配置

UDP报文结构简单,只需要定义自己需要提取的变量即可。起始地址为0的变量就是PLC里定义的时间戳。第二个变量是电文序号。

七、数据记录情况

这是用离线分析软件Ana打开的历史数据文件。

发现在启用时间戳功能时,实际采集周期是2.9ms,电文序号有波动。

而不启用时间戳功能时,实际采集周期是2.1ms,此处的stamp变量是两个扫描周期之间的时间戳差值(专门用于分析的,不是上面给出的程序),可以看出时间戳波动比较大,最小0.04ms,最大1.744ms,平均是1.01ms,因此,这个软PLC里时钟是不稳定的(声明:此处仅为测试系统的表现,不代表倍福实际产品的状态)。

八、小结

采集的速度越快,需要的技术越复杂,代价也越大。PLC-Recorder的主动采集模式,基本只需要在PLC-Recorder里配置变量,不需要在PLC做什么复杂工作,这种方式很便捷,但是速度也有限(最快20ms)。高速模式,就需要在PLC里配置通信,组织数据,然后调用通信语句,才能够实现,因此,对于PLC工程师也有了一点要求。

高速模式采用标准以太网通信协议,这也是大部分PLC都具备的能力,因此,