What Gavin said is true. Start with building/installing the master, and
have a look at the examples. Attached is a little C application that does
what you want with several slaves using stdin/stdout; it wasn't written by
me but a co-worker.

Connect it up to a Linux pipe and voila! you'll have a way to use another
language of your choice (we use Java and Python) to talk to the ethercat
hardware.

Good luck!



On Wed, Jun 4, 2014 at 5:43 PM, Gavin Lambert <gav...@compacsort.com> wrote:

> On 5 June 2014, quoth Javier:
> > I am a beginer and want start turning on a led in the EP2338 box from
> > ethercat master command line.
>
> Typically you cannot do that sort of thing from the command line, as
> without
> an application the devices will remain in PREOP state, and outputs are
> normally not allowed to activate until the device is in OP state.  (And
> even
> if you use the command to explicitly request OP state, devices with outputs
> will typically not remain in OP unless they're being updated cyclically by
> an application.)
>
> You will need to write an actual application in order to bring devices to
> OP
> and keep them there.  See the examples included with the library.
>
>
> _______________________________________________
> etherlab-users mailing list
> etherlab-users@etherlab.org
> http://lists.etherlab.org/mailman/listinfo/etherlab-users
>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#include "ecrt.h"

// Beckhoff product_codes
#define Beckhoff 0x00000002	// vendor id
#define EK1100 0x044c2c52	// bus coupler
#define EL1004 0x03ec3052	// 4 bit digital  input
#define EL1014 0x03f63052	// 4 bit digital  input
#define EL2004 0x07d43052	// 4 bit digital output
#define EL3102 0x0c1e3052	// 16 bit ADC +/- 10v
#define EL4132 0x10243052	// 16 bit DAC +/- 10v

// Beckhoff product data
static uint16_t none_index[]      = { 0 };
static uint8_t  none_subindex[]   = { 0 };
static uint16_t el1004_index[]    = { 0x6000, 0 };
static uint8_t  el1004_subindex[] = {      1, 0 };
static uint16_t el1014_index[]    = { 0x6000, 0 };
static uint8_t  el1014_subindex[] = {      1, 0 };
static uint16_t el2004_index[]    = { 0x7000, 0 };
static uint8_t  el2004_subindex[] = {      1, 0 };
static uint16_t el3102_index[]    = { 0x3101, 0x3102, 0 };
static uint8_t  el3102_subindex[] = {      2,      2, 0 };
static uint16_t el4132_index[]    = { 0x3001, 0x3002, 0 };
static uint8_t  el4132_subindex[] = {      1,      1, 0 };

// the modules on our bus in order
static uint32_t products[] = { EK1100, EL1004, EL2004, EL4132, EL3102, EL3102, EL3102, EL3102, 0 };

// the above data can be obtained by running
// "/opt/etherlab/bin/ethercat slaves" and
// "/opt/etherlab/bin/ethercat cstruct"

// reserve more than enough space
#define MAXSUBCHAN	4
#define MAXSLAVES	16
#define NSAMPLES	2000

// configuration procedure stores transfer information here
enum pdo_xfer_type {NONE=0, READU8, WRITEU8, READS16, WRITES16} pdo_xfer[MAXSLAVES+1][MAXSUBCHAN];
unsigned int pdo_offsets[MAXSLAVES+1][MAXSUBCHAN]; // offsets for PDO entries

// storage between parser and transfer procedure
short inputs[MAXSLAVES+1][MAXSUBCHAN][NSAMPLES];
short  input[MAXSLAVES+1][MAXSUBCHAN];
short output[MAXSLAVES+1][MAXSUBCHAN];
int ethercat_stop = 0;
int last_sample = NSAMPLES-1;

#define NUMMASTER	0	// master number
#define NUMALIAS	0	// no aliases

// globals shared between initialization and transfer procedures
ec_master_t *master = NULL;
ec_domain_t *domain = NULL;
uint8_t *domain_pd = NULL;

// configure all the slaves in the list and their pdo's
// this routine is en lieu of ecrt_domain_reg_pdo_entry_list() - skip
int ethercat_configure(ec_master_t *master, ec_domain_t *domain, uint32_t *product_codes)
{
    uint32_t *product_code;
    uint16_t position = 0;
    ec_slave_config_t *sc;
    uint16_t *index, *indexes;
    uint8_t *subindex, *subindexes;
    enum pdo_xfer_type xfer;
    int subchan;
    int ret;

    for (product_code = product_codes; *product_code; position++, product_code++) {
        if (! (sc = ecrt_master_slave_config(master, NUMALIAS, position, Beckhoff, *product_code))) {
            fprintf(stdout, "master_slave_config failed position %d, product %x\n", position, *product_code);
            return -1;
        }

	indexes    = none_index;
	subindexes = none_subindex;
        switch (*product_code) {
	case EL1004: indexes = el1004_index; subindexes = el1004_subindex; xfer = READU8; break;
	case EL2004: indexes = el2004_index; subindexes = el2004_subindex; xfer = WRITEU8; break;
	case EL3102: indexes = el3102_index; subindexes = el3102_subindex; xfer = READS16; break;
	case EL4132: indexes = el4132_index; subindexes = el4132_subindex; xfer = WRITES16; break;
        }

	for (index = indexes, subindex = subindexes, subchan=0; *index; index++, subindex++, subchan++) {
	    if ((ret = ecrt_slave_config_reg_pdo_entry(sc, *index, *subindex, domain, NULL)) < 0) {
                fprintf(stdout, "slave_config_reg_pdo_entry failed position %d, product %x, index %x subindex %d,\n", position, *product_code, *index, *subindex);
                return -1;
            }
	    pdo_offsets[position][subchan] = ret;
	    pdo_xfer[position][subchan] = xfer;
	}
    }
    return 0;
}

// initialize the hardware
int ethercat_initialize(void)
{
    master = ecrt_request_master(NUMMASTER);
    if (!master) {
        fprintf(stdout, "Unable to get requested master.\n");
        return -1;
    }
    domain = ecrt_master_create_domain(master);
    if (!domain) {
        fprintf(stdout, "Unable to create domain.\n");
        return -1;
    }
    if (ethercat_configure(master, domain, products)) {
	return -1;
    }
    if (ecrt_master_activate(master)) {
        fprintf(stdout,"activation failed.\n");
        return -1;
    }
    if (!(domain_pd = ecrt_domain_data(domain))) {
        fprintf(stdout,"Domain data initialization failed.\n");
        return -1;
    }

    // wait for the domain to come up
    int domain_up = 0;
    unsigned int j;
    for (j=0; j<1000 && !domain_up; j++) {
        ec_domain_state_t domain_state = {};

        ecrt_master_receive(master);
        ecrt_domain_process(domain);

        ecrt_domain_state(domain, &domain_state);
        if (domain_state.wc_state == EC_WC_COMPLETE) {
	    domain_up = 1;
        }

        ecrt_domain_queue(domain);
        ecrt_master_send(master);
        usleep(1000);
    }
    if (!domain_up) {
        fprintf(stdout,"Domain not up.\n");
        return -1;
    }
    return 0;
}

// thread to run the transfer cycles
void * ethercat_transfer(void * dummy)
{
    int position, subchan;
    uint8_t *domain_ptr;
    short *inputs_ptr;
    short *input_ptr;
    short *output_ptr;
    int next_sample;
    struct timeval prev, now;
    int adjust;
    int	new_sleep, prev_sleep;
    int	firsttime = 1;

    while (1) {
        ecrt_master_receive(master);
        ecrt_domain_process(domain);
        if (ethercat_stop)
            break;

	next_sample = last_sample+1;
	if (next_sample >= NSAMPLES)
	    next_sample = 0;

	for (position = 0; position <= MAXSLAVES; position++) {
	    for (subchan = 0; subchan < MAXSUBCHAN; subchan++) {
		domain_ptr = domain_pd + pdo_offsets[position][subchan];
		output_ptr = &output[position][subchan];
		input_ptr  =  &input[position][subchan];
		inputs_ptr = &inputs[position][subchan][next_sample];
		switch (pdo_xfer[position][subchan]) {
		case READU8:
		    *input_ptr = EC_READ_U8(domain_ptr) & 0x0F;
		    break;
		case WRITEU8:
		    EC_WRITE_U8(domain_ptr, *output_ptr & 0x0F);
		    break;
		case READS16:
		    *input_ptr = EC_READ_S16(domain_ptr);
		    *inputs_ptr = *input_ptr;
		    break;
		case WRITES16:
		    EC_WRITE_S16(domain_ptr, *output_ptr);
		    break;
		}
	    }
	}

	last_sample = next_sample;

        ecrt_domain_queue(domain);
        ecrt_master_send(master);

	if (firsttime) {
	    firsttime = 0;
	    gettimeofday(&now, NULL);
	    new_sleep = 1000;
	    usleep(new_sleep);
	} else {
	    prev_sleep = new_sleep;
	    prev.tv_sec = now.tv_sec;
	    prev.tv_usec = now.tv_usec;
	    gettimeofday(&now, NULL);
	    adjust = 1000 - ((now.tv_sec-prev.tv_sec)*1000000+(now.tv_usec-prev.tv_usec));
	    new_sleep = prev_sleep + adjust;
	}
	if ((0 <= new_sleep) && (new_sleep <= 1000)) {
	    usleep(new_sleep);
	} else {
	    new_sleep = 1000;
	    usleep(new_sleep);
	}
    }
}

// dump all the EL3102 samples
void dump (int nsamples) {
    int sample;
    int position, subchan;
    int next_sample;
    short value;
    short *inputs_ptr;
    int MAXSUBCHAN_EL3102 = 2;

    next_sample = last_sample - (nsamples-1);
    if (next_sample < 0)
        next_sample += NSAMPLES;
    if (next_sample >= NSAMPLES)
        next_sample -= NSAMPLES;

    for (sample = 0; sample < nsamples; sample++) {
	for (position = 0; position <= MAXSLAVES; position++) {
	    if (products[position] == EL3102) {
		for (subchan = 0; subchan < MAXSUBCHAN_EL3102; subchan++) {
		    inputs_ptr = &inputs[position][subchan][next_sample];
		    value = *inputs_ptr;
		    printf ("%hd ", value);
		}
	    }
	}
	printf ("\n");
	next_sample++;
	if (next_sample >= NSAMPLES)
	    next_sample -= NSAMPLES;
    }
}

// read and write on stdin/stdout to transfer data to/from ethercat slaves
// read  slave_pos sub_chan
// write slave_pos sub_chan data
// this is asynchronous - you may have to wait a bit for the data transfer

int main(int argc, char **argv)
{
    pthread_t thread_id;
    int address, subchan;
    int nsamples;
    short value;
    char line[120];

    if (ethercat_initialize() == -1)
	return -1;
    if (pthread_create (&thread_id, NULL, ethercat_transfer, NULL) < 0) {
        perror ("pthread_create");
        return -1;
    }
    printf ("pd: 0\n");	// old startup message
    fflush (stdout);

    // the parser
    while (fgets (line, sizeof(line), stdin)) {
        if (sscanf(line, "read %d %d", &address, &subchan) == 2) {
	    if (!(0 < address && address <= MAXSLAVES)) {
                printf ("address out of bounds\n");
	    } else if (!(0 <= subchan && subchan < MAXSUBCHAN)) {
                printf ("subchan out of bounds\n");
	    } else {
	        value =  input[address][subchan];
                printf ("%hd\n", value);
	    }
        } else if (sscanf(line, "write %d %d %hd", &address, &subchan, &value) == 3) {
	    if (!(0 < address && address <= MAXSLAVES)) {
                printf ("address out of bounds\n");
	    } else if (!(0 <= subchan && subchan < MAXSUBCHAN)) {
                printf ("subchan out of bounds\n");
	    } else {
	        output[address][subchan] = value;
                printf ("ok\n");
	    }
        } else if (sscanf(line, "dump %d", &nsamples) == 1) {
	    if (!(0 <= nsamples && nsamples <= NSAMPLES)) {
                printf ("nsamples out of bounds\n");
	    } else {
	        dump (nsamples);
	    }
        } else {
            printf ("parse error\n");
        }
        fflush (stdout);
    }

    ethercat_stop = 1;
    if (pthread_join (thread_id, NULL) < 0) {
        perror ("pthread_join:");
        return -1;
    }
    ecrt_release_master(master);
    return 0;
}
_______________________________________________
etherlab-users mailing list
etherlab-users@etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-users

Reply via email to