Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ethercat - soem Slave 1 State=0x14 StatusCode=0x0027 : Freerun not supported #879

Open
bao1ong opened this issue Dec 16, 2024 · 0 comments

Comments

@bao1ong
Copy link

bao1ong commented Dec 16, 2024

Hello everyone, I need help! I used a Linux environment to drive Soem1.3.1, and I modified the code based on Simple_test. c. This code was once able to operate the position mode of the motor smoothly on an Envision motor, but after changing to SV660n, it has not been able to solve the error related to SDO writing: ERROR: SDO write failed for slave 1, index 0x1600, subindex 0x03, I guess this is also the reason why: Slave 1 State=0x14 StatusCode=0x0027 : Freerun not supported。

This is my Simple_test c:
`//移植自1.4 将ethercat.h暂展开
/*

  • Licensed under the GNU General Public License version 2 with exceptions. See
  • LICENSE file in the project root for full license information
    */

/** \file

  • \brief
  • Headerfile for all ethercat headers
    */

#ifndef _EC_ETHERCAT_H
#define _EC_ETHERCAT_H

#include "ethercattype.h"
#include "nicdrv.h"
#include "ethercatbase.h"
#include "ethercatmain.h"
#include "ethercatdc.h"
#include "ethercatcoe.h"
#include "ethercatfoe.h"
#include "ethercatsoe.h"
//#include "ethercateoe.h"
#include "ethercatconfig.h"
#include "ethercatprint.h"

#endif /* _EC_ETHERCAT_H */

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <signal.h>

#define EC_TIMEOUTMON 500
#define DEBUG 1 // 设置为1以启用调试,设置为0则关闭调试

// 定义IO映射
char IOmap[12800];
OSAL_THREAD_HANDLE thread1;
int expectedWKC;
boolean needlf;
volatile int wkc;
boolean inOP;
uint8 currentgroup = 0;

// 全局变量,用于控制主循环的终止
volatile sig_atomic_t stop = 0;

typedef struct PACKED {
uint16 controlword; // 6040
int32 targetPostion; // 607A
int32 targetSpeed; // 60FF
int16 targetnu;
} PDO_Output;

typedef struct PACKED {
uint16 statusWord; // 6041
int32 actualPostion; // 6064
int32 actualSpeed; // 606C
int16 actualnu;
} PDO_Input;

PDO_Output *outputs1;
PDO_Input *inputs1;

// 调试打印函数
void debug_print(const char* msg) {
if (DEBUG) {
printf("%s\n", msg);
}
}

// 信号处理函数
void handle_sigint(int sig)
{
(void)sig; // 声明参数已被使用
stop = 1;
}

// SDO写操作的错误检查(增加详细的错误信息)
int sdo_write_safe(uint16 slave, uint16 index, uint8 subindex, void *data, int size) {
int ret = ec_SDOwrite(slave, index, subindex, FALSE, size, data, EC_TIMEOUTRXM);

if (ret) {
    return 0;  // 成功
} else {
    // 提供详细的错误信息
    printf("ERROR: SDO write failed for slave %d, index 0x%04X, subindex 0x%02X\n", slave, index, subindex);
    debug_print("Additional SDO write failure details...");
    return -1;  // 失败
}

}

// 设置PDO映射
void INVT_DA180_setup(uint16 slave) {
uint8 u8val;
uint16 u16val;
uint32 u32val;
short i16val;

// PDO 映射配置
u8val = 0;
if (sdo_write_safe(slave, 0x1c12, 0x00, &u8val, sizeof(u8val)) != 0) return;
if (sdo_write_safe(slave, 0x1600, 0x00, &u8val, sizeof(u8val)) != 0) return;

u32val = 0x60400010;
if (sdo_write_safe(slave, 0x1600, 0x01, &u32val, sizeof(u32val)) != 0) return;
u32val = 0x607A0020;
if (sdo_write_safe(slave, 0x1600, 0x02, &u32val, sizeof(u32val)) != 0) return;
u32val = 0x60ff0030;
if (sdo_write_safe(slave, 0x1600, 0x03, &u32val, sizeof(u32val)) != 0) return;

u8val = 3;
if (sdo_write_safe(slave, 0x1600, 0x00, &u8val, sizeof(u8val)) != 0) return;

u16val = 0x1600;
if (sdo_write_safe(slave, 0x1c12, 0x01, &u16val, sizeof(u16val)) != 0) return;
u8val = 1;
if (sdo_write_safe(slave, 0x1c12, 0x00, &u8val, sizeof(u8val)) != 0) return;

u8val = 0;
if (sdo_write_safe(slave, 0x1c13, 0x00, &u8val, sizeof(u8val)) != 0) return;
u8val = 0;
if (sdo_write_safe(slave, 0x1A00, 0x00, &u8val, sizeof(u8val)) != 0) return;

u32val = 0x60410010;
if (sdo_write_safe(slave, 0x1A00, 0x01, &u32val, sizeof(u32val)) != 0) return;
u32val = 0x60640020;
if (sdo_write_safe(slave, 0x1A00, 0x02, &u32val, sizeof(u32val)) != 0) return;
u32val = 0x606c0030;
if (sdo_write_safe(slave, 0x1600, 0x03, &u32val, sizeof(u32val)) != 0) return;

u8val = 3;
if (sdo_write_safe(slave, 0x1A00, 0x00, &u8val, sizeof(u8val)) != 0) return;

u16val = 0x1A00;
if (sdo_write_safe(slave, 0x1c13, 0x01, &u16val, sizeof(u16val)) != 0) return;
u8val = 1;
if (sdo_write_safe(slave, 0x1c13, 0x00, &u8val, sizeof(u8val)) != 0) return;

u8val = 8;
if (sdo_write_safe(slave, 0x6060, 0x00, &u8val, sizeof(u8val)) != 0) return;

i16val = 300;
if (sdo_write_safe(slave, 0x6072, 0x00, &i16val, sizeof(i16val)) != 0) return;

i16val = 100;
if (sdo_write_safe(slave, 0x6071, 0x00, &i16val, sizeof(i16val)) != 0) return;

}

// EtherCAT 状态控制
void EtherCAT_ctrl_state(void) {
switch (outputs1->controlword) {
case 0:
outputs1->controlword = 6; // Shutdown
break;

    case 6:
        outputs1->controlword = 7;  // Ready to switch on
        break;

    case 7:
        outputs1->targetPostion = inputs1->actualPostion;
        outputs1->controlword = 0x0f;  // Enable operation
        break;

    case 0x0f:
        break;

    default:
        outputs1->controlword = 6;  // Shutdown
        break;
}

}

void simpletest(char *ifname) {
printf("\ntest_for_onlyoneslave\n");
int i,j, oloop, iloop, chk;
needlf = FALSE;
inOP = FALSE;

printf("Starting simple test\n");

// 初始化SOEM,绑定socket到指定接口
if (ec_init(ifname)) {
    debug_print("ec_init succeeded.");

    // 查找并自动配置从站
    if (ec_config_init(FALSE) > 0) {
        printf("%d slaves found and configured.\n", ec_slavecount);

        INVT_DA180_setup(1); //// 只配置从站1

        printf("Enter to SafeOP");
        getchar();

        ec_config_map(&IOmap);
        ec_configdc();


        ec_dcsync0(1, 1, 4000 * 1000, 2000 * 1000);

        printf("Slaves mapped, state to SAFE_OP.\n");

        // 等待所有从站到达SAFE_OP状态
        printf("Enter to OP");
        getchar();
        ec_statecheck(1, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);

/*
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;

*/

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

        iloop = ec_slave[1].Ibytes;
        if ((iloop == 0) && (ec_slave[1].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("Calculated workcounter %d\n", expectedWKC);
        ec_slave[1].state = EC_STATE_OPERATIONAL;

        // 发送有效的过程数据,保持从站的输出
        ec_send_processdata();
        ec_receive_processdata(EC_TIMEOUTRET);

        // 请求所有从站进入OP状态
        ec_writestate(1);
        //ec_writestate(2);
        printf("Enter to EX Data");
     	getchar();
        
        chk = 200;
     /* wait for all slaves to reach OP state */
     do
     {
        ec_send_processdata();
        ec_receive_processdata(EC_TIMEOUTRET);
        ec_statecheck(1, EC_STATE_OPERATIONAL, 50000);
        //ec_statecheck(2, EC_STATE_OPERATIONAL, 50000);
     } while (chk-- && (ec_slave[1].state != EC_STATE_OPERATIONAL));
     if (ec_slave[1].state == EC_STATE_OPERATIONAL)
     {
        printf("Operational state reached for the only slave.\n");
        inOP = TRUE;

        printf("count = %d\n", ec_slavecount);

        outputs1 = (PDO_Output *)ec_slave[1].outputs;
        inputs1  = (PDO_Input *)ec_slave[1].inputs;


        /* cyclic loop */


        for (i = 1; i <= 10000; i++)
        {
           ec_send_processdata();
           wkc = ec_receive_processdata(EC_TIMEOUTRET);
        	// outputs1->targetPostion = (i*10)%10000;
      		//outputs1->targetPostion = 2000;
           outputs1->targetnu = 300;
           
           printf("n =========== 1 \n");
        	if (outputs1->controlword == 0x0f) {
    			outputs1->targetPostion += 10;  // 设置目标位?
				printf("haven on 0x0f if\n");				 
			}
			if(outputs1->targetPostion <10000){
				outputs1->targetPostion += 5;
				printf("outputs1->targetPostion <10000 & target ++ 5\n");
			}
			else{
				outputs1->targetPostion = 0;
			}
				
           // 打印调试信息
			printf("Cycle: %d, Target Position: %d\n", i, outputs1->targetPostion);
			printf("Actual position: %d\n", inputs1->actualPostion);
            printf("inputs1->actualPostion = %d\n",inputs1->actualPostion);
            printf("inputs1->actualSpeed = %d\n",inputs1->actualSpeed);
            printf("Controlword: 0x%04X\n", outputs1->controlword);
            EtherCAT_ctrl_state();
            usleep(10000);  // 每10ms执行一次任务


           if (wkc >= expectedWKC)
           {
              printf("Processdata cycle %4d, WKC %d , O:", i, 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:%" PRId64 "\r", ec_DCtime);
              needlf = TRUE;
           }
           /* 
           // 检查是否需要停止
			if (stop)
			{
			    printf("\nCtrl+C pressed, terminating program...\n");
			    break;
			}
			// 程序终止前,将从机状态设置回INIT
			printf("\nRequest init state for all slaves\n");
			ec_slave[1].state = EC_STATE_INIT;
			ec_writestate(1);
			
			// 等待从机状态更新
			ec_statecheck(1, EC_STATE_INIT, EC_TIMEOUTMON * 2);
			
			// 关闭SOEM连接
			ec_close();*/
        }
        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));
           }
        }
     }
     printf("\nRequest init state for all slaves\n");
     ec_slave[1].state = EC_STATE_INIT;
     //原: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);
}
}

OSAL_THREAD_FUNC ecatcheck(void ptr)
{
int slave;
(void)ptr; /
Not used */

while (1)
{
if (inOP && ((wkc < expectedWKC) || ec_group[currentgroup].docheckstate))
{
if (needlf)
{
needlf = FALSE;
printf("\n");
}
/* one ore more slaves are not responding /
ec_group[currentgroup].docheckstate = FALSE;
ec_readstate();
for (slave = 1; slave <= ec_slavecount; slave++)
{
if ((ec_slave[slave].group == currentgroup) && (ec_slave[slave].state != EC_STATE_OPERATIONAL))
{
ec_group[currentgroup].docheckstate = TRUE;
if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))
{
printf("ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n", slave);
ec_slave[slave].state = (EC_STATE_SAFE_OP + EC_STATE_ACK);
ec_writestate(slave);
}
else if (ec_slave[slave].state == EC_STATE_SAFE_OP)
{
printf("WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n", slave);
ec_slave[slave].state = EC_STATE_OPERATIONAL;
ec_writestate(slave);
}
//else if (ec_slave[slave].state > EC_STATE_NONE)
else if (ec_slave[slave].state > 0)
{
if (ec_reconfig_slave(slave, EC_TIMEOUTMON))
{
ec_slave[slave].islost = FALSE;
printf("MESSAGE : slave %d reconfigured\n", slave);
}
}
else if (!ec_slave[slave].islost)
{
/
re-check state */
ec_statecheck(slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET);
//if (ec_slave[slave].state == EC_STATE_NONE)
if (ec_slave[slave].state == 0)
{
ec_slave[slave].islost = TRUE;
printf("ERROR : slave %d lost\n", slave);
}
}
}
if (ec_slave[slave].islost)
{
//if (ec_slave[slave].state == EC_STATE_NONE)
if (ec_slave[slave].state == 0)
{
if (ec_recover_slave(slave, EC_TIMEOUTMON))
{
ec_slave[slave].islost = FALSE;
printf("MESSAGE : slave %d recovered\n", slave);
}
}
else
{
ec_slave[slave].islost = FALSE;
printf("MESSAGE : slave %d found\n", slave);
}
}
}
if (!ec_group[currentgroup].docheckstate)
printf("OK : all slaves resumed OPERATIONAL.\n");
}
osal_usleep(10000);
}
}

int main(int argc, char *argv[])
{
printf("SOEM (Simple Open EtherCAT Master)\nSimple test\n");

// 注册信号处理器
//signal(SIGINT, handle_sigint);

if (argc > 1)
{
/* create thread to handle slave error handling in OP */
// pthread_create( &thread1, NULL, (void ) &ecatcheck, (void) &ctime);
osal_thread_create(&thread1, 128000, &ecatcheck, (void )&ctime);
printf("EtherCAT Master initializing on %s\n", argv[1]);
/
start cyclic part */
simpletest(argv[1]);
}
else
{
printf("Usage: simple_test ifname1\nifname = eth0 for example\n");
}

printf("End program\n");
return (0);
}`

And here is my print debugging information:
3a54595942aa5a8beddcd0a7c3c8d06

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant