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