<div dir="ltr">Hey Andreas,<div><br></div><div>Thanks for replying. I have used the Denali XCR-E motor drive by Novanta. The same drive always works in my system and never requires a power cycle for it to work. So I'm assuming this is not the case here. It is not written in the manuals either, as far as I have seen.</div><div><br></div><div>Would you like some data to be able to help better?</div><div><br></div><div>Here is the code:</div><div><br></div><div>const static ec_pdo_entry_reg_t domain1_regs[] = {<br>    {drivePos, DRIVE1, 0x6040, 0x00, &pitch.rx_pdo.control_word},        //RXPDO<br>    {drivePos, DRIVE1, 0x607a, 0x00, &pitch.rx_pdo.position_setpoint},<br>    {drivePos, DRIVE1, 0x60ff, 0x00, &pitch.rx_pdo.velocity_setpoint},   <br>    {drivePos, DRIVE1, 0x6060, 0x00, &pitch.rx_pdo.op_mode},             //TXPDO<br>    {drivePos, DRIVE1, 0x6041, 0x00, &pitch.tx_pdo.status_word},<br>    {drivePos, DRIVE1, 0x6064, 0x00, &pitch.tx_pdo.actual_position},<br>    {drivePos, DRIVE1, 0x606c, 0x00, &pitch.tx_pdo.actual_velocity},<br>    {drivePos, DRIVE1, 0x6061, 0x00, &pitch.tx_pdo.op_mode_display},<br>    {}<br>};<br><br>ec_pdo_entry_info_t slave_0_pdo_entries[] = {<br>    {0x6040, 0x00, 16}, /* Control Word */<br>    {0x607a, 0x00, 32}, /* Position set-point */<br>    {0x60ff, 0x00, 32}, /* Velocity set-point */<br>    {0x6060, 0x00, 8}, /* Operation mode */<br>    {0x6041, 0x00, 16}, /* Status Word */<br>    {0x6064, 0x00, 32}, /* Actual position */<br>    {0x606c, 0x00, 32}, /* Actual velocity */<br>    {0x6061, 0x00, 8},  /*Mode of op display*/<br>};<br><br>static ec_pdo_info_t slave_0_pdos[] = <br>{<br>        {0x1600, 4, slave_0_pdo_entries + 0},<br> {0x1a00, 4, slave_0_pdo_entries + 4},<br>};<br><br>/* Initialise the sync manager */<br>ec_sync_info_t slave_0_syncs[] = {<br><br>    {2, EC_DIR_OUTPUT, 1, slave_0_pdos + 0},<br>    {3, EC_DIR_INPUT, 1, slave_0_pdos + 1},<br>    {0xff}<br>};<br>/*****************************************************************************/<br><br>void check_domain1_state(void)  /*Check the domain state and print the working counter */<br>{<br>    ec_domain_state_t ds;<br><br>    ecrt_domain_state(domain1, &ds);<br><br>    if (ds.working_counter != domain1_state.working_counter) {<br>        printf("Domain1: WC %u.\n", ds.working_counter);<br>    }<br>    if (ds.wc_state != domain1_state.wc_state) {<br>        printf("Domain1: State %u.\n", ds.wc_state);<br>    }<br><br>    domain1_state = ds;<br>}<br><br>/*****************************************************************************/<br><br>void check_master_state(void)   /* check the master state and print */<br>{<br>    ec_master_state_t ms;<br><br>    ecrt_master_state(master, &ms);<br><br>    if (ms.slaves_responding != master_state.slaves_responding) {<br>        printf("%u slave(s).\n", ms.slaves_responding);<br>    }<br>    if (ms.al_states != master_state.al_states) {<br>        printf("AL states: 0x%02X.\n", ms.al_states);<br>    }<br>    if (ms.link_up != master_state.link_up) {<br>        printf("Link is %s.\n", ms.link_up ? "up" : "down");<br>    }<br><br>    master_state = ms;<br>}<br><br>/*****************************************************************************/<br><br>void check_slave_config_states(void)    /* */<br>{<br>    ec_slave_config_state_t s;<br><br>    ecrt_slave_config_state(sc_in, &s);<br><br>    if (s.al_state != sc_in_state.al_state) {<br>        printf("AnaIn: State 0x%02X.\n", s.al_state);<br>    }<br>    if (s.online != sc_in_state.online) {<br>        printf("AnaIn: %s.\n", s.online ? "online" : "offline");<br>    }<br>    if (s.operational != sc_in_state.operational) {<br>        printf("AnaIn: %soperational.\n", s.operational ? "" : "Not ");<br>    }<br><br>    sc_in_state = s;<br>}<br><br>/************************************************************************************************************/<br><br>void move_axis_to(Axis axs, long pos){<br>    <br>    axs.move_setpoint = pos;<br><br>    axs.status =EC_READ_U16(domain1_pd + axs.tx_pdo.status_word);<br>    axs.position = EC_READ_S32(domain1_pd + axs.tx_pdo.actual_position);<br>    axs.opm_d = EC_READ_S8(domain1_pd + axs.tx_pdo.op_mode_display);<br><br>    if((axs.status & 0x0040) == 0x0040){<br>    EC_WRITE_U16(domain1_pd + axs.rx_pdo.control_word, 0x0006);<br>    printf("switch on Disabled: %lx \n", axs.status);<br>   }<br>   else if((axs.status & 0x002f) == 0x0021){<br>    EC_WRITE_U16(domain1_pd + axs.rx_pdo.control_word, 0x0007);<br>    printf("Ready to switch on: %lx \n", axs.status);<br>   }<br>   else if((axs.status & 0x002f) == 0x0023){<br>    EC_WRITE_U16(domain1_pd + axs.rx_pdo.control_word, 0x000f);<br>    EC_WRITE_S8(domain1_pd + axs.rx_pdo.op_mode, 8);<br>    printf("Switched on: %lx \n", axs.status);<br>   }<br>   else if((axs.status & 0x002f) == 0x0027){<br>    printf("OP Enabled: %lx | ", axs.status);<br>    if((axs.status & 0x4000) == 0x4000){<br>        printf("OP: IAP | ");<br>        printf("OPMD = %ld | ", axs.opm_d);<br>        printf("AP: %ld | ", axs.position);<br>        printf("Setpoint: %ld\n | ", axs.move_setpoint);        <br>        EC_WRITE_S32(domain1_pd + axs.rx_pdo.position_setpoint, axs.move_setpoint);<br>    }<br>   }<br>   else if((axs.status&0x0007) == 0x0007){<br>    printf("Quick Stop Active: %lx \n", axs.status);<br>   }<br>   else if((axs.status & 0x000f) == 0x000f){<br>    printf("Fault reaction active: %lx \n", axs.status);<br>   }<br>   else if((axs.status & 0x0008) == 0x0008){<br>    printf("Fault recieved: %lx \n", axs.status);<br>   }<br>}<br>/*****************************************************************************/<br><br>void cyclic_task()<br>{<br>    ecrt_master_receive(master);<br>    ecrt_domain_process(domain1);<br><br>    if (counter) {<br>        counter--;<br>    } else { // do this at 1 Hz<br>        counter = FREQUENCY;<br><br>        // calculate new process data<br>        blink = !blink;<br><br>        // check for master state (optional)<br>        check_master_state();<br>        // check_domain1_state();<br>        check_slave_config_states();<br>    }<br><br>    move_axis_to(pitch, desired_pos);<br><br>    // send process data<br>    ecrt_domain_queue(domain1);<br>    ecrt_master_send(master);<br>}<br><br>/****************************************************************************/<br><br>void stack_prefault(void)<br>{<br>    unsigned char dummy[MAX_SAFE_STACK];<br><br>    memset(dummy, 0, MAX_SAFE_STACK);<br>}<br><br>/****************************************************************************/<br><br>int main(int argc, char **argv)<br>{<br>    // move_setpoint = atoi(argv[1]);<br><br>    struct timespec wakeup_time;<br>    int ret = 0;<br><br>    read_timeout.tv_sec = 0;<br>    read_timeout.tv_usec = 100;<br>    <br>    client_struct_length = sizeof(client_addr);<br>    memset(setpoint, '\0', sizeof(setpoint));<br>    // Create UDP socket:<br>    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);<br>    setsockopt(socket_desc, SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof read_timeout);<br>    <br>    if(socket_desc < 0){<br>        printf("Error while creating socket\n");<br>        return -1;<br>    }<br><br>    server_addr.sin_family = AF_INET;<br>    server_addr.sin_port = htons(2000);<br>    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");<br><br>    if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){<br>        printf("Couldn't bind to the port\n");<br>        return -1;<br>    }<br><br>    master = ecrt_request_master(0);<br>    if (!master) {<br>        return -1;<br>    }<br><br>    domain1 = ecrt_master_create_domain(master);<br>    if (!domain1) {<br>        return -1;<br>    }<br><br>    if (!(sc_in = ecrt_master_slave_config(<br>                    master, drivePos, DRIVE1))) {<br>        fprintf(stderr, "Failed to get slave configuration.\n");<br>        return -1;<br>    }<br><br>    printf("Configuring PDOs...\n");<br>    if (ecrt_slave_config_pdos(sc_in, EC_END, slave_0_syncs)) {<br>        fprintf(stderr, "Failed to configure PDOs.\n");<br>        return -1;<br>    }<br><br>    if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {<br>        fprintf(stderr, "PDO entry registration failed!\n");<br>        return -1;<br>    }<br><br>    ecrt_slave_config_watchdog(sc_in, 0, 0);<br><br><br>    printf("Activating master...\n");<br>    if (ecrt_master_activate(master)) {<br>        return -1;<br>    }<br><br>    if (!(domain1_pd = ecrt_domain_data(domain1))) {<br>        return -1;<br>    }<br><br>    /* Set priority */<br><br>    struct sched_param param = {};<br>    param.sched_priority = sched_get_priority_max(SCHED_FIFO);<br><br>    printf("Using priority %i.", param.sched_priority);<br>    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {<br>        perror("sched_setscheduler failed");<br>    }<br><br>    // ecrt_master_set_send_interval(master, 1000);<br><br>    /* Lock memory */<br><br>    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {<br>        fprintf(stderr, "Warning: Failed to lock memory: %s\n",<br>                strerror(errno));<br>    }<br><br>    stack_prefault();<br><br>    printf("Starting RT task with dt=%u ns.\n", PERIOD_NS);<br><br>    clock_gettime(CLOCK_MONOTONIC, &wakeup_time);<br>    wakeup_time.tv_sec += 1; /* start in future */<br>    wakeup_time.tv_nsec = 0;<br><br><br>    while (1) {<br>        <br>        ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,<br>                &wakeup_time, NULL);<br>        if (ret) {<br>            fprintf(stderr, "clock_nanosleep(): %s\n", strerror(ret));<br>            break;<br>        }<br><br>        if (recvfrom(socket_desc, setpoint, sizeof(setpoint), 0,<br>         (struct sockaddr*)&client_addr, &client_struct_length) < 0){<br>        // printf("Couldn't receive\n");<br>        }<br>        desired_pos = setpoint[0];<br>        cyclic_task();<br><br>        wakeup_time.tv_nsec += PERIOD_NS;<br>        while (wakeup_time.tv_nsec >= NSEC_PER_SEC) {<br>            wakeup_time.tv_nsec -= NSEC_PER_SEC;<br>            wakeup_time.tv_sec++;<br>        }<br>    }<br>    close(socket_desc);<br>    return ret;<br>}<br></div></div>