今天,正運(yùn)動(dòng)小助手給大家分享一下強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核MotionRT750下PC上位機(jī)的EtherCAT總線初始化。
PC上位機(jī)EtherCAT總線的初始化方式主要分為兩種:純上位機(jī)初始化和下載BASIC腳本初始化。本文將詳細(xì)講解如何通過(guò)純上位機(jī)的方法來(lái)實(shí)現(xiàn)PC上位機(jī)EtherCAT總線初始化。
全國(guó)產(chǎn)強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核MotionRT750
MotionRT750是正運(yùn)動(dòng)技術(shù)首家自主自研的
x86架構(gòu)Windows系統(tǒng)或Linux系統(tǒng)下獨(dú)占確定CPU的強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核。

該方案采用獨(dú)占確定CPU內(nèi)核技術(shù)實(shí)現(xiàn)超強(qiáng)性能的強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制。它將核心的運(yùn)動(dòng)控制、機(jī)器人算法、數(shù)控(CNC)及機(jī)器視覺(jué)等強(qiáng)實(shí)時(shí)的任務(wù),集中運(yùn)行在1-2個(gè)專(zhuān)用CPU核上。與此同時(shí),其余CPU核則專(zhuān)注于處理Windows/Linux相關(guān)的非實(shí)時(shí)任務(wù)。
此外集成MotionRT750 Runtime實(shí)時(shí)層與操作系統(tǒng)非實(shí)時(shí)層,并利用高速共享內(nèi)存進(jìn)行數(shù)據(jù)交互,顯著提升了運(yùn)動(dòng)控制與上層應(yīng)用間的通信效率及函數(shù)執(zhí)行速度,最終實(shí)現(xiàn)更穩(wěn)定、更高效的智能裝備控制,確保了運(yùn)動(dòng)控制任務(wù)的絕對(duì)實(shí)時(shí)性與系統(tǒng)穩(wěn)定性,特別適用于半導(dǎo)體、電子裝備等高速高精的應(yīng)用場(chǎng)合。

MotionRT750應(yīng)用優(yōu)勢(shì):
1.跨平臺(tái)兼容性:支持Windows/Linux系統(tǒng),適配不同等級(jí)CPU。
2.開(kāi)發(fā)靈活性:提供多語(yǔ)言編程接口,便于二次開(kāi)發(fā)與功能定制。
3.實(shí)時(shí)性提升:通過(guò)CPU內(nèi)核獨(dú)占機(jī)制與高效LOCAL接口,實(shí)現(xiàn)2-3us指令交互周期,較傳統(tǒng)PCI/PCIe方案提速近20倍。
4.擴(kuò)展能力強(qiáng)化:多卡多EtherCAT通道架構(gòu)支持254軸運(yùn)動(dòng)控制及500usEtherCAT周期。
5.系統(tǒng)穩(wěn)定性:32軸125us EtherCAT冗余架構(gòu)消除單點(diǎn)故障風(fēng)險(xiǎn),保障連續(xù)生產(chǎn)。
6.安全可靠性:不懼Windows系統(tǒng)崩潰影響,藍(lán)屏?xí)r仍可維持急停與安全停機(jī)功能有效,確保產(chǎn)線安全運(yùn)行。
7.功能擴(kuò)展性:實(shí)時(shí)內(nèi)核支持C語(yǔ)言程序開(kāi)發(fā),方便功能拓展與實(shí)時(shí)代碼提升效率。
MotionRT750視頻介紹可點(diǎn)擊→正運(yùn)動(dòng)強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核MotionRT750。
更多關(guān)于MotionRT750的詳情介紹與使用點(diǎn)擊→強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核MotionRT750(一):驅(qū)動(dòng)安裝、內(nèi)核配置與使用。
01 C#語(yǔ)言進(jìn)行PC上位機(jī)的EtherCAT總線初始化項(xiàng)目開(kāi)發(fā)
1.在VS2019菜單“文件”→“新建”→“項(xiàng)目”,啟動(dòng)創(chuàng)建項(xiàng)目向?qū)А?/p>

2.選擇開(kāi)發(fā)語(yǔ)言為“C#”和Windows窗體應(yīng)用程序,點(diǎn)擊下一步。

3.配置好項(xiàng)目名稱(chēng)和位置,以及相應(yīng)框架,點(diǎn)擊創(chuàng)建。

4.找到廠家提供的光盤(pán)資料里面的C#函數(shù)庫(kù),路徑如下(64位庫(kù)為例)。
進(jìn)入廠商提供的光盤(pán)資料,找到zauxdll.dll,zmotion.dll和Zmcaux.cs這三個(gè)庫(kù)文件。庫(kù)文件路徑:【00光盤(pán)資料】→【04PC函數(shù)】→【01PC函數(shù)庫(kù)V2.1】→【W(wǎng)indows平臺(tái)】→【C#】→【64位】→【庫(kù)文件】。

5.使用純上位機(jī)總線初始化時(shí)需要找廠商提供ZMotionECAT.cs文件。

6.將廠商提供的C#的庫(kù)文件以及相關(guān)文件復(fù)制到新建的項(xiàng)目中。
(1)將zmcaux.cs和ZMotionECAT.cs文件復(fù)制到新建的項(xiàng)目里面中。

(2)將zauxdll.dll和zmotion.dll文件放入bindebug文件夾中。

(3)將Zmcaux.cs和ZMotionECAT.cs文件添加進(jìn)項(xiàng)目中。右鍵項(xiàng)目名稱(chēng),選擇添加,再選擇現(xiàn)有項(xiàng),選擇Zmcaux.cs和ZMotionECAT.cs文件。

7.雙擊Form1.cs里面的Form1,出現(xiàn)代碼編輯界面,在文件開(kāi)頭寫(xiě)入using cszmcaux,并聲明控制器句柄g_handle。

至此,項(xiàng)目新建完成,可進(jìn)行C#項(xiàng)目開(kāi)發(fā)。
02 相關(guān)PC函數(shù)介紹
PC函數(shù)手冊(cè)可在光盤(pán)資料獲取,具體路徑如下:“00光盤(pán)資料3編程手冊(cè)3ZMotion PC函數(shù)庫(kù)編程手冊(cè)”。

1.上位機(jī)連接MotionRT750的接口。

2.控制器回零模式。

3.驅(qū)動(dòng)器回零模式。

03 PC純上位機(jī)總線初始流程

總線初始化代碼:
/// ///EtherCat 總線掃描與初始化 該接口會(huì)阻塞線程,阻塞時(shí)長(zhǎng)為超時(shí)時(shí)間 ////summary?>///句柄/param?>///槽位號(hào),控制器的Ecat總線槽一般為0/param?> ///總線初始化信息結(jié)構(gòu)體,設(shè)置總線軸號(hào)分配情況,總線IO分配情況/param?> ///超時(shí)時(shí)間/param?> ///ActionlogCallback = null回調(diào)函數(shù) 獲取在線命令錯(cuò)誤的返回字符串 ///返回值,小于 0 表示錯(cuò)誤,參考枚舉 EcatInitErrCode,0 表示線程初始化成功,大于0:?jiǎn)蝹€(gè)或多個(gè)zaux接口錯(cuò)誤碼的累加值/returns?> publicstaticintZAux_BusCmd_EcatInit(IntPtr handle,intSlotId, EcatInitInfoSet EcatInfo,intApiOutTime, Action logCallback =null) { intIresult=0;//接口返回值,錯(cuò)誤碼 intOutTime=ApiOutTime;//保存接口的超時(shí)時(shí)間 intEcatScanOutTime=ApiOutTime;//掃描超時(shí)時(shí)間 intIdleOutTime=100;//等待停止的超時(shí)時(shí)間 floatScanNodeNum=0;//掃描到的節(jié)點(diǎn)數(shù)量 StringBuilderReceBuff=newStringBuilder(256); byte[]cmdbuff=newbyte[2048]; intDrive_Vender,Drive_Device,Drive_Alias;//是否初始化Ecat初始化參數(shù) if(EcatInfo.InitStructFlag==1) { //1.本地軸相關(guān)參數(shù),用于指定本地軸的起始軸號(hào)和本地軸的數(shù)目 EcatInfo.LocalAxisId=0;//本地軸起始ID[默認(rèn)0],若使用則從0開(kāi)始 EcatInfo.LocalAxisNum=0;//本地軸使用的軸數(shù)量[默認(rèn)0],若使用則從0開(kāi)始 //2.驅(qū)動(dòng)軸相關(guān)參數(shù),用于指定總線驅(qū)動(dòng)軸的起始軸號(hào)和總線軸的數(shù)目 EcatInfo.DriveAxisStart=0;//驅(qū)動(dòng)軸起始ID[默認(rèn)0],第1個(gè)驅(qū)動(dòng)軸為DriveAxisStart,第2個(gè)為DriveAxisStart+1以此類(lèi)推 EcatInfo.DriveAxisNum=-1;//驅(qū)動(dòng)軸數(shù)量[默認(rèn)-1],-1表示不指定驅(qū)動(dòng)軸數(shù)量,若為0表示掃描到的軸數(shù)量,會(huì)檢查掃描到的軸數(shù)量是否一致 EcatInfo.DriveIoStara=256;//驅(qū)動(dòng)IO映射到寄存器后的前一個(gè)IO起始地址 EcatInfo.DriveIoSpa=16;//一個(gè)驅(qū)動(dòng)映射多少個(gè)IO端口數(shù)量 for(inti=0;i?128;?i++) ????????{ ????????????//?PDO?模式數(shù)組,參考?RTBasic?手冊(cè)?drive_profile?說(shuō)明,默認(rèn)值為?12?表示需要配置相關(guān)?PDO ????????????EcatInfo.DrivePdoMode[i]?=?12; ????????} ????????EcatInfo.DriveEnable?=?1;????//總線初始化時(shí)是否自動(dòng)使能,1?自動(dòng)使能,0?不使能 ????????//?3.?EtherCAT總線節(jié)點(diǎn)使用參數(shù),用于指定EtherCAT總線節(jié)點(diǎn)的數(shù)量和?IO擴(kuò)展模塊的起始地址 ????????EcatInfo.EcatNodeNum?=?-1;???//?ECAT?總線從站的數(shù)量,-1?表示不指定從站數(shù)量,若為?0?表示掃描到的從站數(shù)量,會(huì)檢查掃描到的從站數(shù)量是否一致 ????????for?(int?i?=?0;?i??128;?i++) ????????{ ????????????EcatInfo.NodeIoId[i]?=?0;????//?節(jié)點(diǎn)?IO?起始地址,以節(jié)點(diǎn)?ID?形式 ????????????EcatInfo.NodeAIoId[i]?=?0;???//?節(jié)點(diǎn)?AIO?起始地址,以節(jié)點(diǎn)?ID?形式 ????????} ????????//?4.?DC?同步時(shí)鐘和?DC?偏移補(bǔ)償,用于指定系統(tǒng)時(shí)鐘模式和?DC?偏移標(biāo)志及時(shí)間 ????????EcatInfo.SysClockMode?=?1;??????//?系統(tǒng)時(shí)鐘模式,1?開(kāi)啟?DC?同步時(shí)鐘,0?關(guān)閉?DC?同步時(shí)鐘 ????????for?(int?i?=?0;?i??128;?i++) ????????{ ????????????EcatInfo.DcOffsetFlag[i]?=?0;?//?N?個(gè)節(jié)點(diǎn)對(duì)應(yīng)的是否需要進(jìn)行?DC?偏移補(bǔ)償,0?關(guān)閉?DC?偏移,1?開(kāi)啟?DC?偏移,以節(jié)點(diǎn)?ID?形式 ????????????EcatInfo.DcOffsetTime[i]?=?0;?//?N?個(gè)節(jié)點(diǎn)對(duì)應(yīng)的?DC?偏移時(shí)間,單位為微秒,0.5?表示?0.5?微秒,以節(jié)點(diǎn)?ID?形式 ????????} ????} ????//需要特殊處理的驅(qū)動(dòng)器列表 ????//?定義?Elmo?廠商和設(shè)備?ID ????int?ElmoVender?=?0x9a; ????//?Elmo?驅(qū)動(dòng)器的廠商?ID ????int?ElmoDevice?=?0x30924;?//?Elmo?驅(qū)動(dòng)器的設(shè)備?ID????//?停止急停 ????Iresult?=?zmcaux.ZAux_Direct_Rapidstop(handle,?2); ????//獲取系統(tǒng)規(guī)格 ????UInt16?VirtualAxiseNum?=?0;?//?虛擬軸數(shù)量 ????uint8[]?MotionAxisNum?=?new?uint8[1];????//?運(yùn)動(dòng)軸數(shù)量 ????uint8[]?IoNum?=?new?uint8[4];?//?IO?數(shù)量 ????zmcaux.ZAux_GetSysSpecification(handle,?ref?VirtualAxiseNum,?MotionAxisNum,?IoNum); ????//?1、初始化軸參數(shù) ????for?(int?i?=?0;?i??VirtualAxiseNum;?i++) ????{ ????????Iresult?+=?zmcaux.ZAux_Direct_SetAxisAddress(handle,?i,?0); ????????Iresult?+=?zmcaux.ZAux_Direct_SetAxisEnable(handle,?i,?0); ????????Iresult?+=?zmcaux.ZAux_Direct_SetAtype(handle,?i,?0); ????????//?等待停止 ????????int?Idle?=?0; ????????while?(IdleOutTime??>0) { Iresult+=zmcaux.ZAux_Direct_GetIfIdle(handle,i,refIdle); if(Idle==-1) { break; } MyDelayMs(10,refOutTime); IdleOutTime=IdleOutTime-10; } } //2、本地軸號(hào)重映射 for(inti=0;i?EcatInfo.LocalAxisNum;?i++) ????{ ????????Iresult?+=?zmcaux.ZAux_Direct_SetAxisAddress(handle,?EcatInfo.LocalAxisId?+?i,?(-1?16)?+?i);?//?軸?0?--?>i映射到LocalAxisId-->LocalAxisId+i Iresult+=zmcaux.ZAux_Direct_SetAtype(handle,EcatInfo.LocalAxisId+i,1); } //3、DC同步時(shí)鐘的設(shè)置 if(EcatInfo.SysClockMode==1) { Iresult+=zmcaux.ZAux_Execute(handle,"SYSTEM_ZSET=SET_BIT(7,SYSTEM_ZSET)",ReceBuff,256);//打開(kāi)總線時(shí)鐘優(yōu)化 } else { Iresult+=zmcaux.ZAux_Execute(handle,"SYSTEM_ZSET=CLEAR_BIT(7,SYSTEM_ZSET)",ReceBuff,256);//關(guān)閉總線時(shí)鐘優(yōu)化 } if(0!=Iresult)//階段錯(cuò)誤碼攔截! { returnIresult; } //用于保存SlotScan回調(diào)中的字符串 stringslotScanLog=null; stringfirstLine=null; //自定義回調(diào):捕獲字符串,并可選地轉(zhuǎn)發(fā)給外部 ActioncaptureCallback=(msg)=> { slotScanLog=msg;//捕獲回調(diào)內(nèi)容! logCallback?.Invoke(msg);//同時(shí)通知外部(保持原有行為) }; //4、如果前面的流程都正常,則進(jìn)行第一次總線掃描,進(jìn)行DC偏移時(shí)間的設(shè)置 for(intii=0;ii?3;?ii++) ????{ ????????//停止總線掃描 ????????Iresult?+=?ZAux_BusCmd_SlotStop(handle,?SlotId); ????????//等待200ms ????????MyDelayMs(200,?ref?OutTime); ????????//開(kāi)始總線掃描 ????????if?(ZAux_BusCmd_SlotScan(handle,?SlotId,?ref?OutTime,?captureCallback)?==?1) ????????{ ????????????//DC偏移時(shí)間的設(shè)置 ????????????string?CmdBuff?=?string.Format("?NODE_COUNT({0})",?SlotId); ????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????ScanNodeNum?=?int.Parse(ReceBuff.ToString()); ????????????for?(int?j?=?0;?j??ScanNodeNum;?j++) ????????????{ ????????????????//判斷是否需要設(shè)置DC偏移時(shí)間 ????????????????if?(EcatInfo.DcOffsetFlag[j]?==?1) ????????????????{ ????????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},?0)",?SlotId,?j);????????//該節(jié)點(diǎn)的廠商ID ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????Drive_Vender?=?int.Parse(ReceBuff.ToString()); ????????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},?1)",?SlotId,?j);???????//該節(jié)點(diǎn)的設(shè)備編號(hào) ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????Drive_Device?=?int.Parse(ReceBuff.ToString());????????????????????//DC?偏移時(shí)間單位是ns ????????????????????CmdBuff?=?string.Format("ZML_INFO(19,?{0},?{1})?=?SERVO_PERIOD?*?{2}?*?1000",?Drive_Vender,?Drive_Device,?EcatInfo.DcOffsetTime[j]); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????} ????????????} ????????????break; ????????} ????????//獲取在線命令返回字符串傳給主窗口 ????????firstLine?=?string.IsNullOrEmpty(slotScanLog) ??????????string.Empty ????????:?slotScanLog.Split(new[]?{?'r',?'n'?},?StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); ????????if?(!string.IsNullOrEmpty(firstLine)) ????????{ ????????????ZMotionECAT.Instance.DoWork(firstLine); ????????} ????} ????//5、DC偏移時(shí)間設(shè)置后,需要再次掃描總線驅(qū)動(dòng)器 ????for?(int?ii?=?0;?ii??3;?ii++) ????{ ????????//停止總線掃描 ????????Iresult?+=?ZAux_BusCmd_SlotStop(handle,?SlotId); ????????//等待200ms ????????MyDelayMs(200,?ref?OutTime); ????????//開(kāi)始總線掃描 ????????if?(ZAux_BusCmd_SlotScan(handle,?SlotId,?ref?OutTime,?captureCallback)?==?1) ????????{ ????????????//【6、節(jié)點(diǎn)數(shù)目判斷,看看是否少?gòu)恼尽?????????????String?CmdBuff?=?string.Format("?NODE_COUNT({0})",?SlotId); ????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????ScanNodeNum?=?int.Parse(ReceBuff.ToString()); ????????????if?(EcatInfo.EcatNodeNum??>=0) { //判斷節(jié)點(diǎn)數(shù)目是否正確 if((int)ScanNodeNum!=EcatInfo.EcatNodeNum) { //節(jié)點(diǎn)數(shù)目不一致 return(int)EcatInitErrCode.WrongNodeNum; } } //【7、總線軸個(gè)數(shù)判斷,看看軸數(shù)是否可以對(duì)上】 intBusAxisNum=0;//總線軸個(gè)數(shù) intNodeAxisNum=0;//當(dāng)前節(jié)點(diǎn)軸個(gè)數(shù) if(EcatInfo.DriveAxisNum>=0) { for(intj=0;j?ScanNodeNum;?j++) ????????????????{ ????????????????????CmdBuff?=?string.Format("?NODE_AXIS_COUNT({0},{1})",?SlotId,?j); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????NodeAxisNum?=?int.Parse(ReceBuff.ToString()); ????????????????????BusAxisNum?=?BusAxisNum?+?(int)NodeAxisNum; ????????????????} ????????????????//判斷軸數(shù)目是否正確 ????????????????if?(BusAxisNum?!=?EcatInfo.DriveAxisNum) ????????????????{ ????????????????????//驅(qū)動(dòng)器軸數(shù)目不一致 ????????????????????return?(int)EcatInitErrCode.WrongAxisNum; ????????????????} ????????????} ????????????//【8、IO映射和軸映射】 ????????????//總線軸總數(shù),從0開(kāi)始計(jì)數(shù) ????????????BusAxisNum?=?0; ????????????int?ServoPeriod?=?0; ????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?"?SERVO_PERIOD",?ReceBuff,?256);//獲取總線周期 ????????????ServoPeriod?=?int.Parse(ReceBuff.ToString()); ????????????//遍歷節(jié)點(diǎn) ????????????for?(int?i?=?0;?i??ScanNodeNum;?i++) ????????????{ ????????????????CmdBuff?=?string.Format("?NODE_AXIS_COUNT({0},{1})",?SlotId,?i);????//各個(gè)節(jié)點(diǎn)的軸數(shù) ????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????NodeAxisNum?=?int.Parse(ReceBuff.ToString()); ????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},?0)",?SlotId,?i);???????//該節(jié)點(diǎn)的廠商ID ????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????Drive_Vender?=?int.Parse(ReceBuff.ToString()); ????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},?1)",?SlotId,?i);???????//該節(jié)點(diǎn)的設(shè)備編號(hào) ????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????Drive_Device?=?int.Parse(ReceBuff.ToString()); ????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},?3)",?SlotId,?i);????????//該節(jié)點(diǎn)的設(shè)備撥碼ID ????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????Drive_Alias?=?int.Parse(ReceBuff.ToString()); ????????????????//【DC偏移設(shè)置成功校驗(yàn)】 ????????????????if?(EcatInfo.DcOffsetFlag[i]?==?1) ????????????????{ ????????????????????int?ZmlInfo,?NodeInfo; ????????????????????CmdBuff?=?string.Format("?ZML_INFO(19,{0},{1})",?Drive_Vender,?Drive_Device); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????ZmlInfo?=?int.Parse(ReceBuff.ToString()); ????????????????????CmdBuff?=?string.Format("?NODE_INFO({0},{1},19)",?SlotId,?i); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????NodeInfo?=?int.Parse(ReceBuff.ToString()); ????????????????????//DC偏移設(shè)置失敗 ????????????????????if?(((ServoPeriod?*?1000?*?EcatInfo.DcOffsetTime[i]?-?ZmlInfo)??>5)||(ZmlInfo!=NodeInfo)) { return(int)EcatInitErrCode.DcShiftSetFailu;//DC偏移設(shè)置失敗 } } //遍歷節(jié)點(diǎn)的各個(gè)電機(jī) for(intj=0;j?NodeAxisNum;?j++) ????????????????{ ????????????????????//【軸號(hào)的映射與軸類(lèi)型的設(shè)置】 ????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetAxisAddress(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?BusAxisNum?+?1); ????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetAtype(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?65); ????????????????????//【PDO的配置】 ????????????????????if?((Drive_Device?==?ElmoDevice)?&&?(Drive_Vender?==?ElmoVender)) ????????????????????{ ????????????????????????//如果是ELMO的驅(qū)動(dòng)器的PDO配置 ????????????????????????//ELMO的驅(qū)動(dòng)器需要關(guān)閉總線時(shí)鐘優(yōu)化 ????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?"SYSTEM_ZSET?=?CLEAR_BIT(7,?SYSTEM_ZSET)",?ReceBuff,?256); ????????????????????????CmdBuff?=?string.Format("DRIVE_PROFILE({0})?=?-1",?EcatInfo.DriveAxisStart?+?BusAxisNum); ????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????????CmdBuff?=?string.Format("NODE_PROFILE({0},{1})?=?-1",?SlotId,?i); ????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????????//ELMO的驅(qū)動(dòng)器需要自定義PDO ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c12,?0,?5,?0);//禁用RxPDO,禁用后才可以修改內(nèi)容 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c1c,?0,?5,?0);//禁用TxPDO,禁用后才可以修改內(nèi)容 ????????????????????????MyDelayMs(50,?ref?OutTime);????????????????????????//更新TXPDO列表 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?0,?5,?0);//禁用0x1a07 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?1,?7,?0x60410010);//狀態(tài)字 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?2,?7,?0x60770010);//當(dāng)前力矩 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?3,?7,?0x60640020);//反饋位置 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?4,?7,?0x60fd0020);//驅(qū)動(dòng)器輸入 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?5,?7,?0x60b90010);//probe狀態(tài) ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?6,?7,?0x60ba0020);//probe位置1 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?7,?7,?0x60bb0020);//probe位置2 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1a07,?0,?5,?0x7);//啟用分配?????????????????????????????????????????????????????????????????????????????????????????????????????????????????//更新RXPDO列表 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?0,?5,?0);//禁用0x1607 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?1,?7,?0x60400010);//控制字 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?2,?7,?0x60710010);//周期力矩 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?3,?7,?0x60ff0020);//周期速度 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?4,?7,?0x607a0020);//目標(biāo)位置 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?5,?7,?0x60b80010);//probe設(shè)置 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?6,?7,?0x60720010);//力矩限制 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?7,?7,?0x60600008);//控制模式 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1607,?0,?5,?0x7);//啟用分配?????????????????????????????????????????????????????????????????????????//1C12的配置 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c12,?0,?6,?0x1607);//?RxPDO分配對(duì)象 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c12,?1,?5,?1);//啟用分配? ????????????????????????//1C13的配置 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c13,?0,?6,?0x1a07);//TxPDO分配對(duì)象 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x1c13,?1,?5,?1);//啟用分配????????????????????????//清除ELMO的驅(qū)動(dòng)器報(bào)警 ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x6040,?0,?6,?0);//狀態(tài)初始化????????????????????????MyDelayMs(50,?ref?OutTime); ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x6040,?0,?6,?7);//伺服shutdown????????????????????????MyDelayMs(50,?ref?OutTime); ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x6040,?0,?6,?7);//伺服disable?voltage????????????????????????MyDelayMs(50,?ref?OutTime); ????????????????????????Iresult?+=?zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?0x6040,?0,?6,?15);//伺服fault?reset ?????????????????????} ????????????????????else?if?((Drive_Device?==?0x1ab0)?&&?(Drive_Vender?==?0x41B)) ????????????????????{ ????????????????????????//如果正運(yùn)動(dòng)的脈沖擴(kuò)展卡 ????????????????????????CmdBuff?=?string.Format("DRIVE_PROFILE({0})?=?0",?EcatInfo.DriveAxisStart?+?BusAxisNum); ????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????} ????????????????????else ????????????????????{ ????????????????????????//驅(qū)動(dòng)器PDO設(shè)置,驅(qū)動(dòng)器默認(rèn)設(shè)置--?-1?位置模式--0??速度模式--20+??力矩模式--30+ ????????????????????????CmdBuff?=?string.Format("DRIVE_PROFILE({0})?=?{1}",?EcatInfo.DriveAxisStart?+?BusAxisNum,?EcatInfo.DrivePdoMode[BusAxisNum]); ????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????????//是否映射總線驅(qū)動(dòng)器的硬件限位和原點(diǎn) ????????????????????????if?((4?==?EcatInfo.DrivePdoMode[BusAxisNum])?||?(5?==?EcatInfo.DrivePdoMode[BusAxisNum])?||?(12?==?EcatInfo.DrivePdoMode[BusAxisNum])) ????????????????????????{ ????????????????????????????//設(shè)置總線驅(qū)動(dòng)器的起始IO地址 ????????????????????????????int?StartIdTemp?=?EcatInfo.DriveIoStara?+?EcatInfo.DriveIoSpa?*?(BusAxisNum); ????????????????????????????CmdBuff?=?string.Format("DRIVE_IO({0})?=?{1}",?EcatInfo.DriveAxisStart?+?BusAxisNum,?StartIdTemp); ????????????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????????????//設(shè)置負(fù)限位 ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetRevIn(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?StartIdTemp); ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetInvertIn(handle,?StartIdTemp,?1); ????????????????????????????//設(shè)置正限位 ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetFwdIn(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?StartIdTemp?+?1); ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetInvertIn(handle,?StartIdTemp?+?1,?1); ????????????????????????????//設(shè)置負(fù)限位 ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetDatumIn(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?StartIdTemp?+?2); ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_SetInvertIn(handle,?StartIdTemp?+?2,?1); ????????????????????????} ????????????????????????else?if?(EcatInfo.DrivePdoMode[BusAxisNum]??4) ????????????????????????{ ????????????????????????????int?TempVar?=?0; ????????????????????????????//取消負(fù)限位的設(shè)置 ????????????????????????????Iresult?+=?zmcaux.ZAux_Direct_GetRevIn(handle,?EcatInfo.DriveAxisStart?+?BusAxisNum,?ref?TempVar); ????????????????????????????if?(TempVar??>=EcatInfo.DriveIoStara) { Iresult+=zmcaux.ZAux_Direct_SetRevIn(handle,EcatInfo.DriveAxisStart+BusAxisNum,-1); Iresult+=zmcaux.ZAux_Direct_SetInvertIn(handle,TempVar,0); } //取消正限位的設(shè)置 Iresult+=zmcaux.ZAux_Direct_GetFwdIn(handle,EcatInfo.DriveAxisStart+BusAxisNum,refTempVar); if(TempVar>=EcatInfo.DriveIoStara) { Iresult+=zmcaux.ZAux_Direct_SetFwdIn(handle,EcatInfo.DriveAxisStart+BusAxisNum,-1); Iresult+=zmcaux.ZAux_Direct_SetInvertIn(handle,TempVar,0); } //取消設(shè)置原點(diǎn) Iresult+=zmcaux.ZAux_Direct_GetDatumIn(handle,EcatInfo.DriveAxisStart+BusAxisNum,refTempVar); if(TempVar>=EcatInfo.DriveIoStara) { Iresult+=zmcaux.ZAux_Direct_SetDatumIn(handle,EcatInfo.DriveAxisStart+BusAxisNum,-1); Iresult+=zmcaux.ZAux_Direct_SetInvertIn(handle,TempVar,0); } } } //每軸單獨(dú)分組,軸報(bào)警只停自己 CmdBuff=string.Format("DISABLE_GROUP({0})",EcatInfo.DriveAxisStart+BusAxisNum); Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); //總線軸計(jì)數(shù)+1 BusAxisNum=BusAxisNum+1; } /*************************************************************************************** -------------------------------2:IO模塊和AIO模塊的設(shè)置------------------------------ ***************************************************************************************/ //ECAT節(jié)點(diǎn)數(shù)字量IO起始地址的映射 if(EcatInfo.NodeIoId[i]>=32) { CmdBuff=string.Format("NODE_IO({0},{1})={2}",SlotId,i,EcatInfo.NodeIoId[i]); Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); } //ECAT節(jié)點(diǎn)模擬量IO起始地址的映射 if(EcatInfo.NodeAIoId[i]>0) { CmdBuff=string.Format("NODE_AIO({0},{1})={2}",SlotId,i,EcatInfo.NodeAIoId[i]); Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); } /*************************************************************************************** --------------------------------3:特殊模塊的設(shè)置---------------------------------- ***************************************************************************************/ //正運(yùn)動(dòng)EIO24088脈沖擴(kuò)展軸和EIO16084脈沖擴(kuò)展軸軸類(lèi)型的設(shè)置與脈沖模式的設(shè)置 if((Drive_Device==0x1AB0)&&(Drive_Vender==0x41B)) {for(intk=0;k?NodeAxisNum;?k++) ????????????????????{ ????????????????????????//設(shè)置擴(kuò)展脈沖軸ATYPE類(lèi)型?ATYPE=1 ????????????????????????zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?(uint)(0x6011?+?k?*?0x800),?0,?5,?1); ????????????????????????//設(shè)置擴(kuò)展脈沖軸INVERT_STEP脈沖輸出模式??INVERT_STEP=0 ????????????????????????zmcaux.ZAux_BusCmd_SDOWrite(handle,?(uint)SlotId,?(uint)i,?(uint)(0x6012?+?k?*?0x800),?0,?6,?0); ????????????????????} ????????????????} ????????????} ????????????//【4、總線開(kāi)啟】 ????????????if?(ZAux_BusCmd_SlotStart(handle,?SlotId,?ref?OutTime,?captureCallback)?==?1) ????????????{ ????????????????MyDelayMs(3000,?ref?OutTime);?//延遲3秒,等待驅(qū)動(dòng)器時(shí)鐘同步,不同驅(qū)動(dòng)器時(shí)間不同,具體根據(jù)驅(qū)動(dòng)器調(diào)整延時(shí) ??????????????????????????????????????????????//"開(kāi)始清除驅(qū)動(dòng)器報(bào)警" ????????????????for?(int?Drivei?=?EcatInfo.DriveAxisStart;?Drivei??(EcatInfo.DriveAxisStart?+?BusAxisNum);?Drivei++) ????????????????{ ????????????????????//伺服錯(cuò)誤清除 ????????????????????CmdBuff?=?string.Format("DRIVE_CONTROLWORD({0})=128",?Drivei); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????MyDelayMs(10,?ref?OutTime); ????????????????????//伺服shutdown ????????????????????CmdBuff?=?string.Format("DRIVE_CONTROLWORD({0})=6",?Drivei); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????MyDelayMs(10,?ref?OutTime); ????????????????????//伺服disable?voltage ????????????????????//伺服fault?reset ????????????????????CmdBuff?=?string.Format("DRIVE_CONTROLWORD({0})=15",?Drivei); ????????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?CmdBuff,?ReceBuff,?256); ????????????????????MyDelayMs(10,?ref?OutTime); ????????????????} ????????????????MyDelayMs(10,?ref?OutTime); ????????????????//清除控制器所有軸的錯(cuò)誤狀態(tài) ????????????????zmcaux.ZAux_Direct_Single_Datum(handle,?0,?0); ????????????????MyDelayMs(200,?ref?OutTime); ????????????????//打開(kāi)總線軸使能總開(kāi)關(guān) ????????????????Iresult?+=?zmcaux.ZAux_Execute(handle,?"WDOG=1",?ReceBuff,?256); ????????????????//總線軸單軸上使能 ????????????????if?(EcatInfo.DriveEnable?==?1) ????????????????{ ????????????????????for?(int?Drivei?=?EcatInfo.DriveAxisStart?+?BusAxisNum?-?1;?Drivei??>=(EcatInfo.DriveAxisStart);Drivei--) { zmcaux.ZAux_Direct_SetAxisEnable(handle,Drivei,1);//總線軸通過(guò)這個(gè)指令上使能 MyDelayMs(10,refOutTime); } } returnIresult; } else { //獲取在線命令返回字符串傳給主窗口 firstLine=string.IsNullOrEmpty(slotScanLog) ?string.Empty :slotScanLog.Split(new[]{'r','n'},StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); if(!string.IsNullOrEmpty(firstLine)) { ZMotionECAT.Instance.DoWork(firstLine); } return(int)EcatInitErrCode.EcatStartFailu;//總線開(kāi)啟失敗 } } //獲取在線命令返回字符串傳給主窗口 firstLine=string.IsNullOrEmpty(slotScanLog) ?string.Empty :slotScanLog.Split(new[]{'r','n'},StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); if(!string.IsNullOrEmpty(firstLine)) { ZMotionECAT.Instance.DoWork(firstLine); } } return(int)EcatInitErrCode.NotScanNode; } //////停止槽位號(hào)是SlotId的總線通訊 //////句柄///返回值z(mì)aux接口錯(cuò)誤碼publicstaticintZAux_BusCmd_SlotStop(IntPtrhandle,intSlotId) { stringCmdBuff=string.Format("SLOT_STOP({0})",SlotId); StringBuilderReceBuff=newStringBuilder(256); returnzmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); } //////掃描控制器對(duì)應(yīng)槽的總線設(shè)備 //////句柄///返回值z(mì)aux接口錯(cuò)誤碼///ActionlogCallback=null回調(diào)函數(shù)獲取在線命令錯(cuò)誤的返回字符串 publicstaticintZAux_BusCmd_SlotScan(IntPtrhandle,intSlotId,refintOutTime,ActionlogCallback=null) { intScanOkFlag=0; intIresult=0; intEcatScanOutTime; UInt32puiread=0; uint8pbifExcuteDown=0; byte[]ZmcReceBuff=newbyte[256]; EcatScanOutTime=OutTime; //總線掃描指令的拼接 stringCmdBuff=string.Format("SLOT_SCAN({0})?RETURN",SlotId); //定義接受緩沖器并清空 StringBuilderReceBuff=newStringBuilder(1024); ReceBuff.Remove(0,ReceBuff.Length); //開(kāi)始掃描總線設(shè)備情況 Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,1024); //通過(guò)回調(diào)通知外部 stringresult=ReceBuff.ToString().Replace("-1n",""); logCallback?.Invoke(result); //延時(shí)等待掃描結(jié)果 if(ReceBuff.ToString()=="-1n") { EcatScanOutTime=0; ScanOkFlag=1; returnScanOkFlag; //Console.WriteLine("直接獲取-1,條件成功"); }elseif(ReceBuff.Length>0)//如果有其他的返回值則報(bào)未掃描到設(shè)備 { ScanOkFlag=0; //Console.WriteLine("直接獲取-1,條件失敗"); returnScanOkFlag; } else { MyDelayMs(500,refOutTime); EcatScanOutTime=EcatScanOutTime-500; } while(EcatScanOutTime>0) { Array.Clear(ZmcReceBuff,0,ZmcReceBuff.Length); //讀取在線命令的應(yīng)答,對(duì)沒(méi)有接收應(yīng)答的命令有用 Iresult+=zmcaux.ZMC_ExecuteGetReceive(handle,ZmcReceBuff,1000,refpuiread,refpbifExcuteDown); if(ZmcReceBuff[0]!=0) { //返回負(fù)一表示有成功掃描到設(shè)備 if((ZmcReceBuff[0]==45)&&(ZmcReceBuff[1]==49)&&(ZmcReceBuff[2]==10)) { ScanOkFlag=1; //Console.WriteLine("while獲取-1,條件成功"); break; } else { ScanOkFlag=0; //Console.WriteLine("while獲取-1,條件NG"); break; } } MyDelayMs(50,refOutTime); EcatScanOutTime=EcatScanOutTime-50; } returnScanOkFlag;} /////打開(kāi)總線 //////句柄///返回值z(mì)aux接口錯(cuò)誤碼///ActionlogCallback=null回調(diào)函數(shù)獲取在線命令錯(cuò)誤的返回字符串 publicstaticintZAux_BusCmd_SlotStart(IntPtrhandle,intSlotId,refintOutTime,ActionlogCallback=null) { intStartOkFlag=0; intIresult=0; intEcatScanOutTime; StringBuilderReceBuff=newStringBuilder(1024); UInt32puiread=0; uint8pbifExcuteDown=0; byte[]ZmcReceBuff=newbyte[256]; EcatScanOutTime=OutTime; MyDelayMs(100,refOutTime); stringCmdBuff=string.Format("SLOT_START({0},4)",SlotId); Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); //通過(guò)回調(diào)通知外部 stringresult=ReceBuff.ToString().Replace("-1n",""); logCallback?.Invoke(result); MyDelayMs(1000,refOutTime); CmdBuff=string.Format("SLOT_START({0},8)?Return",SlotId); Iresult+=zmcaux.ZAux_Execute(handle,CmdBuff,ReceBuff,256); //延時(shí)等待掃描結(jié)果if(ReceBuff.ToString()=="-1n") { EcatScanOutTime=0; StartOkFlag=1; returnStartOkFlag; //Console.WriteLine("直接獲取-1,條件成功"); } elseif(ReceBuff.Length>0)//如果有其他的返回值則報(bào)未掃描到設(shè)備 { StartOkFlag=0; //Console.WriteLine("直接獲取-1,條件失敗"); returnStartOkFlag; } else { MyDelayMs(500,refOutTime); EcatScanOutTime=EcatScanOutTime-500; } while(EcatScanOutTime>0) { Array.Clear(ZmcReceBuff,0,ZmcReceBuff.Length); //讀取在線命令的應(yīng)答,對(duì)沒(méi)有接收應(yīng)答的命令有用 Iresult+=zmcaux.ZMC_ExecuteGetReceive(handle,ZmcReceBuff,1000,refpuiread,refpbifExcuteDown); if(ZmcReceBuff[0]!=0) { //返回負(fù)一表示有成功掃描到設(shè)備 if((ZmcReceBuff[0]==45)&&(ZmcReceBuff[1]==49)&&(ZmcReceBuff[2]==10)) { StartOkFlag=1; //Console.WriteLine("while獲取-1,條件成功"); break; } else { StartOkFlag=0; //Console.WriteLine("while獲取-1,條件NG"); break; } } MyDelayMs(50,refOutTime); EcatScanOutTime=EcatScanOutTime-50; } returnStartOkFlag; }
04 C#總線初始化功能展示例程介紹
一、選擇連接方式為L(zhǎng)OCAL連接,點(diǎn)擊【連接】。彈出連接成功提示框后,配置總線軸地址參數(shù)和本地脈沖軸地址參數(shù)后,點(diǎn)擊【總線初始化】,會(huì)在界面表格中顯示總線相關(guān)信息。

1.若無(wú)法成功總線初始化,命令與輸出窗口會(huì)打印相關(guān)錯(cuò)誤信息。如:Unknown device man XXXSlot return error:3205.
報(bào)錯(cuò)信息如下圖,則需要先詢(xún)問(wèn)對(duì)應(yīng)驅(qū)動(dòng)器廠家提供XML文件。


解決方法:將驅(qū)動(dòng)器廠家提供的XML文件,添加到RTSys項(xiàng)目的配置文件中。
(1)打開(kāi)RTSys軟件,點(diǎn)擊【文件】,選擇【新建工程】。

(2)選擇文件路徑,輸入文件名,然后點(diǎn)擊【保存】。

(3)右鍵點(diǎn)擊【配置文件】,選擇【添加到配置文件】,選中要添加的XML文件后點(diǎn)擊【打開(kāi)】。

(4)點(diǎn)擊菜單欄中的【控制器】,接著點(diǎn)擊【生成ZAR文件】,隨后點(diǎn)擊【瀏覽】來(lái)選擇生成ZAR文件的路徑。

(5)將生成的ZAR文件放在項(xiàng)目的ZAR文件夾中,隨后進(jìn)行總線初始化。

具體代碼如下:
//獲取解決方案根目錄
stringsolutionDir=Path.GetFullPath(Path.Combine(AppContext.BaseDirectory,@"......"));
stringzarPath=Path.Combine(solutionDir,"ZAR");
//獲取所有文件的完整路徑string[]fileNames=Directory.GetFiles(zarPath).Select(Path.GetFileName).ToArray();
foreach(stringfileNameinfileNames)
{
//Init.zar為下載的ZAR文件名
if(fileName=="Init.zar")
{
stringpath=Path.Combine(zarPath,"Init.zar");
zmcaux.ZAux_ZarDown(g_handle,path,0);
AppendTextOut("ZAR文件下載成功?。。?,Color.DarkGoldenrod);
}
}
2.如需將對(duì)應(yīng)總線節(jié)點(diǎn)的IO狀態(tài)信息或模擬量信息映射到控制器上對(duì)應(yīng)起始地址查看,則修改對(duì)應(yīng)節(jié)點(diǎn)IO或模擬量的起始地址,修改完成后,點(diǎn)擊【保存】,再點(diǎn)擊【總線初始化】。

3.通過(guò)RTSys軟件查看IO或模擬量映射的地址成功與否。
成功連接控制器后,在菜單欄中找到【控制器】→【控制器狀態(tài)】→【槽位0節(jié)點(diǎn)】,可以看到所有節(jié)點(diǎn)對(duì)應(yīng)的IO或模擬量起始地址??梢栽诳偩€初始化完成后觀看此界面確認(rèn)IO或模擬量起始地址映射正常。

相關(guān)代碼介紹:
(1)上位機(jī)如何鏈接上MotionRT750。
if(Controler_IP.Text!=null&&Controler_IP.Text!="")
{
intret=-1;
switch(Connect_ModeIP.Text)
{
case"IP":
//控制器IP地址連接
ret=zmcaux.ZAux_FastOpen(2,Controler_IP.Text.Trim(),5000,outg_handle);
break;
case"COM":
//控制器COM串口號(hào)連接
ret=zmcaux.ZAux_OpenCom(uint.Parse(Controler_IP.Text),outg_handle);
break;
case"LOCAL":
//LOCAL接口連接RT750
ret=zmcaux.ZAux_FastOpen(5,Controler_IP.Text.Trim(),5000,outg_handle);
break;
case"PCI":
//插入卡槽卡號(hào)連接PCI卡
ret=zmcaux.ZAux_FastOpen(4,Controler_IP.Text.Trim(),5000,outg_handle);
break;
}
if(ret!=0)
{
MessageBox.Show("IP鏈接失敗,報(bào)錯(cuò)碼:"+ret.ToString());
}
else
{
if(g_handle!=(IntPtr)0)
{
//連接成功后停止所有軸
ret=zmcaux.ZAux_Direct_Rapidstop(g_handle,2);
MessageBox.Show("鏈接成功!");
this.Text="已連接";
timer1.Enabled=true;
}
}
}
(2)總線初始化結(jié)構(gòu)體定義,自定義初始化所需的變量,例如LocalAxisId(本地軸起始ID)和LocalAxisNum(本地軸使用的軸數(shù)量)。
具體變量信息可以在解決方案中點(diǎn)擊ZMotionEcat.cs文件進(jìn)行查看。
其中,DrivePdoMode用于設(shè)置每個(gè)軸的發(fā)送PDO和接收PDO的配置選擇。不同模式對(duì)應(yīng)的PDO數(shù)據(jù)各不相同。
例如,若總線軸需切換至EtherCAT周期速度模式或EtherCAT周期力矩模式,則相應(yīng)的PDO列表必須包含對(duì)應(yīng)數(shù)據(jù),如模式17和18支持三種總線模式。
具體列表數(shù)據(jù)請(qǐng)參考RTBasic手冊(cè)中的drive_profile說(shuō)明。
if(textBox1.Text==""||textBox3.Text=="")
{
Console.WriteLine("總線參數(shù)不能為空");
return;
}
//定義總線初始化的信息結(jié)構(gòu)體個(gè)數(shù),最多可以支持128個(gè)節(jié)點(diǎn)MyEcatInit.EcatInitInfoSetecatInitInfo=new
MyEcatInit.EcatInitInfoSet(int.Parse(textBox3.Text));
?ecatInitInfo.InitStructFlag=0;//是否自定義初始化參數(shù),設(shè)置1的話使用默認(rèn)的總線初始化參數(shù),設(shè)置成0則需要自定義總線初始化相關(guān)參數(shù)
if(ecatInitInfo.InitStructFlag!=1)
{
//1.本地軸參數(shù),用于指定本地軸的起始ID和使用的軸數(shù)量
ecatInitInfo.LocalAxisId=int.Parse(textBox2.Text);//本地軸起始ID
ecatInitInfo.LocalAxisNum=int.Parse(textBox4.Text);//本地軸使用的軸數(shù)量
//2.驅(qū)動(dòng)軸相關(guān)參數(shù),用于指定驅(qū)動(dòng)軸的起始ID和數(shù)量
ecatInitInfo.DriveAxisStart=int.Parse(textBox1.Text);//驅(qū)動(dòng)軸起始ID,第1個(gè)驅(qū)動(dòng)軸為DriveAxisStart,第2個(gè)為DriveAxisStart+1以此類(lèi)推
ecatInitInfo.DriveAxisNum=-1;//驅(qū)動(dòng)軸數(shù)量[默認(rèn)-1],-1表示總線初始化的時(shí)候不判斷驅(qū)動(dòng)的軸數(shù)量是否對(duì)上,若為0表示掃描到的軸數(shù)量,會(huì)檢查掃描到的軸數(shù)量是否一致
ecatInitInfo.EcatNodeNum=int.Parse(textBox3.Text);//總線節(jié)點(diǎn)數(shù)目[默認(rèn)-1],-1表示總線初始化的時(shí)候不判斷節(jié)點(diǎn)個(gè)數(shù)是否對(duì)上
for(inti=0;i?ecatInitInfo.EcatNodeNum;?i++)
????{
????????ecatInitInfo.DrivePdoMode[i]?=?12;??????????????????//?PDO?模式數(shù)組,參考?RTBasic?手冊(cè)?drive_profile?說(shuō)明,默認(rèn)值為?12?表示需要配置相關(guān)?PDO
????}
????ecatInitInfo.DriveEnable?=?1;???????????????????????????//?總線初始化時(shí)是否自動(dòng)使能,1?驅(qū)動(dòng)器自動(dòng)使能,0?不使能驅(qū)動(dòng)器
????ecatInitInfo.DriveIoSpa?=?16;???????????????????????????//?一個(gè)驅(qū)動(dòng)映射多少個(gè)?IO?端口數(shù)量????
????//?3.DC?同步時(shí)鐘和?DC?偏移補(bǔ)償,用于指定系統(tǒng)時(shí)鐘模式和?DC?偏移標(biāo)志及時(shí)間
????ecatInitInfo.SysClockMode?=?1;??????????????????????????//?系統(tǒng)時(shí)鐘模式,1?開(kāi)啟?DC?同步時(shí)鐘,0?關(guān)閉?DC?同步時(shí)鐘
????for?(int?i?=?0;?i??ecatInitInfo.EcatNodeNum;?i++)
????{
????????ecatInitInfo.DcOffsetFlag[i]?=?0;???????????????????//?N?個(gè)節(jié)點(diǎn)對(duì)應(yīng)的是否需要進(jìn)行?DC?偏移補(bǔ)償,0?關(guān)閉?DC?偏移,1?開(kāi)啟?DC?偏移,以節(jié)點(diǎn)?ID?形式
????????ecatInitInfo.DcOffsetTime[i]?=?0;???????????????????//?N?個(gè)節(jié)點(diǎn)對(duì)應(yīng)的?DC?偏移時(shí)間,單位為微秒,0.5?表示?0.5?微秒,以節(jié)點(diǎn)?ID?形式
????}
}
二、點(diǎn)擊【軸參數(shù)初始化】進(jìn)入軸控制界面,開(kāi)始總線軸的手動(dòng)調(diào)試運(yùn)動(dòng)。
1.軸的使能控制。首先將軸類(lèi)型切換到總線軸,再觀察軸使能狀態(tài)指示燈的顏色,可以準(zhǔn)確判斷軸的使能情況:綠色代表已使能,紅色則表示未使能。點(diǎn)擊圖案即可切換軸的使能狀態(tài)。

2.配置好軸參數(shù)、軸號(hào)及相關(guān)參數(shù)后,通過(guò)左轉(zhuǎn)右轉(zhuǎn)手動(dòng)調(diào)試軸運(yùn)動(dòng)。
建議將【脈沖當(dāng)量】設(shè)置為機(jī)臺(tái)運(yùn)動(dòng)1mm所需的脈沖數(shù)。若按此推薦設(shè)置,【速度】的單位為mm/s,【加速度】和【減速度】的單位則為mm/s2。
通常,【加速度】和【減速度】設(shè)置為速度的10倍。
3.若在調(diào)試過(guò)程中不確定機(jī)臺(tái)運(yùn)動(dòng)1mm所需的脈沖數(shù),可將【脈沖當(dāng)量】設(shè)為1。
為安全起見(jiàn),【速度】可先設(shè)為10,此時(shí)左右整體速度為1*10=10個(gè)脈沖每秒,【加速度】和【減速度】均設(shè)為1000。隨后手動(dòng)運(yùn)動(dòng)軸,觀察軸是否運(yùn)動(dòng)及【反饋位置】是否有變化。
若手動(dòng)運(yùn)動(dòng)時(shí)【反饋位置】數(shù)據(jù)變化但實(shí)際軸未動(dòng),可逐步將【脈沖當(dāng)量】以10倍遞增,每次調(diào)整后反復(fù)手動(dòng)運(yùn)動(dòng),檢查軸是否運(yùn)動(dòng)。
【反饋位置】由編碼器反饋,若其數(shù)據(jù)變化,軸必定在運(yùn)動(dòng);若肉眼難以察覺(jué),可能是機(jī)臺(tái)運(yùn)動(dòng)較慢。

手動(dòng)運(yùn)動(dòng)和寸動(dòng)代碼如下:
//參數(shù)同步 zmcaux.ZAux_Direct_SetAtype(g_handle,axis[select_axis],int.Parse(atype_s[select_axis]));//設(shè)置軸類(lèi)型 zmcaux.ZAux_Direct_SetUnits(g_handle,axis[select_axis],units[select_axis]);//設(shè)置脈沖當(dāng)量 zmcaux.ZAux_Direct_SetAccel(g_handle,axis[select_axis],accel[select_axis]);//設(shè)置加速度 zmcaux.ZAux_Direct_SetDecel(g_handle,axis[select_axis],decel[select_axis]);//設(shè)置減速度 zmcaux.ZAux_Direct_SetSpeed(g_handle,axis[select_axis],speed[select_axis]);//設(shè)置運(yùn)行速度 zmcaux.ZAux_Direct_SetFsLimit(g_handle,axis[select_axis],Fslimit[select_axis]);//設(shè)置正向軟限位 zmcaux.ZAux_Direct_SetRsLimit(g_handle,axis[select_axis],Rslimit[select_axis]);//設(shè)置負(fù)向軟限位 zmcaux.ZAux_Direct_SetFastDec(g_handle,axis[select_axis],speed[select_axis]*accel[select_axis]);//設(shè)置快減減速度,達(dá)到限位或異常停止時(shí)自動(dòng)采用 Thread.Sleep(1); if(param?5)//左轉(zhuǎn) { ????zmcaux.ZAux_Direct_Single_MoveAbs(g_handle,?axis[select_axis],?Rslimit[select_axis]); } else?if?(5?<=?param?&&?param??9)//運(yùn)動(dòng) { ????if?(mode[select_axis])//絕對(duì)運(yùn)動(dòng) ????{ ????????zmcaux.ZAux_Direct_Single_MoveAbs(g_handle,?axis[select_axis],?move_dpos[select_axis]); ????} ????else?//相對(duì)運(yùn)動(dòng) ????{ ????????zmcaux.ZAux_Direct_Single_Move(g_handle,?axis[select_axis],?move_dpos[select_axis]); ????} }
三、在確保手動(dòng)運(yùn)動(dòng)正常且方向無(wú)誤的前提下,我們可以繼續(xù)測(cè)試軸的回零功能。
若未勾選【啟用控制器回零方式】,則默認(rèn)采用總線驅(qū)動(dòng)器回零(精度更高,推薦使用,驅(qū)動(dòng)器回零參考驅(qū)動(dòng)器手冊(cè))。
此時(shí),需參照總線驅(qū)動(dòng)器手冊(cè)中對(duì)回零模式的說(shuō)明,并將原點(diǎn)傳感器連接至驅(qū)動(dòng)器的原點(diǎn)輸入口。若勾選【啟用控制器回零方式】,則使用控制器回零,具體回零方式可參考下拉框中的介紹。
在實(shí)際項(xiàng)目中,仍建議優(yōu)先選擇總線驅(qū)動(dòng)器回零?;亓銣y(cè)試步驟如下:
1.選擇回零軸號(hào),配置軸的正限位信號(hào)、負(fù)限位信號(hào)及原點(diǎn)信號(hào)后,點(diǎn)擊【配置軸IO】。若軸狀態(tài)顯示“30h”,則勾選【反轉(zhuǎn)】,并再次點(diǎn)擊【配置軸IO】。
2.配置速度、爬行速度及回零模式后,點(diǎn)擊【啟動(dòng)回零】。若出現(xiàn)方向錯(cuò)誤或速度過(guò)快的情況,請(qǐng)立即點(diǎn)擊【緊急停止】,并重新進(jìn)行調(diào)試。

3.若軸狀態(tài)顯示“8h”,則表示驅(qū)動(dòng)器出現(xiàn)報(bào)錯(cuò)。以下是遇到驅(qū)動(dòng)器報(bào)警后的處理方法。

(1)檢查驅(qū)動(dòng)器上的LED面板是否顯示報(bào)錯(cuò)信息,報(bào)錯(cuò)時(shí)將呈現(xiàn)相應(yīng)的錯(cuò)誤碼。

常見(jiàn)的錯(cuò)誤,如驅(qū)動(dòng)器過(guò)載和轉(zhuǎn)矩飽和異常等,均可通過(guò)【清除報(bào)警】按鈕清除。

具體代碼如下:
intposition=3;//獲取第3位 intvalue=0; zmcaux.ZAux_BusCmd_DriveClear(g_handle,(uint)param,0);//清除總線伺服軸報(bào)警 Thread.Sleep(5000);//等待報(bào)警清除 zmcaux.ZAux_BusCmd_SDOReadAxis(g_handle,(uint)param,0x6041,0,6,refvalue);//讀取驅(qū)動(dòng)器狀態(tài)字對(duì)應(yīng)數(shù)據(jù)字典6041 if(((value>>position)&1)==0) { zmcaux.ZAux_Direct_Single_Datum(g_handle,param,0);//清除控制器報(bào)警 Thread.Sleep(100); zmcaux.ZAux_Direct_SetAxisEnable(g_handle,param,1);//重新上使能 MessageBox.Show("報(bào)警清除成功?。?!"); } else{MessageBox.Show("報(bào)警清除失敗,重新清除或查找報(bào)錯(cuò)原因?。?!");}
(2)如果通過(guò)代碼無(wú)法清除報(bào)警,絕大多數(shù)驅(qū)動(dòng)器報(bào)警問(wèn)題可以通過(guò)斷電并重啟驅(qū)動(dòng)器來(lái)解決。若斷電重啟后報(bào)警依然存在,則需參照驅(qū)動(dòng)器手冊(cè)進(jìn)行錯(cuò)誤排查,并可咨詢(xún)驅(qū)動(dòng)器技術(shù)人員以獲取解決方案。
教學(xué)視頻請(qǐng)點(diǎn)擊→PC強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制(一):C#的EtherCAT總線初始化(上)
完整代碼獲取地址
▼

本次,正運(yùn)動(dòng)技術(shù)PC強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制(一):C#的EtherCAT總線初始化(上),就分享到這里。
更多精彩內(nèi)容請(qǐng)關(guān)注“正運(yùn)動(dòng)小助手”公眾號(hào),需要相關(guān)開(kāi)發(fā)環(huán)境與例程代碼,請(qǐng)咨詢(xún)正運(yùn)動(dòng)技術(shù)銷(xiāo)售工程師:400-089-8936。

正運(yùn)動(dòng)技術(shù)專(zhuān)注于運(yùn)動(dòng)控制技術(shù)研究和通用運(yùn)動(dòng)控制軟硬件產(chǎn)品的研發(fā),是國(guó)家級(jí)高新技術(shù)企業(yè)。正運(yùn)動(dòng)技術(shù)匯集了來(lái)自華為、中興等公司的優(yōu)秀人才,在堅(jiān)持自主創(chuàng)新的同時(shí),積極聯(lián)合各大高校協(xié)同運(yùn)動(dòng)控制基礎(chǔ)技術(shù)的研究,是國(guó)內(nèi)工控領(lǐng)域發(fā)展最快的企業(yè)之一,也是國(guó)內(nèi)少有、完整掌握運(yùn)動(dòng)控制核心技術(shù)和實(shí)時(shí)工控軟件平臺(tái)技術(shù)的企業(yè)。主要業(yè)務(wù)有:運(yùn)動(dòng)控制卡_運(yùn)動(dòng)控制器_EtherCAT運(yùn)動(dòng)控制卡_EtherCAT控制器_運(yùn)動(dòng)控制系統(tǒng)_視覺(jué)控制器__運(yùn)動(dòng)控制PLC_運(yùn)動(dòng)控制_機(jī)器人控制器_視覺(jué)定位_XPCIe/XPCI系列運(yùn)動(dòng)控制卡等等。
審核編輯 黃宇
-
總線
+關(guān)注
關(guān)注
10文章
3061瀏覽量
91903 -
運(yùn)動(dòng)控制
+關(guān)注
關(guān)注
5文章
840瀏覽量
34687 -
ethercat
+關(guān)注
關(guān)注
20文章
1582瀏覽量
46267
發(fā)布評(píng)論請(qǐng)先 登錄
【正運(yùn)動(dòng)】高速高精,超高實(shí)時(shí)性的PCIe EtherCAT實(shí)時(shí)運(yùn)動(dòng)控制卡 | PCIE464
EtherCAT超高速實(shí)時(shí)運(yùn)動(dòng)控制卡XPCIE1032H上位機(jī)C#開(kāi)發(fā)(二):EtherCAT總線初始化
EtherCAT運(yùn)動(dòng)控制卡之ECI2820如何使用
EtherCAT總線運(yùn)動(dòng)控制的優(yōu)勢(shì)主要體現(xiàn)在哪?
經(jīng)濟(jì)型EtherCAT運(yùn)動(dòng)控制器:EtherCAT總線快速入門(mén)
EtherCAT總線運(yùn)動(dòng)控制的優(yōu)勢(shì)主要體現(xiàn)在哪?
Windows實(shí)時(shí)運(yùn)動(dòng)控制軟核(一):LOCAL高速接口測(cè)試之C#
EtherCAT運(yùn)動(dòng)控制卡的硬件接線與C#的硬件外設(shè)讀寫(xiě)與回零運(yùn)動(dòng)
EtherCAT運(yùn)動(dòng)控制卡的硬件接線與C#的單軸運(yùn)動(dòng)控制
EtherCAT超高速實(shí)時(shí)運(yùn)動(dòng)控制卡XPCIE1032H上位機(jī)C#開(kāi)發(fā)(二):EtherCAT總線初始化
EtherCAT超高速實(shí)時(shí)運(yùn)動(dòng)控制卡(二):EtherCAT總線初始化
強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制內(nèi)核MotionRT750(一):驅(qū)動(dòng)安裝、內(nèi)核配置與使用
EtherCAT總線初始化步驟
PC強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制(一):C#的EtherCAT總線初始化(下)
PC強(qiáng)實(shí)時(shí)運(yùn)動(dòng)控制(一):C#的EtherCAT總線初始化(上)
評(píng)論