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