我們的套件在使用 EtherCAT 控制電機(jī)時(shí),采用了 CANopen 應(yīng)用層協(xié)議中的 CiA402 規(guī)范。為了更好地理解 CiA402 的工作原理,我們先簡(jiǎn)要回顧一下 CANopen 協(xié)議。CANopen 是一個(gè)基于 CAN 協(xié)議的通信協(xié)議,廣泛應(yīng)用于工業(yè)自動(dòng)化領(lǐng)域。PDO(過(guò)程數(shù)據(jù)對(duì)象)和 SDO(服務(wù)數(shù)據(jù)對(duì)象)是 CANopen 協(xié)議中的核心概念,用于在網(wǎng)絡(luò)節(jié)點(diǎn)之間傳輸數(shù)據(jù)和提供服務(wù)。
在 CANopen 協(xié)議中,每個(gè)節(jié)點(diǎn)都維護(hù)一個(gè)稱為對(duì)象字典(Object Dictionary,OD)的數(shù)據(jù)結(jié)構(gòu)。對(duì)象字典是節(jié)點(diǎn)信息的中央倉(cāng)庫(kù),包含了節(jié)點(diǎn)的配置信息、通信參數(shù)以及過(guò)程數(shù)據(jù)(PDO)等。上層應(yīng)用通過(guò)與對(duì)象字典的交互來(lái)實(shí)現(xiàn)通信和控制。PDO 特別適合快速的數(shù)據(jù)處理與傳輸,因?yàn)樗鼈儽辉O(shè)計(jì)為直接映射到 CAN 幀,從而減少了處理時(shí)間和網(wǎng)絡(luò)延遲。
在對(duì)象字典中,PDO 是由多個(gè)條目(Entry)構(gòu)成的,每個(gè)條目都通過(guò)特定的索引(Index)、子索引(Subindex)和位數(shù)(Bit Length)來(lái)定義其數(shù)據(jù)源和屬性。這種結(jié)構(gòu)化的組織方式使得 PDO 的配置和管理變得簡(jiǎn)單而高效。
現(xiàn)在,我們回到 EtherCAT 和 CoE(CAN over EtherCAT)的話題。EtherCAT 是一種高性能的工業(yè)以太網(wǎng)協(xié)議,用于實(shí)時(shí)數(shù)據(jù)交換和分布式控制。CoE 是 EtherCAT 中用于支持 CANopen 協(xié)議的一個(gè)子協(xié)議,它允許 EtherCAT 網(wǎng)絡(luò)中的節(jié)點(diǎn)使用 CANopen 的對(duì)象字典和通信機(jī)制。
在套件實(shí)現(xiàn)中,我們可以看到對(duì) CiA402 的支持。CiA402 是一個(gè)針對(duì)驅(qū)動(dòng)器和運(yùn)動(dòng)控制器的 CANopen 應(yīng)用層規(guī)范。在源代碼中,如?CiA402appl.c?文件中的?UINT16 CiA402_Init(void)?函數(shù),就包含了與 CiA402 相關(guān)的初始化代碼。這部分代碼負(fù)責(zé)設(shè)置和配置與 CiA402 相關(guān)的對(duì)象字典條目、PDO 映射等,以支持特定的電機(jī)控制功能。
通過(guò)深入分析這些代碼,我們可以更深入地理解 CiA402 在 EtherCAT 控制系統(tǒng)中的應(yīng)用和實(shí)現(xiàn)方式。
CiA402_Init(void)?函數(shù)如下所示:
//聲明并初始化對(duì)象字典
LocalAxes[AxisCnt].ObjDic?=?(TOBJECT?*)?LLOCMEM(SIZEOF(DefCiA402AxisObjDic));
HMEMCPY(LocalAxes[AxisCnt].ObjDic,&DefCiA402AxisObjDic,SIZEOF(DefCiA402AxisObjDic));
{
TOBJECT?OBJMEM *pDiCEntry?=?LocalAxes[AxisCnt].ObjDic;
/*初始化每一個(gè)條目,表示其指向哪一個(gè)變量*/
while(pDiCEntry->Index?!=?0xFFFF)
{
BOOL bObjectFound?=?TRUE;
?
switch(pDiCEntry->Index)
{
case?0x1600://PDO映射方式1(CSV/CSP)
pDiCEntry->pVarPtr?=?&LocalAxes[AxisCnt].Objects.sRxPDOMap0;
break;
case?0x1601://PDO映射方式2(CSP)
pDiCEntry->pVarPtr?=?&LocalAxes[AxisCnt].Objects.sRxPDOMap1;
break;
case?0x1602://PDO映射方式3(CSV)
pDiCEntry->pVarPtr?=?&LocalAxes[AxisCnt].Objects.sRxPDOMap2;
break;
... ... ...
case?0x6064:
pDiCEntry->pVarPtr?=?&LocalAxes[AxisCnt].Objects.objPositionActualValue;
break;
... ... ...
default?:
bObjectFound?=?FALSE;
break;
}
可以看到這段代碼初始化了幾個(gè)對(duì)象字典(AxisCnt),每個(gè)電機(jī)軸都對(duì)應(yīng)一個(gè)對(duì)象字典(Object Dictionary),用于存儲(chǔ)和管理該軸的狀態(tài)、參數(shù)和實(shí)時(shí)數(shù)據(jù)。這些對(duì)象字典條目通過(guò)特定的索引和子索引進(jìn)行唯一標(biāo)識(shí),并被初始化以指向?qū)嶋H的變量或數(shù)據(jù)結(jié)構(gòu)。并且對(duì)對(duì)象字典中每一個(gè)條目進(jìn)行了初始化,使其指向一個(gè)實(shí)際的變量。目前例程中并不是所有條目都有用到,我們看一個(gè)實(shí)際用到的條目:
case?0x6064:
pDiCEntry->pVarPtr?=?&LocalAxes[AxisCnt].Objects.objPositionActualValue;
break;
索引0x6064的條目通常用于存儲(chǔ)電機(jī)的實(shí)際位置值。在初始化過(guò)程中,該條目會(huì)被關(guān)聯(lián)到LocalAxes[AxisCnt].Objects.objPositionActualValue這個(gè)變量上,從而實(shí)現(xiàn)了實(shí)際變量與對(duì)象字典條目的關(guān)聯(lián)。
為了通過(guò)網(wǎng)絡(luò)傳輸這些變量,我們需要用到PDO,為了實(shí)現(xiàn)PDO傳輸,我們需要將PDO與對(duì)象字典條目進(jìn)行關(guān)聯(lián)或映射。
在對(duì)象字典的前幾個(gè)條目中,0x1600、0x1601、0x1602等通常用于定義RxPDO(接收過(guò)程數(shù)據(jù)對(duì)象)的映射方式,而0x1A00、0x1A01、0x1A02等則用于定義TxPDO(發(fā)送過(guò)程數(shù)據(jù)對(duì)象)的映射方式。這些映射方式對(duì)應(yīng)于電機(jī)的不同工作模式,如CSV/CSP、CSV和CSP等。需要注意的是,這三種映射方式中,通常只有一種會(huì)被激活使用,以適應(yīng)當(dāng)前的工作模式。
在CiA402_Init(void)函數(shù)的開(kāi)始部分,通過(guò)以下代碼:
HMEMCPY(&LocalAxes[AxisCnt].Objects,&DefCiA402ObjectValues,CIA402_OBJECTS_SIZE);
每個(gè)電機(jī)軸的對(duì)象字典和PDO映射都會(huì)被初始化為預(yù)定義的默認(rèn)值,這些默認(rèn)值存儲(chǔ)在DefCiA402ObjectValues這個(gè)變量中。以case 0x1601為例,其具體內(nèi)容為:{3, {0x60400010,0x607A0020,0x00000010 }}, /*TOBJ1601*/
這里,3表示PDO映射包含三個(gè)條目。接下來(lái)的三個(gè)對(duì)(索引和大?。┒x了PDO中應(yīng)包含的數(shù)據(jù):
- 0x6040?和?0x0010?表示從對(duì)象字典索引0x6040開(kāi)始,傳輸16位(0x10)的數(shù)據(jù)。
- 0x607A?和?0x0020?表示從對(duì)象字典索引0x607A開(kāi)始,傳輸32位(0x20)的數(shù)據(jù)。
- 最后一個(gè)對(duì)用于填充對(duì)齊。
表示0x1601這種映射方式下RxPDO映射到0x6064以及0x607A條目的內(nèi)容。
另外我們?cè)訇P(guān)注一下UINT16 CiA402_Init(void)函數(shù)中下面這段代碼
/*increment object index*/
if?(pDiCEntry->Index?>=?0x1400?&&?pDiCEntry->Index?<=?0x1BFF)?//PDO region
{
pDiCEntry->Index?+=?AxisCnt*?PDOOffset;
}
else
{
pDiCEntry->Index?+=?AxisCnt*?(UINT16)ObjectOffset;
}
因?yàn)槲覀冎肋@個(gè)從站可以同時(shí)控制最多四個(gè)電機(jī),因此不同電機(jī)之間對(duì)象字典索引是不能一樣的,這段代碼就是使得每個(gè)電機(jī)的對(duì)象字典索引有一個(gè)偏移量從而進(jìn)行區(qū)分。
通過(guò)以上代碼我們可以確定從站設(shè)備的配置中,存在三種PDO(過(guò)程數(shù)據(jù)對(duì)象)映射方式,這些映射方式對(duì)應(yīng)于不同的操作模式或數(shù)據(jù)傳輸需求。然而,在任何給定的時(shí)間,從站只會(huì)使用其中的一種映射方式來(lái)傳輸數(shù)據(jù)。
ApplicationObjDic字典是一個(gè)包含應(yīng)用層相關(guān)參數(shù)的對(duì)象字典。在這個(gè)字典中,條目0x1C12和0x1C13(或類(lèi)似的索引)通常用于存儲(chǔ)RxPDO(接收PDO)和TxPDO(發(fā)送PDO)的映射配置信息。這兩個(gè)變量,即sRxPDOassign和sTxPDOassign,定義了從站應(yīng)該接收和發(fā)送哪些數(shù)據(jù),以及這些數(shù)據(jù)在PDO中的布局。
我們?cè)倏匆幌潞瘮?shù)void APPL_OutputMapping(UINT16* pData)和void APPL_InputMapping(UINT16* pData),這兩個(gè)函數(shù)用于處理PDO數(shù)據(jù)的映射。在這些函數(shù)中,switch語(yǔ)句用于根據(jù)sTxPDOassign.aEntries[j]或sRxPDOassign.aEntries[j]的某個(gè)部分(通常是低四位,通過(guò)& 0x000F得到)來(lái)決定當(dāng)前處理的是哪種PDO映射。
通過(guò)修改ApplicationObjDic字典中的0x1C12和0x1C13條目(即sRxPDOassign和sTxPDOassign變量),開(kāi)發(fā)人員可以動(dòng)態(tài)地調(diào)整RxPDO和TxPDO的數(shù)據(jù)內(nèi)容。這允許在運(yùn)行時(shí)更改數(shù)據(jù)傳輸?shù)母袷胶皖?lèi)型,以適應(yīng)不同的操作模式或應(yīng)用需求。
在TwinCAT主站軟件中,這些修改通常是在工程文件的相應(yīng)配置頁(yè)面(如Slots標(biāo)簽頁(yè))中進(jìn)行的(目前從站只支持CSP模式)。
?
我們看一下下圖標(biāo)簽頁(yè)Startup里面的內(nèi)容也會(huì)隨之改變。
其中前兩條剛好是修改0x1C12和0x1C13的內(nèi)容,完成這些修改后,相關(guān)的配置變化會(huì)在從站狀態(tài)機(jī)從Pre-Operational(預(yù)操作)狀態(tài)轉(zhuǎn)換到Safe-Operational(安全操作)狀態(tài)時(shí)生效。這個(gè)通信過(guò)程通常是通過(guò)EtherCAT郵箱機(jī)制(SDO,服務(wù)數(shù)據(jù)對(duì)象)進(jìn)行的。
具體到從站代碼層面,當(dāng)主站通過(guò)SDO郵箱機(jī)制發(fā)送新的PDO映射配置時(shí),從站會(huì)接收到這些配置數(shù)據(jù),并在UINT8 SDOS_SdoInd(TINITSDOMBX MBXMEM *pSdoInd)這樣的函數(shù)中處理這些數(shù)據(jù)。這個(gè)函數(shù)負(fù)責(zé)解析主站發(fā)送的SDO請(qǐng)求,并根據(jù)請(qǐng)求的內(nèi)容更新從站內(nèi)部的對(duì)象字典(如0x1C12和0x1C13條目),從而修改RxPDO和TxPDO的映射配置。
一旦這些配置更新完成,從站的過(guò)程數(shù)據(jù)(PDOs)就會(huì)根據(jù)新的映射配置進(jìn)行傳輸,從而可能改變從站的工作模式或數(shù)據(jù)傳輸格式。這個(gè)過(guò)程允許開(kāi)發(fā)者在運(yùn)行時(shí)動(dòng)態(tài)地調(diào)整從站的行為,以適應(yīng)不同的應(yīng)用需求或操作場(chǎng)景。
總結(jié)來(lái)說(shuō),通過(guò)TwinCAT主站軟件修改PDO映射配置,并利用EtherCAT的SDO郵箱機(jī)制將這些配置下發(fā)到從站,可以實(shí)現(xiàn)從站過(guò)程數(shù)據(jù)的動(dòng)態(tài)修改和工作模式的靈活調(diào)整。
到這里,對(duì)象字典初始化以及配置都完成,主站就可以通過(guò)過(guò)程數(shù)據(jù)對(duì)從站進(jìn)行控制了
。我們以一個(gè)電機(jī)為例,在TwinCAT中可以看到實(shí)際使用的過(guò)程數(shù)據(jù),如下圖所示:
0x6041表示Status Word,0x6064表示ActualPosition,這兩個(gè)數(shù)據(jù)傳輸方向?yàn)閺臋C(jī)到主站,0x6040表示Control Word,0x607A表示TargetPosition,這兩個(gè)數(shù)據(jù)傳輸方向?yàn)橹髡镜綇恼尽?/p>
主站與從站的通信接口已經(jīng)配置完成了,為了實(shí)現(xiàn)CiA 402規(guī)范定義的電機(jī)控制,從站必須運(yùn)行一個(gè)狀態(tài)機(jī)來(lái)管理其操作狀態(tài)和響應(yīng)主站的控制命令。這個(gè)狀態(tài)機(jī)定義了從站在不同階段的操作能力和狀態(tài),以便主站可以根據(jù)這些狀態(tài)來(lái)發(fā)送適當(dāng)?shù)目刂泼睢恼局饕ㄟ^(guò)函數(shù)CiA402_StateMachine()實(shí)現(xiàn)CiA402的狀態(tài)轉(zhuǎn)換,包含以下幾個(gè)狀態(tài):
#define?STATE_NOT_READY_TO_SWITCH_ON?0x0001 /**< brief Not ready to switch on (optional)*/
#define?STATE_SWITCH_ON_DISABLED?0x0002 /**< brief Switch on but disabled (optional)*/
#define?STATE_READY_TO_SWITCH_ON?0x0004 /**< brief Ready to switch on (mandatory)*/
#define?STATE_SWITCHED_ON?0x0008 /**< brief Switch on (mandatory)*/
#define?STATE_OPERATION_ENABLED?0x0010 /**< brief Operation enabled (mandatory)*/
#define?STATE_QUICK_STOP_ACTIVE?0x0020 /**< brief Quick stop active (optional)*/
#define?STATE_FAULT_REACTION_ACTIVE?0x0040 /**< brief Fault reaction active (mandatory)*/
#define?STATE_FAULT?0x0080 /**< brief Fault state (mandatory)*/
與此同時(shí),主機(jī)通過(guò)讀取從機(jī)的Status Word(索引0x6041)來(lái)了解從機(jī)的當(dāng)前狀態(tài)。盡管Status Word的某些位可能與狀態(tài)機(jī)的狀態(tài)相對(duì)應(yīng),但兩者并不完全相同。Status Word提供了關(guān)于從機(jī)當(dāng)前狀態(tài)和可能發(fā)生的故障或警告的詳細(xì)信息。,Status Word各bit含義如下:
主機(jī)通過(guò)Control Word(索引0x6040)向從機(jī)發(fā)送控制命令,以改變其操作狀態(tài)或觸發(fā)特定的動(dòng)作。Control Word的各個(gè)位定義了不同的控制命令??刂谱諧ontrol Word 各bit含義如下:
在IGH主站控制從站CiA 402狀態(tài)機(jī)的一個(gè)例程中,函數(shù)axis_start根據(jù)從機(jī)的當(dāng)前狀態(tài)(通過(guò)status參數(shù)傳入)和所需的工作模式(mode參數(shù))來(lái)決定發(fā)送何種Control Word:
static?int?axis_start(nser_axle *ns_axis,?uint16_t status,?uint8_t mode)?{
int?ret?=?0;
axle_state s?=?get_axle_state(status);
if?(status?&?0x8)?{
nser_pdo_set_Controlword(ns_axis,?0x80);
return?0;
}
switch?(s)?{
case?(no_ready_to_switch_on):
case?(switch_on_disable):
nser_pdo_set_Controlword(ns_axis,?contrlword_shutdown(0));
break;
case?(ready_to_switch_on):
nser_pdo_set_Controlword(ns_axis,?contrlword_switch_on(0));
break;
case?(switched_on):
nser_pdo_set_Controlword(ns_axis,?contrlword_enable_operation(0));
nser_pdo_set_Modes_of_operation(ns_axis,?mode);
break;
case?(operation_enable):
ret?=?1;
break;
case?(quick_stop_active):
case?(fault_reaction_active):
case?(fault):
default:
ret?=?-1;
}
return?ret;
}
在CiA 402協(xié)議中,當(dāng)從站成功達(dá)到STATE_OPERATION_ENABLED狀態(tài)后,這標(biāo)志著從站已準(zhǔn)備好接收并執(zhí)行來(lái)自主站的控制命令。此時(shí),主站可以開(kāi)始通過(guò)發(fā)送TargetPosition(索引0x607A)來(lái)指定從站電機(jī)的目標(biāo)位置,并可以通過(guò)讀取ActualPosition(索引0x6064)來(lái)監(jiān)控電機(jī)的實(shí)時(shí)位置。
?
?