Rexroth(力士乐)PLC与Labwindows CVI OPC通讯的实现

本文详细介绍了Rexroth PLC与CVI通过OPC进行通讯的全过程,包括OPC Server的安装与配置、OPC Configurator的使用、OPC Test Client的测试方法以及PLC端的配置与编程技巧。特别关注了变量表的配置和Labwindows CVI 2013下的编程实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OPC Server 安装

力士乐开发软件中已经集成了OPC Server的相关组件,只需要安装Indraworks里的communication 组件即可,当前我使用的版本是Indraworks 12v08,这里就不详细介绍安装方法了。
只是要注意一点:最好将电脑非Unicode设置成非中文,再安装,我碰到许多次出现Indraworks安装失败,或者在配置后测试 noconfig的状态。

OPC Server配置

OPC Configurator 配置

  1. 打开Rexroth>IndraLogic>OPC Configurator
    在这里插入图片描述
  2. 添加PLC, 如果是一个客户端选择 Single PLC,如果位多个可以右击append PLC在这里插入图片描述.在这里插入图片描述
  3. Edit创建通讯参数,如果已有Gateway可以直接点添加New…,如有没有先添加Gateway 选择TCP/IP
  4. 在这里插入图片描述在这里插入图片描述
  5. 添加PLC配置时,请选择TCP/IP(Level 2 Route)在这里插入图片描述

OPC Test Client 测试

如果想要确认新建的OPC Server运行状态如何,可以使用 OPC Test Client 程序。
Rexroth>Communication>OPC Test Client
在这里插入图片描述
选择IndraLogic.OPC在这里插入图片描述状态信息栏里显示运行状态
在这里插入图片描述
如果出现状态noconfig的状态,你的PLC是连接到你的服务器的,只是读不到你的配置文件,或者读不到 你的变量表。
遇到这个问题
1.首先确认你的电脑是否设置成了Unicode简体中文,可先将他设置成英文。
2.变量表是你的PLC编译后生成的.SDB文件。可以将他手动配置到你的Gateway Files里。

连接好PLC后可以通过添加Item 来确认变量是否可以遍历到
在这里插入图片描述

PLC端配置

新建变量
在这里插入图片描述Project>Option>Symbol Configuration>Configure symbol file 选中所有变量
在这里插入图片描述

CVI OPC通讯编程

当前使用的是Labwindows CVI 2013版本
从文件读取配置信号ini配置文件如下
[PLC_TO_IPC]
Num=16
;
[IPC_TO_PLC]
Num=25
;
[PO_0]
EN=“HeartBeat”
CN=“心跳信号”
GM=“HeartBeat”
URL=“opc://localhost/IndraLogic.OPC.02/PLC1:.stPLC.bPuls”
TYPE=111
SIZE=2
;
[PO_1]
EN=“DMC”
CN=“ID码”
GM=“DMC”
URL=“opc://localhost/IndraLogic.OPC.02/PLC1:.stPLC.chDMC”
TYPE=115
SIZE=50
;
[PO_2]
EN=“Mode”
CN=“模式”
GM=“Mode”
URL=“opc://localhost/IndraLogic.OPC.02/PLC1:.stPLC.iMode”
TYPE=102
SIZE=4
;

封装部分直接上源代码
当前只读取PLC 的四种类型。CodeSys下的 REAL,BOOL,INT,STRING

// Include files

#include "dataskt.h"
#include <ansi_c.h>
#include "inifile.h"
#include "PLCCom.h"

//==============================================================================
// Constants

#define GETURL(section,chvalue)   if(0>=Ini_GetPointerToRawString (handle,section,"URL",&chvalue)) return -1001;else      //get the url if wrong return -1;
#define GETTYPE(section,value)   if(0>=Ini_GetInt(handle,section,"TYPE",&value)) return -1002;else 				//get the valible type if wrong return -1;
#define GETSIZE(section,value)   if(0>=Ini_GetInt(handle,section,"SIZE",&value)) return -1005;else 				//get the valible type if wrong return -1; 
#define GETHANDLE(url,section,i)  if(0>DS_OpenEx(url,DSConst_ReadWriteAutoUpdate,NULL,NULL,DSConst_EventModel,1,&section)) return -1003000-i;else  //get the handle of the valible

#define CHECK_HANDLE(handle,i)	if(handle== 0)  return -1000000-10000*i;else
#define OPC_GETTYPE(handle,type,i)  if(0>DS_GetDataType(handle,&type,&uiSize,NULL)) return -2000000-10000*i;else
#define CHECK_TYPE(type,type2,i)   if(type2!=type) return -3000000-10000*i-type2;else 
#define ErrCheck(function,i)    if(function<0) return -4000000-10000*i;else
//==============================================================================
// Types

//==============================================================================
// Static global variables
static struct  SignalInfo stPLC[56];
static struct  SignalInfo stIPC[56]; 
int PLCNO=0;
int IPCNO=0;

//==============================================================================
// Static functions
enum Type
{
	T_BOOL=111,
	T_INT=102,
	T_REAL=104,
	T_STRING=115,

};

unsigned char *pPlcData;
unsigned char *pIpcData;


//==============================================================================
// Global variables

//==============================================================================
// Global functions
/*****************  initial  the url********************/
//RootPath  the root path of the program
//pPlcInfo plc 信息的结构体指针
//pIpcInfo ipc信息结构体指针
//success 返回0   失败返回负数
//               -1 FAIL TO GET URL
//               -2 FAIL TO GET THE HANDLE
//               -3 FAIL TO GET THE TYPE
//               -4 FAIL TO fIND THE FILE 
extern "C" __declspec(dllexport)int PLC_COM_Initial(char *RootPath,unsigned char *pPlcInfo , unsigned char *pIpcInfo)
{
	char path[225]="";
	char *chval;
	char temp[20]="";
	char *opcURLs;
	pPlcData=pPlcInfo;
	pIpcData=pIpcInfo;
	strcpy(path,RootPath);
	strcat(path,"\\Configuration\\PLCInterface.ini"); //文件路径获取
	IniText handle=Ini_New (0);
	if(0!=Ini_ReadFromFile(handle,path)) {Ini_Dispose(handle);return -1004;}
	
	if(0>=Ini_GetInt (handle,"PLC_TO_IPC","Num",&PLCNO)) return -1005;
	
	if(0>=Ini_GetInt (handle,"IPC_TO_PLC","Num",&IPCNO)) return -1006;
	
		
	unsigned int  uiType=0, uiSize=0; 
	//read the url for the config file
	for(int i=0; i<PLCNO; i++)
	{
		sprintf(temp,"PO_%d",i);
		GETURL(temp,chval);
		opcURLs=StrDup(chval);
		GETHANDLE(opcURLs,stPLC[i].iHandle,i);
		free(opcURLs); 
		GETTYPE(temp,stPLC[i].iType); 
		GETSIZE(temp,stPLC[i].iSize);
		OPC_GETTYPE(stPLC[i].iHandle,uiType,i);
		CHECK_TYPE(stPLC[i].iType,uiType,i) ;
	}
	
	for(int i=0; i<IPCNO; i++)
	{
		sprintf(temp,"IO_%d",i);
		GETURL(temp,chval);
		opcURLs=StrDup(chval);
		GETHANDLE(opcURLs,stIPC[i].iHandle,i);
		free(opcURLs); 
		GETTYPE(temp,stIPC[i].iType);
		GETSIZE(temp,stIPC[i].iSize);
		OPC_GETTYPE(stIPC[i].iHandle,uiType,i);
		CHECK_TYPE(stIPC[i].iType,uiType,i) ;
	}
	
	Ini_Dispose(handle);
	return 0;
}
/*****************  read the signal from plc********************/
//success 返回0   失败返回负数 
//               -1 FAIL CHECK THE HANDLE
//               -2 FAIL TO GET THE TYPE  
//               -3 FAIL TO CHECK THE TYPE
//               -4 FAIL TO GET THE VALUE
extern "C" __declspec(dllexport)int PLC_COM_Read()
{
	int index=0;
	unsigned int uiType=0;
	unsigned int uiSize=0;
		
	//plc to ipc signal receive
	for(int i=0; i<PLCNO; i++)
	{
		int *piVal=(int *)(pPlcData+index);
		short *psVal=(short *)(pPlcData+index);
		char *pcVal=(char *)(pPlcData+index);
		float *pfVal =(float *)(pPlcData+index);
		
		int iVal=0;
		short sVal=0;
		float fVal=0;
		CHECK_HANDLE(stPLC[i].iHandle,i);
		OPC_GETTYPE(stPLC[i].iHandle,uiType,i);
		switch(stPLC[i].iType)
		{
			case T_BOOL:
				ErrCheck(DS_GetDataValue(stPLC[i].iHandle,CAVT_SHORT, &sVal, uiSize+1, NULL,NULL),i);
				sVal=abs(sVal);
				*psVal=sVal;
				break;
			case T_INT:
				ErrCheck(DS_GetDataValue(stPLC[i].iHandle,CAVT_INT, &iVal, uiSize+1, NULL,NULL),i);
				*piVal=iVal;
				break;
			case T_STRING:
				ErrCheck(DS_GetDataValue(stPLC[i].iHandle,CAVT_CSTRING,pcVal, uiSize+1, NULL,NULL),i);
				break;
			case T_REAL:
				ErrCheck(DS_GetDataValue(stPLC[i].iHandle,CAVT_FLOAT, &fVal, uiSize+1, NULL,NULL),i);
				*pfVal=fVal;
				break; 
			default:
				return -600000-i*1000-stPLC[i].iType;
		}
		index+=stPLC[i].iSize; 
	}
	return 0;
}
/*****************  write the signal to plc ********************/
//success 返回0   失败返回负数 
//               -1 FAIL CHECK THE HANDLE
//               -2 FAIL TO GET THE TYPE  
//               -3 FAIL TO CHECK THE TYPE
//               -4 FAIL TO set THE VALUE
extern "C" __declspec(dllexport)int PLC_COM_Set()
{
	int index=0; 
	//ipc to plc signal receive
	for(int i=0; i<IPCNO; i++)
	{
		int *piVal=(int *)(pIpcData+index);
		short *psVal=(short *)(pIpcData+index);
		char *pcVal=(char *)(pIpcData+index);
		float *pfVal =(float *)(pIpcData+index);
		
		int iVal=0;
		short sVal=0;
		float fVal=0;
		CHECK_HANDLE(stIPC[i].iHandle,i);
		switch(stIPC[i].iType)
		{

			case T_BOOL:
				sVal=*psVal;
				ErrCheck(DS_SetDataValue (stIPC[i].iHandle,CAVT_SHORT, &sVal,0,0),i);
				break;
			case T_INT:
				iVal=*piVal;
				ErrCheck(DS_SetDataValue(stIPC[i].iHandle,CAVT_INT, &iVal, 0,0),i);
				break;
			case T_STRING:
				ErrCheck(DS_SetDataValue (stIPC[i].iHandle,CAVT_CSTRING, pcVal,0,0),i);
				break;
			case T_REAL:
				fVal=*pfVal;
				ErrCheck(DS_SetDataValue(stIPC[i].iHandle,CAVT_FLOAT, &fVal, 0,0),i);
				break;
			default:
				return -700000-i*1000-stIPC[i].iType;
		}
		index+=stIPC[i].iSize; 
	}
	return 0;
}

调用以上函数的方法

//此部分位初始化调用
int PLCInterface_Initial()
{
	int iRetVal=0;
	
	if(Initialed==0)
		iRetVal=PLC_COM_Initial(gPara.SWPath,(unsigned char*)&stPLC,(unsigned char*)&stIPC);
	if(iRetVal==0)
	{
		Initialed=1;
		stIPC.bIsReady=TRUE;
	}else
	{
		char temp[20]="";
		sprintf(temp,"Code:%d",iRetVal);
		MessageAlarm("1081",temp,gPara.ActLanguage); 
	}
	return iRetVal;
}
//此部分贴入定时器循环扫描
int PLC_IPC_Ctrol()
{
	static int bPulseEx=0;
	static double dTimerA=0,dTimerB=0;//timer count
	static char Trigger=0;
	static int ModeEx=-1;
	

	if(!Initialed) return 0; // 
	//READ AND WRITE
	int ret=PLC_COM_Read();
	if(0!=ret)
	{
		char temp[20]="";
		sprintf(temp,"RCode:%d",ret);
		MessageAlarm("1070",temp,gPara.ActLanguage);
		return 0;
	}
	ret=PLC_COM_Set();
	if(0!=ret)
	{
		char temp[20]="";
		sprintf(temp,"WCode:%d",ret);
		MessageAlarm("1070",temp,gPara.ActLanguage);
		return 0;
	}
}

至此,整个OPC通讯的实现就已完成。
划重点
DS_GetDataValue(stPLC[i].iHandle,CAVT_SHORT, &sVal, uiSize+1, NULL,NULL),i);
CAVT_SHORT 是指 在上位机程序变量的定义类型 而非PLC端变量的定义类型。
运行效果
在这里插入图片描述

论文摘要 近年来,随着虚拟仪器技术、网络通讯技术的显著进步以及Intemet的迅速 普及,将网络技术应用到虚拟仪器,使信号采集、传输和处理分析一体化,已 成为一种趋势。这一方面可以使许多昂贵的硬件资源得以共享,另一方面还便 于系统的扩展和效率的提高。它通过应用程序各功能化模块的有机结合,用 户利用友好的图形界面来控制计算机,完成对仪器控制、数据采集、分析、存 储及显示等功能。 本文针对数据采集监控系统的开发需求,设计并实现了一种基于虚拟仪 器平台的数据采集监控系统。系统采用的是一个虚拟仪器的构造形式,由数 据采集卡、工业控制计算机和信号调理电路构成硬件系统。系统软件开发平台 为LabWindow托VI,应用软件完成数据采集、处理、存储和显示等功能。 论文的主要研究工作如下: (1)根据数据采集监控系统的功能需求,提出了系统软件的总体设计方 案,并对虚拟仪器的体系结构和软件开发两方面进行了深入的研究; (2)设计并实现了数据采集和处理模块。利用基于线程池的多线程技术和 基于线程安全队列的数据保护机制,改善数据吞吐量,提高程序响应速度和更 有效的后台数据处理; (3)设计并实现了通信模块。制定串口通信协议,确保数据传输的可靠性 和高速率,有效解决了数据传输远程监控的问题; (4)设计并实现了数据库模块。实现了详细数据查询、报警信息查询、数 据报表管理、交接班管理、用户登录权限管理等功能。
### 回答1: 《力士乐PLC编程手册》是一本专门针对力士乐PLC编程的指南手册,其内容详细介绍了力士乐PLC的功能、使用方法以及常见编程技巧。在这本手册中,读者可以了解到PLC的基本原理和工作原理,学习如何进行PLC的硬件配置和系统设置。同时,手册还涵盖了PLC编程的基础知识,包括PLC编程语言、数据类型、逻辑控制以及常用的PLC指令等内容。 编程手册中文版的推出,有助于更多中文用户更方便地学习和应用力士乐PLC。尤其对于初学者和想要深入了解和掌握PLC编程技巧的人来说,这本手册是一个非常有价值的参考工具。手册中的文字清晰明了,配有丰富的实例和图表,方便读者理解和操作。 使用这本手册,读者可以学习如何通过编程实现PLC的各种控制功能,例如输入输出模块的配置、数据处理和计算、定时器和计数器的应用、PID控制等等。此外,手册还对PLC的调试和故障排除进行了详细说明,帮助读者解决在使用过程中可能遇到的问题。 总之,《力士乐PLC编程手册》中文版是一本对于想要学习和应用力士乐PLC编程的人来说非常实用的工具书。无论是初学者还是有一定经验的PLC程序员,都可以从中获得知识和技巧,提高PLC编程的能力和效率。 ### 回答2: 力士乐plc编程手册是一本专门为力士乐可编程逻辑控制器(PLC)的用户准备的指南。PLC是一种用于自动化控制系统的电子设备,在工业生产中起着重要的作用。 编程手册中文提供了关于力士乐PLC编程的详细说明和指导。它包含了PLC的工作原理、编程基础、编程语言和函数模块等方面的内容。手册中的信息可以帮助用户了解PLC的功能和操作流程,从而更好地应用于实际的控制系统中。 编程手册中文主要包括以下几个方面的内容: 1. PLC的基础知识:介绍PLC的基本原理和工作方式,包括硬件组成、输入输出模块、通信接口等。 2. 编程环境设置:指导用户如何在计算机上安装和配置编程软件,以及PLC的连接操作。 3. 编程语言介绍:详细介绍常用的编程语言,如梯形图、结构化文本、函数块图等,以及它们在PLC编程中的应用。 4. PLC指令和函数:列举了常用的PLC指令和函数,如逻辑运算、计数器、定时器、数据转换等,提供了它们的语法和使用示例。 5. 示例项目:给出了一些实际的案例项目,帮助用户理解如何应用编程技巧解决特定的控制问题。 通过阅读和学习力士乐PLC编程手册,用户可以深入了解PLC的原理和编程方法,掌握PLC编程技巧,为工业控制系统的设计和维护提供了重要的参考。同时,手册中的实例和案例也可以帮助用户快速上手和解决实际问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值