TwinCAT 中读取第三方伺服的 CoE 参数

作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

TwinCAT 3 简介

倍福推出的基于 PC 的控制技术定义了自动化领域的全球标准。在软件方面,1996 年推出的 TwinCAT(The Windows Control and Automation Technology,基于 Windows 的控制和自动化技术)自动化套件是倍福控制系统的核心部分。通过与 TwinCAT 软件结合使用,基于开放性和高度可扩展性原则,构建优化协调的自动化解决方案。

TwinCAT 可将任何一个基于 PC 的系统转换为一个带多个 PLC、NC、CNC 和机器人实时操作系统的实时控制系统。可模块化扩展的硬件和软件组件便于随时修改和添加功能,在需要时,控制解决方案具备的开放性不仅允许集成第三方组件,还可以为现有设备和系统定制改造方案,这样既能确保灵活性,又能保障客户的投资安全。

TwinCAT 3 是 TwinCAT 2 进一步发展的产物,重新定义了我们对自动化技术的认知。TwinCAT 3 为工程技术开辟了一条新的道路,并通过添加很多功能对实时内核进行扩展。工程环境完全集成在微软的 Visual Studio 框架中,除了系统配置、运动控制、I/O 和 IEC61131 PLC 编程语言之外,还可以进行编程和调试。

TwinCAT CoE、PDO、SDO 简介

TwinCAT CoE(CANopen over EtherCAT)是一种用于在 EtherCAT 网络上进行 CANopen 通信的协议。它允许通过 EtherCAT 总线与 CANopen 设备进行通信,并支持读取和写入 CANopen 对象字典中的数据。

PDO(Process Data Object)是 CANopen 协议中的一种过程数据对象,是 CANopen 中最主要的数据传输方式。由于 PDO 的传输不需要应答,且 PDO 的长度可以小于 8 个字节,因此传输速度快。

SDO(Service Data Object)是 CANopen 协议中的一种服务数据对象,通过对象索引和子索引与对象字典建立联系, 通过 SDO 可以读取对象字典中的对象内容, 或者在允许的情况下修改对象数据。所有的 SDO 报文数据段都必须是 8 个字节

EtherCAT 简介

EtherCAT(以太网控制自动化技术)是一个开放架构,以以太网为基础的现场总线系统,其名称的 CAT 为控制自动化技术(Control Automation Technology)字首的缩写。EtherCAT 是确定性的工业以太网,最早是由德国的 Beckhoff 公司研发。自动化对通讯一般会要求较短的资料更新时间(或称为周期时间)、资料同步时的通讯抖动量低,而且硬件的成本要低,EtherCAT 开发的目的就是让以太网可以运用在自动化应用中。

EtherCAT 的主站与从站通信方式,理解起来就是从主站发出一个火车,这个火车上拉着可以确定目标从站地址的信息、数据以及 EtherCAT 报文的其他部分。当经过一个从站的时候,从站管理器(ESC)就会将 EtherCAT 报文中和自己这一站有关的数据提取出来,同时将从站需要发给主站的数据插入上去,然后这个火车就会继续开往下个从站,直到最后一个从站。当发现到达最后一个从站后,这个火车就会顺着原路返回到主站,将从站的数据带给主站。

EtherCAT 从站对数据帧的读取、解析、过程数据的提取与插入完全由硬件来实现,这使得数据帧的处理不受 CPU 的性能、软件的实现方式等影响,时间延迟极小、实时性很高。而软件只需要把从站管理器从报文中提取出来的数据(RxPDO)进行处理,然后将 TxPDO 传给从站管理器。对于 SDO 也是一样,对下发的 SDO 数据进行处理,然后对上送的 SDO 数据进行读取、传递。

TwinCAT PLC 读写 SDO

  1. 导入库:TC2_EtherCAT

在这里插入图片描述

  1. 获取主站的 EtherCAT 地址

在这里插入图片描述

  1. 获取从站的 EtherCAT 地址

在这里插入图片描述

  1. 在 CoE - Online 中确定 Index 和 SubIndex

在这里插入图片描述

  1. 示例代码
PROGRAM MAIN
VAR
	sNetId     		: T_AmsNetId := '169.254.235.251.6.1';
	
	fbSdoRead  		: FB_EcCoESdoRead;
    bExecute_r   	: BOOL := TRUE;
    nSlaveAddr_r 	: UINT := 1001;
    nIndex_r     	: WORD := 16#1011;
    nSubIndex_r  	: BYTE := 0;
    vendorId_r   	: UDINT;
    bError_r     	: BOOL;
    nErrId_r     	: UDINT;
	
	fbSdoWrite  	: FB_EcCoESdoWrite;
	bExecute_w   	: BOOL := TRUE;
    nSlaveAddr_w 	: UINT := 1001;
    nIndex_w     	: WORD := 16#6071;
    nSubIndex_w  	: BYTE := 0;
    vendorId_w   	: INT := 33;	(*注意数据类型*)
    bError_w     	: BOOL;
    nErrId_w     	: UDINT;
END_VAR

fbSdoRead(
	sNetId:= sNetId, 
	nSlaveAddr:= nSlaveAddr_r, 
	nSubIndex:= nSubIndex_r, 
	nIndex:= nIndex_r, 
	pDstBuf:= ADR(vendorId_r), 
	cbBufLen:= SIZEOF(vendorId_r), 
	bExecute:= bExecute_r, 
	tTimeout:= , 
	bBusy=> , 
	bError=> bError_r, 
	nErrId=> nErrId_r, 
	cbRead=> );

fbSdoWrite(
	sNetId:= sNetId, 
	nSlaveAddr:= nSlaveAddr_w, 
	nSubIndex:= nSubIndex_w, 
	nIndex:= nIndex_w, 
	pSrcBuf:= ADR(vendorId_w), 
	cbBufLen:= SIZEOF(vendorId_w), 
	bExecute:= bExecute_w, 
	tTimeout:= , 
	bBusy=> , 
	bError=> bError_w, 
	nErrId=> nErrId_w);

在这里插入图片描述
在这里插入图片描述

TwinCAT C++ 读写 SDO

  1. 参考倍福的官方示例程序

在这里插入图片描述

  1. 重写 AdsReadCon 和 AdsWriteCon
    读写操作都是使用的请求和响应的形式来实现,需要配合使用
// CAds
void SubmitAdsCoEReadReq(AmsAddr amsAddr, DWORD index, DWORD subIndex, ULONG length);
virtual void AdsReadCon(AmsAddr& rAddr, ULONG invokeId, ULONG result, ULONG cbLength, PVOID pData);

void SubmitAdsCoEWriteReq(AmsAddr amsAddr, DWORD index, DWORD subIndex, ULONG length, PVOID pData);
virtual void AdsWriteCon(AmsAddr& rAddr, ULONG invokeId, ULONG result);
  1. 主要代码
HRESULT CTcSdoAccessModul::CycleUpdate(ITcTask* ipTask, ITcUnknown* ipCaller, ULONG_PTR context)
{
	HRESULT hr = S_OK;

	// handle pending ADS indications and confirmations
	CheckOrders();

	// TODO: Submit your ADS requests 
	ULONGLONG cnt = 0;
	if (SUCCEEDED(ipTask->GetCycleCounter(&cnt)))
	{
		if (cnt % 100 == 0)
		{
			// Cyclic call only for explanation
			// CoE can be call during SAFEOP
			m_vector.push_back(&m_Outputs.DataList[0]);
			SubmitAdsCoEReadReq(m_Inputs.AmsAddress, 0x2006, 0, 2);

			m_vector.push_back(&m_Outputs.DataList[1]);
			SubmitAdsCoEReadReq(m_Inputs.AmsAddress, 0x2100, 0, 1);

			m_vector.push_back(&m_Outputs.DataList[2]);
			SubmitAdsCoEReadReq(m_Inputs.AmsAddress, 0x2101, 0, 1);

			m_vector.push_back(&m_Outputs.DataList[3]);
			SubmitAdsCoEReadReq(m_Inputs.AmsAddress, 0x2200, 0, 1);

			m_Inputs.Value = 11;
			m_Inputs.Status = 22;
			m_Inputs.Data = 33;
			SubmitAdsCoEWriteReq(m_Inputs.AmsAddress, 0x6068, 0, 2, &m_Inputs.Value);
			SubmitAdsCoEWriteReq(m_Inputs.AmsAddress, 0x6071, 0, 2, &m_Inputs.Status);
			SubmitAdsCoEWriteReq(m_Inputs.AmsAddress, 0x607A, 0, 4, &m_Inputs.Data);
		}
	}

	return hr;
}

void CTcSdoAccessModul::SubmitAdsCoEReadReq(AmsAddr amsAddr, DWORD index, DWORD subIndex, ULONG length)
{
	// index = HIWORD(iOffs), subIndex = LOBYTE(LOWORD(iOffs))
	DWORD nOffset = (index << 16) | subIndex;

	AdsReadReq(amsAddr, invokeIdReadVendorIdByCoE, ADSIGRP_CANOPEN_SDO, nOffset, length);
}

void CTcSdoAccessModul::AdsReadCon(AmsAddr& rAddr, ULONG invokeId, ULONG nResult, ULONG cbLength, PVOID pData)
{
	if (invokeId == invokeIdReadVendorIdByCoE)
	{
		if (nResult != ADSERR_NOERR)
		{
			// "read failed with error=0x%x(%s)", nResult, AdsGetErrorText(nResult)
		}
		else
		{
			if (m_vector.size() > 0) {
				PVOID varAddr = m_vector[0];
				m_vector.erase(m_vector.begin());

				PULONG temp = static_cast<PULONG>(varAddr);
				*temp = *static_cast<PULONG>(pData);
			}
		}
	}
	else
	{
		__super::AdsReadWriteCon(rAddr, invokeId, nResult, cbLength, pData);
	}
}

void CTcSdoAccessModul::SubmitAdsCoEWriteReq(AmsAddr amsAddr, DWORD index, DWORD subIndex, ULONG length, PVOID pData)
{
	// index = HIWORD(iOffs), subIndex = LOBYTE(LOWORD(iOffs))
	DWORD nOffset = (index << 16) | subIndex;

	AdsWriteReq(amsAddr, invokeIdWriteBaudRateByCoE, ADSIGRP_CANOPEN_SDO, nOffset, length, pData);
}

void CTcSdoAccessModul::AdsWriteCon(AmsAddr& rAddr, ULONG invokeId, ULONG nResult)
{
	if (invokeId == invokeIdWriteBaudRateByCoE)
	{
		if (nResult != ADSERR_NOERR)
		{
			// "write failed with error=0x%x(%s)", nResult, AdsGetErrorText(nResult)
		}
	}
}
  1. 效果展示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值