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 <[email protected]> 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
> [email protected]
> 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
[email protected]
http://lists.etherlab.org/mailman/listinfo/etherlab-users