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