So I have managed to get it to work.  I thought I would put my solution
on this mailing list in case others have similar problems.

First, I made use the of the unofficial patches at
https://sourceforge.net/u/uecasm/etherlab-patches/ci/default/tree/#readme.
 With this I was able to do a clean build, and also build the e1000e
module.  And the program I posted last time didn't crash the computer,
and the slave went to OP.  But it also didn't work in that the motor
didn't move.

The key turned out to be waiting for the Parker Hannifin Drive to be
"ready."  And this is performed by the following code snippet:

int count = 3;

then inside the main loop:

    if (data_pointer[off_status_word] & 1) {
      data_pointer[off_ctl_word] |= 1;
      if (count > 0) count--;
    } else {
      printf("Waiting to start\n");
      data_pointer[off_ctl_word] &= ~1;
    }

    if (count <= 2) {
      data_pointer[off_op_mode] = 8;
    }

    if (count == 1) {
      printf("Starting");
      start_position = EC_READ_S32(data_pointer + off_act_pos);
    }

    if (count == 0) {
      position = start_position - 200000*(1-cos(t));
      printf("Setting position %g %d\n", t, position);
      EC_WRITE_S32(data_pointer+off_tgt_pos, position);
    }


The only problem with the attached code is that if I quit the resulting
program, and then restart it, the motor doesn't work.  I have to power
cycle the drive first.  I'll work on that next.

Of course, you should remove the printf statements when actually using
it.  it is just to show you that progress is happening.

Stephen


On 04/14/2018 07:01 PM, Montgomery-Smith, Stephen wrote:
> I have a Parker Hannifin P-Series drive, described here:
> https://www.parkermotion.com/products/Servo_Drives__7319__30_32_80_567_29.html.
>  
> I am able to make it work using the software package EC-Master by
> Acontis, but I would prefer to use open source software
> 
> I have tried both etherlab and SOEM without any success.  I am attaching
> the program I wrote for etherlab (also cutting and pasting it below in
> case the attachment is removed).  Actually, running this program can
> cause the computer to freeze.  I am using ubuntu-16.10 with linux kernel
> 4.10.  Any help or hints would be greatly appreciated.
> 
> The program enters the loop, and outputs values saying where the move
> should be moving to.  But the motor simply doesn't move.  The lights on
> the drive, and the output of "etherlab config" suggest the drive is
> still in the SAFE_OP state.  My guess is that there are some other
> initialization commands the drive needs, and if I understood how to
> properly read ENI files (the one used and generated by the Acontis
> software), that perhaps both this program, and the one I wrote in SOEM,
> would work.
> 
> I am using the generic etherlab module.  Unfortunately the e1000e module
> doesn't work on any linux kernel greater than 3.4, and I am having a
> really hard time getting sufficiently old versions of linux to work.
> 
> Also, does anyone know a good help forum for SOEM, so I can ask similar
> questions there about the SOEM program I wrote?
> 
> Thanks, Stephen
> 
#include <ecrt.h>
#include <pthread.h>
#include <sys/time.h>
#include <signal.h>
#include <math.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>

#define NSEC_PER_SEC (1000000000L)
#define TIMESPEC2NS(T) ((uint64_t) (T).tv_sec * NSEC_PER_SEC + (T).tv_nsec)
#define CYCLE_TIME 1000

pthread_mutex_t do_loop_cond_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t do_loop_cond = PTHREAD_COND_INITIALIZER;

struct timespec abstime;

ec_master_t *master;
ec_slave_config_t *slave0;
ec_domain_t *domain, *domain;

pthread_mutex_t pdo_mutex = PTHREAD_MUTEX_INITIALIZER;
uint8_t *data_pointer;
uint off_ctl_word, off_tgt_torque, off_tgt_pos, off_op_mode, off_t_probe_fn,
     off_status_word, off_act_torque, off_act_pos, off_act_pos_err, off_dig_input,
     off_op_mode_disp, off_comm_speed, off_op_speed, off_t_probe_st,
     off_t_probe_pos_pos_val;



int main() {
  int ret_val;

  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
    perror("mlockall failed");
    exit(1);
  }

  if ((master = ecrt_open_master(0)) == NULL) {
    printf("Unable to request master\n");
    exit(1);
  }

  if ((ret_val = ecrt_master_reserve(master)) < 0) {
    printf("Unable to reserve master %d\n", ret_val);
    exit(1);
  }

  if ((domain = ecrt_master_create_domain(master)) == NULL) {
    printf("Unable to create domain\n");
  }

  if ((slave0 = ecrt_master_slave_config(master, 0, 0, 0x9000089, 0x10001)) == NULL) {
    printf("Unable to request slave0\n");
    exit(1);
  }

  ec_pdo_entry_info_t pdo_entries_out[] = {{0x6040, 0, 16},
                                           {0x6071, 0, 16},
                                           {0x607a, 0, 32},
                                           {0x6060, 0, 8},
                                           {0x60b8, 0, 16}};
  ec_pdo_info_t pdos_out[] = {{0x1600, 5, pdo_entries_out}};
  ec_sync_info_t syncs_out[] = {{2, EC_DIR_OUTPUT, 1, pdos_out, EC_WD_DEFAULT}};
  if ((ret_val = ecrt_slave_config_pdos(slave0, 1, syncs_out)) < 0) {
    printf("Unable to configure output pdos %d\n", ret_val);
    exit(1);
  }

  ec_pdo_entry_info_t pdo_entries_in[] = {{0x6041, 0, 16},
                                          {0x6077, 0, 16},
                                          {0x6064, 0, 32},
                                          {0x60f4, 0, 32},
                                          {0x60fd, 0, 32},
                                          {0x6061, 0, 8},
                                          {0x2601, 0, 16},
                                          {0x2600, 0, 16},
                                          {0x60b9, 0, 16},
                                          {0x60ba, 0, 32}};
  ec_pdo_info_t pdos_in[] = {{0x1a00, 10, pdo_entries_in}};
  ec_sync_info_t syncs_in[] = {{3, EC_DIR_INPUT, 1, pdos_in, EC_WD_DEFAULT}};
  if ((ret_val = ecrt_slave_config_pdos(slave0, 1, syncs_in)) < 0) {
    printf("Unable to configure input pdos %d\n", ret_val);
    exit(1);
  }

  ec_pdo_entry_reg_t pdo_entry_regs[] = {
    {0, 0, 0x9000089, 0x10001, 0x6040, 0, &off_ctl_word, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6071, 0, &off_tgt_torque, NULL},
    {0, 0, 0x9000089, 0x10001, 0x607a, 0, &off_tgt_pos, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6060, 0, &off_op_mode, NULL},
    {0, 0, 0x9000089, 0x10001, 0x60b8, 0, &off_t_probe_fn, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6041, 0, &off_status_word, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6077, 0, &off_act_torque, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6064, 0, &off_act_pos, NULL},
    {0, 0, 0x9000089, 0x10001, 0x60f4, 0, &off_act_pos_err, NULL},
    {0, 0, 0x9000089, 0x10001, 0x60fd, 0, &off_dig_input, NULL},
    {0, 0, 0x9000089, 0x10001, 0x6061, 0, &off_op_mode_disp, NULL},
    {0, 0, 0x9000089, 0x10001, 0x2601, 0, &off_comm_speed, NULL},
    {0, 0, 0x9000089, 0x10001, 0x2600, 0, &off_op_speed, NULL},
    {0, 0, 0x9000089, 0x10001, 0x60b9, 0, &off_t_probe_st, NULL},
    {0, 0, 0x9000089, 0x10001, 0x60ba, 0, &off_t_probe_pos_pos_val, NULL},
    {0, 0, 0, 0, 0, 0, 0, 0}};

  if ((ret_val = ecrt_domain_reg_pdo_entry_list(domain, pdo_entry_regs)) != 0) {
    printf("Unable to register pdos %d\n", ret_val);
    exit(1);
  }

  ecrt_slave_config_dc(slave0, 0, 0, 0, 0, 0);

  if ((ret_val = ecrt_master_activate(master)) < 0) {
    printf("Unable to activate master %d\n", ret_val);
    exit(1);
  }

  if ((data_pointer = ecrt_domain_data(domain)) == NULL) {
    printf("Unable to get data pointer to domain\n");
    exit(1);
  }

  clock_gettime(CLOCK_REALTIME, &abstime);

  data_pointer[off_ctl_word] = 0xf;

  int32_t start_position;
  int32_t position;
  double t = 0;
  struct timespec time;
  int count = 3;

  while(1) {
    ecrt_master_receive(master);
    ecrt_domain_process(domain);

    if (data_pointer[off_status_word] & 1) {
      data_pointer[off_ctl_word] |= 1;
      if (count > 0) count--;
    } else {
      printf("Waiting to start\n");
      data_pointer[off_ctl_word] &= ~1;
    }

    if (count <= 2) {
      data_pointer[off_op_mode] = 8;
    }

    if (count == 1) {
      printf("Starting");
      start_position = EC_READ_S32(data_pointer + off_act_pos);
    }

    if (count == 0) {
      position = start_position - 200000*(1-cos(t));
      printf("Setting position %g %d\n", t, position);
      EC_WRITE_S32(data_pointer+off_tgt_pos, position);
    }

    ecrt_domain_queue(domain);
    ecrt_master_send(master);

    clock_gettime(CLOCK_REALTIME, &time);
    ecrt_master_application_time(master, TIMESPEC2NS(time));

    abstime.tv_nsec += CYCLE_TIME*1000; // Advance CYCLE_TIME us from prior time.
    while (abstime.tv_nsec >= NSEC_PER_SEC) {
      abstime.tv_nsec -= NSEC_PER_SEC;
      abstime.tv_sec += 1;
    }
    pthread_mutex_lock(&do_loop_cond_mutex);
    pthread_cond_timedwait(&do_loop_cond, &do_loop_cond_mutex, &abstime);
    pthread_mutex_unlock(&do_loop_cond_mutex);

    if (count == 0) t += CYCLE_TIME*1000.0/NSEC_PER_SEC;

  }
}
_______________________________________________
etherlab-users mailing list
etherlab-users@etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-users

Reply via email to