硬汉嵌入式论坛

 找回密码
 立即注册
查看: 192|回复: 4
收起左侧

[有问必答] 求助EtherCat问题

[复制链接]

1

主题

5

回帖

8

积分

新手上路

积分
8
QQ
发表于 2025-4-16 11:51:15 | 显示全部楼层 |阅读模式
目前研究EtherCat中,采用407 +  国产化ESC, 想询问PDO的动态配置问题,目前项目PDO数据索引长度可能会随时变更,这又涉及更新XML文件,繁琐。想问问一般有什么解决方案?翻了下说明,ETG5001的MDP扩展似乎可以实现在PRO_OP中配置SLOT来控制PDO的交互,因没有会员,资料不全,在此求相关资料。关于MDP的实现仅需要在OD中修改即可嘛?目前使用SSC TOOL,有相关参考嘛?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-4-17 09:46:12 | 显示全部楼层
帮顶。
回复

使用道具 举报

0

主题

15

回帖

15

积分

新手上路

积分
15
发表于 2025-4-17 14:25:56 | 显示全部楼层
本帖最后由 cking616 于 2025-4-17 14:55 编辑

1. 修改 PDO 配置寄存器属性, 将 SDO 1600~1A00 的 PDO 配置寄存器属性修改为 "wr"(可读写)模式。
2. XML 配置文件设置, 确保以下配置参数正确设置:
[XML] 纯文本查看 复制代码
  
   <Mailbox DataLinkLayer="true">
       <CoE SdoInfo="true" PdoAssign="false" PdoConfig="true" CompleteAccess="true" SegmentedSdo="true" />
       <FoE />
   </Mailbox>
   
   <RxPdo Fixed="false" Mandatory="true" Sm="2">
   <TxPdo Fixed="false" Mandatory="true" Sm="3">

注意 `PdoConfig="true"` 必须设为 true,  RxPdo`和 TxPdo`的 Fixed`属性必须设为 false

3. 实现代码上, Ethercat接口函数generateMap、Input、Output这几个函数重新实现,正确从SDO配置中提取PDO变量指针和大小,示例代码:
[C] 纯文本查看 复制代码
// 位操作辅助宏
#define GET_INDEX(val) (((val) & 0xFFFF0000) >> 16)
#define GET_SUBINDEX(val) (((val) & 0xFF00) >> 8)
#define GET_BITSIZE(val) ((val) & 0xFF)
#define BITS_TO_BYTES(bits) ((bits) >> 3)

uint16_t axisCtrlEcatMapGenerate(axisDataT *axisEcat,
                              uint16_t *pInputSize,
                              uint16_t *pOutputSize) {
    uint16_t result = ALSTATUSCODE_NOERROR;
    TOBJ1A00 *txpdoPtr = &axisEcat->txpdoTable;    // 发送PDO表指针
    TOBJ1600 *rxpdoPtr = &axisEcat->rxpdoTable;    // 接收PDO表指针
    uint16_t inputSize = 0, outputSize = 0;
    uint32_t objIndex, objSubindex;
    uint16_t size;
    uint8_t *pVarPtr;
    int i;

    // 限制RxPDO数量
    if (rxpdoPtr->u16SubIndex0 > MAX_RX_PDO)
        rxpdoPtr->u16SubIndex0 = MAX_RX_PDO;

    // 处理RxPDO映射
    for (i = 0; i < rxpdoPtr->u16SubIndex0; i++) {
        objIndex = GET_INDEX(rxpdoPtr->SI[i]);
        objSubindex = GET_SUBINDEX(rxpdoPtr->SI[i]);
        size = BITS_TO_BYTES(GET_BITSIZE(rxpdoPtr->SI[i]));

        // 获取对象变量指针,失败则设为0
        axisEcat->rxPdoVarPtr[i] = (getObjectVariable(objIndex, objSubindex, &pVarPtr) == 0) ? pVarPtr : 0;
        axisEcat->rxPdoSize[i] = size;
        outputSize += GET_BITSIZE(rxpdoPtr->SI[i]);
    }

    axisEcat->numOfRxPdo = rxpdoPtr->u16SubIndex0;
    outputSize = BITS_TO_BYTES(outputSize);  // 比特转字节

    // 限制TxPDO数量
    if (txpdoPtr->u16SubIndex0 > MAX_TX_PDO)
        txpdoPtr->u16SubIndex0 = MAX_TX_PDO;

    // 处理TxPDO映射
    for (i = 0; i < txpdoPtr->u16SubIndex0; i++) {
        objIndex = GET_INDEX(txpdoPtr->SI[i]);
        objSubindex = GET_SUBINDEX(txpdoPtr->SI[i]);
        size = BITS_TO_BYTES(GET_BITSIZE(txpdoPtr->SI[i]));

        // 获取对象变量指针,失败则设为0
        axisEcat->txPdoVarPtr[i] = (getObjectVariable(objIndex, objSubindex, &pVarPtr) == 0) ? pVarPtr : 0;
        axisEcat->txPdoSize[i] = size;
        inputSize += GET_BITSIZE(txpdoPtr->SI[i]);
    }

    axisEcat->numOfTxPdo = txpdoPtr->u16SubIndex0;
    inputSize = BITS_TO_BYTES(inputSize);  // 比特转字节

    // 更新总大小
    *pInputSize += inputSize;
    *pOutputSize += outputSize;

    return result;
}

uint32_t axisCtrlEcatOutput(axisDataT *axisEcat, uint8_t *pData) {
    uint32_t size = 0;

    // 复制接收PDO数据到目标变量
    for (int i = 0; i < axisEcat->numOfRxPdo; i++) {
        if (axisEcat->rxPdoVarPtr[i]) {  // 非空指针检查
            memcpy(axisEcat->rxPdoVarPtr[i], pData, axisEcat->rxPdoSize[i]);
        }
        pData += axisEcat->rxPdoSize[i];
        size += axisEcat->rxPdoSize[i];
    }

    return size;
}

uint32_t axisCtrlEcatInput(axisDataT *axisEcat, uint8_t *pData) {
    uint32_t size = 0;

    // 复制来源变量数据到发送PDO
    for (int i = 0; i < axisEcat->numOfTxPdo; i++) {
        if (axisEcat->txPdoVarPtr[i]) {  // 非空指针检查
            memcpy(pData, axisEcat->txPdoVarPtr[i], axisEcat->txPdoSize[i]);
        }
        pData += axisEcat->txPdoSize[i];
        size += axisEcat->txPdoSize[i];
    }

    return size;

}
[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]


关于 PDO 配置的存储,您可以选择以下几种方式:
1. 使用 SSC Tool 的存储功能并实现相应接口
2. 将 SDO 1600~1A00 对应的 SDO 配置保存,并在设备上电时载入





回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
QQ
 楼主| 发表于 2025-4-17 15:56:25 | 显示全部楼层
cking616 发表于 2025-4-17 14:25
1. 修改 PDO 配置寄存器属性, 将 SDO 1600~1A00 的 PDO 配置寄存器属性修改为 "wr"(可读写)模式。
2.  ...

感谢大哥回答,SDO配置PDO参数可以实现效果,但XML文件PDO部分也要条目更改这是没想到的。因目主机用的是TwinCat,源码采用的是SSC Tool V1.3版本生成,源码中从ProOp->SafeOp时会校验SM2中PDO的参数,不符则初始化失败。我想在XML文件稳定,后续针对PDO的动态修改的同时直接更新SM2寄存器的内容,原则上可以实现,但不知道是否符合规范?有什么要注意的嘛?


//附现底层源码,校验部分
if (result == 0 && maxChannel > PROCESS_DATA_OUT)
    {
        /* check the Sync Manager Parameter for the Outputs (Sync Manager Channel 2) */
        pSyncMan = GetSyncMan(PROCESS_DATA_OUT);    //SM2REG

    SMLength = pSyncMan->Length;
    SMAddress = pSyncMan->hysicalStartAddress;



    if ((pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE) != 0 && SMLength == 0)
    {
        /* the SM2 size is 0 and the SM2 is active */
        result = SYNCMANCHSETTINGS + 1;
    }
        else if (pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE)
        { //与PDO实际长度校验对比
            /* Sync Manager Channel 2 is active, output size has to greater 0 */
            if ( SMLength == nPdOutputSize && nPdOutputSize != 0 && SMLength <= ((UINT16)MAX_PD_OUTPUT_SIZE))
            {
                /* sizes match */
                if ( (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_DIRECTION_MASK) == SM_SETTING_DIRECTION_WRITE_VALUE )
                {
                    /* settings match */
                    if ( ( ( nAlStatus == STATE_PREOP )&&( SMAddress >= MIN_PD_WRITE_ADDRESS )&&( SMAddress <= MAX_PD_WRITE_ADDRESS ) )
                       ||( ( nAlStatus != STATE_PREOP )&&( SMAddress == nEscAddrOutputData ) )
                        )
                    {
                        /* addresses match */
                        {
                            /* check, if watchdog trigger is enabled */
                            if (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_WATCHDOG_VALUE)
                            {
                                bWdTrigger = TRUE;
                            }
                            else
                            {
                                bWdTrigger = FALSE;
                            }

                            if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_MASK) == SM_SETTING_MODE_ONE_BUFFER_VALUE)
                            {
                                /* outputs are running in 1-Buffer-Mode, reset flag b3BufferMode */
                                b3BufferMode = FALSE;
                                }
                        }
                    }
                    else
                    {
                        /* output address is out of the allowed area or has changed in SAFEOP or OP */
                        result = SYNCMANCHADDRESS + 1;
                    }
                }
                else
                {
                    /* output settings do not match */
                    result = SYNCMANCHSETTINGS + 1;
                }
            }
            else
            {
                /* output sizes don't match */
                result = SYNCMANCHSIZE + 1;
            }
        }
        else if (SMLength != 0 || nPdOutputSize != 0)
        {
            /* output size is not zero although the SM2 channel is not enabled */
            result = SYNCMANCHSIZE + 1;
        }
回复

使用道具 举报

1

主题

5

回帖

8

积分

新手上路

积分
8
QQ
 楼主| 发表于 2025-4-17 17:36:06 | 显示全部楼层
xrswnw 发表于 2025-4-17 15:56
感谢大哥回答,SDO配置PDO参数可以实现效果,但XML文件PDO部分也要条目更改这是没想到的。因目主机用 ...

尝试了下,PDI对SM的操作此部分RO,也就是目前阶段此源码,SDO修改PDO后,SM会校验失败,非必要不改底层再考虑其它办法。尝试接入5001ETG MDP方案,资料过少且无参考的情况下不一定成功。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-25 20:45 , Processed in 0.244093 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表