使用soem配置汇川sv660n伺服无法从安全运行状态转到运行状态。

W10平台;SOEM V1.4.0;
想要实现使用SOEM来驱动汇川sv660n伺服,但根据返回的信息来看,伺服无法从安全运行状态转到运行状态。
这是PDO配置:

int Servosetup(uint16 slave)
{
    //int retval=0;
    uint8 u8val;
    uint16 u16val;
    uint32 u32val;
    printf("成功调用servosetup函数\n");
    u8val = 0;
    ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//清除0x1c12数据
    u8val = 0;
    ec_SDOwrite(slave, 0x1600, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//清除0x1600数据

    u16val = 0x1600;
    ec_SDOwrite(slave, 0x1c12, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM);//设定为所选的PDO映像配置
    u32val = 0x60400010;
    ec_SDOwrite(slave, 0x1600, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);//增加0x1600子索引
    u32val = 0x607A0020;
    ec_SDOwrite(slave, 0x1600, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);//增加0x1600子索引
    u8val = 2;
    ec_SDOwrite(slave, 0x1600, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//设定为PDO映射中的映射数

    u8val = 1;
    ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//启用PDO配置

    /**********************************************************************************************************/
    u8val = 0;
    ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//清除0x1c13数据
    u8val = 0;
    ec_SDOwrite(slave, 0x1A00, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//清除0x1A00数据

    u16val = 0x1A00;
    ec_SDOwrite(slave, 0x1c13, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM);//设定为所选的PDO映像配置
    u32val = 0x60410010;
    ec_SDOwrite(slave, 0x1A00, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);
    u32val = 0x60640020;
    ec_SDOwrite(slave, 0x1A00, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);
    u8val = 2;
    ec_SDOwrite(slave, 0x1A00, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//设定为PDO映射中的映射数

    u8val = 1;
    ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);//启用PDO配置

    while (EcatError) printf("%s", ec_elist2string());
    return 1;
}

状态转换:

void simpletest(char* ifname)
{
    int i, j, oloop, iloop, wkc_count, cnt, chk, slc;
    UINT mmResult;
    //uint8 u8val;
    //uint16 c;
    needlf = FALSE;
    inOP = FALSE;

    printf("Starting simple test\n");

    /* initialise SOEM, bind socket to ifname */
    if (ec_init(ifname))
    {
        printf("ec_init on %s succeeded.\n", ifname);
        /* find and auto-config slaves */
        if (ec_config_init(FALSE) > 0)
        {
            printf("%d slaves found and configured.\n", ec_slavecount);
            
            
            if ((ec_slavecount > 1))
            {
                for (slc = 1; slc <= ec_slavecount; slc++)
                {

                    printf("try to link Servosetup\n");
                    //if ((ec_slave[slc].eep_man == 0x0001048576) && (ec_slave[slc].eep_id == 0x0000786701))
                    //{
                        printf("Found %s at position %d\n", ec_slave[slc].name, slc);
                        //u8val = 8;
                        //ec_SDOwrite(slc, 0x6060, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);
                        ec_slave[slc].PO2SOconfig = &Servosetup;
                        //ec_slave[slc].PO2SOconfig = &AEPsetup;
                        // link slave specific setup to preop->safeop hook
                    //}
                }
            }
        
            printf("eep_man:%i\n",ec_slave[1].eep_man);
            printf("eep_id:%i\n",ec_slave[1].eep_id);
            //printf("slave:%i\n", ec_ODlistt.slave);
        //process_data_config();
        printf("config map\n");
        ec_config_map(&IOmap);

        printf("configdc\n");
        ec_configdc();
        //int k = sizeof(1);
        //ec_SDOread(1, 0x1600, 0x01, FALSE, k, &1, EC_TIMEOUTRXM);
        //c = sizeof(1);
        //SDO2string(0, 0x1600, 0x01, c);
        ec_dcsync0(1, TRUE, 10000000, 3000);
        ec_dcsync0(2, TRUE, 10000000, 3000);
        printf("Slaves mapped, state to SAFE_OP.\n");

        /* wait for all slaves to reach SAFE_OP state */
        ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);
        printf("Slave 1 State=0x%04x\r\n", ec_slave[1].state);//cln add
        printf("Slave 2 State=0x%04x\r\n", ec_slave[2].state);//cln add
        do
        {
            ec_statecheck(1, EC_STATE_SAFE_OP, 50000);
            ec_statecheck(2, EC_STATE_SAFE_OP, 50000);
        } while ((ec_slave[1].state != EC_STATE_SAFE_OP) || (ec_slave[2].state != EC_STATE_SAFE_OP));
        printf("Slave 1 State=0x%04x\r\n", ec_slave[1].state);//cln add
        printf("Slave 2 State=0x%04x\r\n", ec_slave[2].state);//cln add
        


        oloop = ec_slave[0].Obytes;
        if ((oloop == 0) && (ec_slave[0].Obits > 0)) oloop = 1;
        if (oloop > 8) oloop = 8;
        iloop = ec_slave[0].Ibytes;
        if ((iloop == 0) && (ec_slave[0].Ibits > 0)) iloop = 1;
        if (iloop > 8) iloop = 8;


        printf("segments : %d : %d %d %d %d\n", ec_group[0].nsegments, ec_group[0].IOsegment[0], ec_group[0].IOsegment[1], ec_group[0].IOsegment[2], ec_group[0].IOsegment[3]);

        printf("Request operational state for all slaves\n");
        expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
        printf("%d %d\n", ec_group[0].outputsWKC, ec_group[0].inputsWKC);
        printf("Calculated workcounter %d\n", expectedWKC);
        ec_slave[1].state = EC_STATE_OPERATIONAL;
        ec_slave[2].state = EC_STATE_OPERATIONAL;

        /* send one valid process data to make outputs in slaves happy*/
        ec_send_processdata();
        //printf("send_wkc:%d\n", wkc);
        wkc=ec_receive_processdata(EC_TIMEOUTRET);
        //printf("receive_wkc:%d\n", wkc);

        /* start RT thread as periodic MM timer */
        //mmResult = timeSetEvent(1, 0, RTthread, 0, TIME_PERIODIC);
        if (wkc == expectedWKC)
        {
            printf("wkc计数符合预期\n");
        }
        //printf("configindex:", ec_slave.configindex);
        /* request OP state for all slaves */
        ec_writestate(0);
        mmResult = timeSetEvent(1, 0, RTthread, 0, TIME_PERIODIC);
        chk = 40;
        /* wait for all slaves to reach OP state */

        do
        {
            ec_statecheck(0, EC_STATE_OPERATIONAL, 50000);
        } while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));


        for (cnt = 1; cnt <= ec_slavecount; cnt++)
        {
            printf("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n",
                cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits,
                ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc);
            printf(" Configured address: %x\n", ec_slave[cnt].configadr);
             //printf(" Outputs address: %i\n", ec_slave[cnt].outputs);
             //printf(" Inputs address: %i\n", ec_slave[cnt].inputs);

            for (j = 0; j < ec_slave[cnt].FMMUunused; j++)
            {
                printf(" FMMU%1d Ls:%x Ll:%4d Lsb:%d Leb:%d Ps:%x Psb:%d Ty:%x Act:%x\n", j,
                    (int)ec_slave[cnt].FMMU[j].LogStart, ec_slave[cnt].FMMU[j].LogLength, ec_slave[cnt].FMMU[j].LogStartbit,
                    ec_slave[cnt].FMMU[j].LogEndbit, ec_slave[cnt].FMMU[j].PhysStart, ec_slave[cnt].FMMU[j].PhysStartBit,
                    ec_slave[cnt].FMMU[j].FMMUtype, ec_slave[cnt].FMMU[j].FMMUactive);
            }
            printf(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
                ec_slave[cnt].FMMU0func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU3func);

        }
        ec_readstate();

        if (ec_slave[0].state == EC_STATE_OPERATIONAL)
        {
            printf("Operational state reached for all slaves.\n");
            wkc_count = 0;
            inOP = TRUE;


            /* cyclic loop, reads data from RT thread */
            for (i = 1; i <= 500; i++)
            {
                if (wkc >= expectedWKC)
                {
                    printf("Processdata cycle %4d, WKC %d , O:", rtcnt, wkc);

                    for (j = 0; j < oloop; j++)
                    {
                        printf(" %2.2x", *(ec_slave[0].outputs + j));
                    }

                    printf(" I:");
                    for (j = 0; j < iloop; j++)
                    {
                        printf(" %2.2x", *(ec_slave[0].inputs + j));
                    }
                    printf(" T:%lld\r", ec_DCtime);
                    needlf = TRUE;
                }
                osal_usleep(50000);

            }
            inOP = FALSE;
        }
        else
        {
            printf("Not all slaves reached operational state.\n");
            ec_readstate();
            for (i = 1; i <= ec_slavecount; i++)
            {
                if (ec_slave[i].state != EC_STATE_OPERATIONAL)
                {
                    printf("Slave %d State=0x%2.2x StatusCode=0x%4.4x : %s\n",
                        i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
                }
            }
        }
        /* stop RT thread */
        timeKillEvent(mmResult);

        printf("\nRequest init state for all slaves\n");
        ec_slave[0].state = EC_STATE_INIT;
        /* request INIT state for all slaves */
        ec_writestate(0);
        }
        else
        {
            printf("No slaves found!\n");
        }
        printf("End simple test, close socket\n");
        /* stop SOEM, close socket */
        ec_close();
    }
    else
    {
    printf("No socket connection on %s\nExcecute as root\n", ifname);
    }

}


这是PC连接到伺服上,运行程序反馈的信息:

img

请问是哪里出了问题,我应该从那几个方面改。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    抱歉,由于问题未给出,我无法给出任何解决方案。请提供具体的问题以获得帮助。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^